WwiseFileHandlerBase.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /*******************************************************************************
  2. The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
  3. Technology released in source code form as part of the game integration package.
  4. The content of this file may not be used without valid licenses to the
  5. AUDIOKINETIC Wwise Technology.
  6. Note that the use of the game engine is subject to the Unreal(R) Engine End User
  7. License Agreement at https://www.unrealengine.com/en-US/eula/unreal
  8. License Usage
  9. Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
  10. this file in accordance with the end user license agreement provided with the
  11. software or, alternatively, in accordance with the terms contained
  12. in a written agreement between you and Audiokinetic Inc.
  13. Copyright (c) 2023 Audiokinetic Inc.
  14. *******************************************************************************/
  15. #include "Wwise/WwiseFileHandlerBase.h"
  16. #include "Wwise/WwiseIOHook.h"
  17. #include "Wwise/WwiseStreamableFileStateInfo.h"
  18. #include "Wwise/Stats/FileHandler.h"
  19. #include "Wwise/Stats/AsyncStats.h"
  20. #include "Misc/ScopeRWLock.h"
  21. #include <inttypes.h>
  22. FWwiseFileHandlerBase::FWwiseFileHandlerBase()
  23. {
  24. }
  25. FWwiseFileHandlerBase::~FWwiseFileHandlerBase()
  26. {
  27. FRWScopeLock StateLock(FileStatesByIdLock, FRWScopeLockType::SLT_Write);
  28. if (UNLIKELY(FileStatesById.Num() > 0))
  29. {
  30. UE_LOG(LogWwiseFileHandler, Log, TEXT("Closing FileHandler with remaining %" PRIu32 " FileStates. Leaking."), FileStatesById.Num());
  31. for (auto& State : FileStatesById)
  32. {
  33. // Locking in memory the file states
  34. new FWwiseFileStateSharedPtr(State.Value);
  35. }
  36. }
  37. }
  38. void FWwiseFileHandlerBase::OpenStreaming(AkAsyncFileOpenData* io_pOpenData)
  39. {
  40. FWwiseAsyncCycleCounter OpCycleCounter(GET_STATID(STAT_WwiseFileHandlerIORequestLatency));
  41. IncrementFileStateUseAsync(io_pOpenData->fileID, EWwiseFileStateOperationOrigin::Streaming,
  42. [ManagingTypeName = GetManagingTypeName(), io_pOpenData]
  43. {
  44. UE_LOG(LogWwiseFileHandler, Error, TEXT("Trying to open streaming for unknown %s %" PRIu32), ManagingTypeName, io_pOpenData->fileID);
  45. return FWwiseFileStateSharedPtr{};
  46. },
  47. [this, io_pOpenData, OpCycleCounter = MoveTemp(OpCycleCounter)](const FWwiseFileStateSharedPtr& InFileState, bool bInResult) mutable
  48. {
  49. OpCycleCounter.Stop();
  50. SCOPED_WWISEFILEHANDLER_EVENT_F_3(TEXT("FWwiseFileHandlerBase::OpenStreaming %s Async"), GetManagingTypeName());
  51. AKRESULT Result = GetOpenStreamingResult(io_pOpenData);
  52. if (Result == AK_Success && UNLIKELY(!bInResult))
  53. {
  54. Result = AK_UnknownFileError;
  55. }
  56. if (LIKELY(Result == AK_Success))
  57. {
  58. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("Succeeded opening %" PRIu32 " for streaming"), io_pOpenData->fileID);
  59. io_pOpenData->pCallback(io_pOpenData, Result);
  60. }
  61. else
  62. {
  63. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("Failed opening %" PRIu32 " for streaming. Doing callback later."), io_pOpenData->fileID);
  64. FFunctionGraphTask::CreateAndDispatchWhenReady([io_pOpenData, Result]
  65. {
  66. SCOPED_WWISEFILEHANDLER_EVENT_3(TEXT("FWwiseFileHandlerBase::OpenStreaming Failure Async"));
  67. io_pOpenData->pCallback(io_pOpenData, Result);
  68. });
  69. }
  70. });
  71. }
  72. AKRESULT FWwiseFileHandlerBase::GetOpenStreamingResult(AkAsyncFileOpenData* io_pOpenData)
  73. {
  74. FWwiseAsyncCycleCounter OpCycleCounter(GET_STATID(STAT_WwiseFileHandlerIORequestLatency));
  75. FWwiseFileStateSharedPtr State;
  76. {
  77. FRWScopeLock StateLock(FileStatesByIdLock, FRWScopeLockType::SLT_ReadOnly);
  78. const auto* StatePtr = FileStatesById.Find(io_pOpenData->fileID);
  79. if (UNLIKELY(!StatePtr || !StatePtr->IsValid()))
  80. {
  81. UE_LOG(LogWwiseFileHandler, Error, TEXT("Could not open file %" PRIu32 " for streaming: File wasn't initialized prior to OpenStreaming."), io_pOpenData->fileID);
  82. return AK_FileNotFound;
  83. }
  84. State = *StatePtr;
  85. }
  86. AKRESULT Result = AK_Success;
  87. if (auto* StreamableFileStateInfo = State->GetStreamableFileStateInfo())
  88. {
  89. io_pOpenData->pFileDesc = StreamableFileStateInfo->GetFileDesc();
  90. }
  91. else
  92. {
  93. UE_LOG(LogWwiseFileHandler, Error, TEXT("Could not open file %" PRIu32 " for streaming: Could not get AkFileDesc."), io_pOpenData->fileID);
  94. Result = AK_UnknownFileError;
  95. }
  96. return Result;
  97. }
  98. void FWwiseFileHandlerBase::CloseStreaming(uint32 InShortId, FWwiseFileState& InFileState)
  99. {
  100. return DecrementFileStateUseAsync(InShortId, &InFileState, EWwiseFileStateOperationOrigin::Streaming, []{});
  101. }
  102. void FWwiseFileHandlerBase::IncrementFileStateUseAsync(uint32 InShortId, EWwiseFileStateOperationOrigin InOperationOrigin,
  103. FCreateStateFunction&& InCreate, FIncrementStateCallback&& InCallback)
  104. {
  105. FileHandlerExecutionQueue.Async([this, InShortId, InOperationOrigin, InCreate = MoveTemp(InCreate), InCallback = MoveTemp(InCallback)]() mutable
  106. {
  107. IncrementFileStateUse(InShortId, InOperationOrigin, MoveTemp(InCreate), MoveTemp(InCallback));
  108. });
  109. }
  110. void FWwiseFileHandlerBase::DecrementFileStateUseAsync(uint32 InShortId, FWwiseFileState* InFileState, EWwiseFileStateOperationOrigin InOperationOrigin, FDecrementStateCallback&& InCallback)
  111. {
  112. FileHandlerExecutionQueue.Async([this, InShortId, InFileState, InOperationOrigin, InCallback = MoveTemp(InCallback)]() mutable
  113. {
  114. DecrementFileStateUse(InShortId, InFileState, InOperationOrigin, MoveTemp(InCallback));
  115. });
  116. }
  117. void FWwiseFileHandlerBase::IncrementFileStateUse(uint32 InShortId, EWwiseFileStateOperationOrigin InOperationOrigin, FCreateStateFunction&& InCreate, FIncrementStateCallback&& InCallback)
  118. {
  119. SCOPED_WWISEFILEHANDLER_EVENT_F_3(TEXT("FWwiseFileHandlerBase::IncrementFileStateUse %s"), GetManagingTypeName());
  120. FWwiseFileStateSharedPtr State;
  121. {
  122. FRWScopeLock StateLock(FileStatesByIdLock, FRWScopeLockType::SLT_ReadOnly);
  123. if (const auto* StatePtr = FileStatesById.Find(InShortId))
  124. {
  125. State = *StatePtr;
  126. }
  127. }
  128. if (!State.IsValid())
  129. {
  130. FRWScopeLock StateLock(FileStatesByIdLock, FRWScopeLockType::SLT_Write);
  131. if (const auto* StatePtr = FileStatesById.Find(InShortId))
  132. {
  133. State = *StatePtr;
  134. }
  135. else
  136. {
  137. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("Creating new State for %s %" PRIu32), GetManagingTypeName(), InShortId);
  138. State = InCreate();
  139. if (LIKELY(State.IsValid()))
  140. {
  141. FileStatesById.Add(InShortId, State);
  142. }
  143. }
  144. }
  145. if (UNLIKELY(!State.IsValid()))
  146. {
  147. UE_LOG(LogWwiseFileHandler, Verbose, TEXT("Trying to increment invalid state for %s %" PRIu32), GetManagingTypeName(), InShortId);
  148. SCOPED_WWISEFILEHANDLER_EVENT_4(TEXT("FWwiseFileHandlerBase::IncrementFileStateUse Callback"));
  149. InCallback(State, false);
  150. }
  151. else
  152. {
  153. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("Incrementing State for %s %" PRIu32), GetManagingTypeName(), InShortId);
  154. State->IncrementCountAsync(InOperationOrigin, [State, InCallback = MoveTemp(InCallback)](bool bInResult)
  155. {
  156. SCOPED_WWISEFILEHANDLER_EVENT_4(TEXT("FWwiseFileHandlerBase::IncrementFileStateUse Callback"));
  157. InCallback(State, bInResult);
  158. });
  159. }
  160. }
  161. void FWwiseFileHandlerBase::DecrementFileStateUse(uint32 InShortId, FWwiseFileState* InFileState, EWwiseFileStateOperationOrigin InOperationOrigin, FDecrementStateCallback&& InCallback)
  162. {
  163. SCOPED_WWISEFILEHANDLER_EVENT_F_3(TEXT("FWwiseFileHandlerBase::DecrementFileStateUse %s"), GetManagingTypeName());
  164. if (!InFileState)
  165. {
  166. const FWwiseFileStateSharedPtr* StatePtr;
  167. {
  168. FRWScopeLock StateLock(FileStatesByIdLock, FRWScopeLockType::SLT_ReadOnly);
  169. StatePtr = FileStatesById.Find(InShortId);
  170. if (LIKELY(StatePtr && StatePtr->IsValid()))
  171. {
  172. InFileState = StatePtr->Get();
  173. }
  174. }
  175. if (UNLIKELY(!StatePtr || !StatePtr->IsValid()))
  176. {
  177. UE_LOG(LogWwiseFileHandler, Log, TEXT("Could not find state for for %s %" PRIu32), GetManagingTypeName(), InShortId);
  178. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileHandlerBase::DecrementFileStateUse %s Callback"), GetManagingTypeName());
  179. InCallback();
  180. return;
  181. }
  182. }
  183. InFileState->DecrementCountAsync(InOperationOrigin, [this, InShortId, InFileState, InOperationOrigin](FDecrementStateCallback&& InCallback) mutable
  184. {
  185. // File state deletion request
  186. FileHandlerExecutionQueue.Async([this, InShortId, InFileState, InOperationOrigin, InCallback = MoveTemp(InCallback)]() mutable
  187. {
  188. OnDeleteState(InShortId, *InFileState, InOperationOrigin, MoveTemp(InCallback));
  189. });
  190. }, MoveTemp(InCallback));
  191. }
  192. void FWwiseFileHandlerBase::OnDeleteState(uint32 InShortId, FWwiseFileState& InFileState, EWwiseFileStateOperationOrigin InOperationOrigin, FDecrementStateCallback&& InCallback)
  193. {
  194. SCOPED_WWISEFILEHANDLER_EVENT_F_3(TEXT("FWwiseFileHandlerBase::OnDeleteState %s"), GetManagingTypeName());
  195. {
  196. FRWScopeLock StateLock(FileStatesByIdLock, FRWScopeLockType::SLT_Write);
  197. if (!InFileState.CanDelete())
  198. {
  199. UE_LOG(LogWwiseFileHandler, Verbose, TEXT("OnDeleteState %s %" PRIu32 ": Cannot delete State. Probably re-loaded between deletion request and now."),
  200. GetManagingTypeName(), InShortId);
  201. }
  202. else
  203. {
  204. UE_LOG(LogWwiseFileHandler, Verbose, TEXT("OnDeleteState %s %" PRIu32 ": Deleting."), GetManagingTypeName(), InShortId);
  205. const auto RemovalCount = FileStatesById.Remove(InShortId); // WARNING: This will very probably delete InFileState reference. Do not use the File State from that point!
  206. UE_CLOG(RemovalCount != 1, LogWwiseFileHandler, Error, TEXT("Removing a state for %s %" PRIu32 ", ended up deleting %" PRIi32 " states."),
  207. GetManagingTypeName(), InShortId, RemovalCount);
  208. }
  209. }
  210. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileHandlerBase::OnDeleteState %s Callback"), GetManagingTypeName());
  211. InCallback();
  212. }