WwiseFileHandlerBase.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  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/WwiseTask.h"
  19. #include "Wwise/Stats/FileHandler.h"
  20. #include "Wwise/Stats/AsyncStats.h"
  21. #include "Misc/ScopeRWLock.h"
  22. #include <inttypes.h>
  23. FWwiseFileHandlerBase::FWwiseFileHandlerBase() :
  24. FileHandlerExecutionQueue(WWISE_EQ_NAME("FWwiseFileHandler"), EWwiseTaskPriority::High)
  25. {
  26. }
  27. FWwiseFileHandlerBase::~FWwiseFileHandlerBase()
  28. {
  29. FRWScopeLock StateLock(FileStatesByIdLock, FRWScopeLockType::SLT_Write);
  30. if (UNLIKELY(FileStatesById.Num() > 0))
  31. {
  32. UE_LOG(LogWwiseFileHandler, Log, TEXT("Closing FileHandler with remaining %" PRIu32 " FileStates. Leaking."), FileStatesById.Num());
  33. for (auto& State : FileStatesById)
  34. {
  35. // Locking in memory the file states
  36. new FWwiseFileStateSharedPtr(State.Value);
  37. }
  38. }
  39. }
  40. void FWwiseFileHandlerBase::OpenStreaming(AkAsyncFileOpenData* io_pOpenData)
  41. {
  42. FWwiseAsyncCycleCounter OpCycleCounter(GET_STATID(STAT_WwiseFileHandlerIORequestLatency));
  43. IncrementFileStateUseAsync(io_pOpenData->fileID, EWwiseFileStateOperationOrigin::Streaming,
  44. [ManagingTypeName = GetManagingTypeName(), io_pOpenData]
  45. {
  46. UE_LOG(LogWwiseFileHandler, Error, TEXT("Trying to open streaming for unknown %s %" PRIu32), ManagingTypeName, io_pOpenData->fileID);
  47. return FWwiseFileStateSharedPtr{};
  48. },
  49. [this, io_pOpenData, OpCycleCounter = MoveTemp(OpCycleCounter)](const FWwiseFileStateSharedPtr& InFileState, bool bInResult) mutable
  50. {
  51. OpCycleCounter.Stop();
  52. SCOPED_WWISEFILEHANDLER_EVENT_F_3(TEXT("FWwiseFileHandlerBase::OpenStreaming %s Async"), GetManagingTypeName());
  53. AKRESULT Result = GetOpenStreamingResult(io_pOpenData);
  54. if (Result == AK_Success && UNLIKELY(!bInResult))
  55. {
  56. Result = AK_UnknownFileError;
  57. }
  58. if (LIKELY(Result == AK_Success))
  59. {
  60. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("Succeeded opening %" PRIu32 " for streaming"), io_pOpenData->fileID);
  61. io_pOpenData->pCallback(io_pOpenData, Result);
  62. }
  63. else
  64. {
  65. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("Failed opening %" PRIu32 " for streaming. Doing callback later."), io_pOpenData->fileID);
  66. LaunchWwiseTask(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileHandlerBase::OpenStreaming Failure Async"), [io_pOpenData, Result]
  67. {
  68. io_pOpenData->pCallback(io_pOpenData, Result);
  69. });
  70. }
  71. });
  72. }
  73. AKRESULT FWwiseFileHandlerBase::GetOpenStreamingResult(AkAsyncFileOpenData* io_pOpenData)
  74. {
  75. FWwiseAsyncCycleCounter OpCycleCounter(GET_STATID(STAT_WwiseFileHandlerIORequestLatency));
  76. FWwiseFileStateSharedPtr State;
  77. {
  78. FRWScopeLock StateLock(FileStatesByIdLock, FRWScopeLockType::SLT_ReadOnly);
  79. const auto* StatePtr = FileStatesById.Find(io_pOpenData->fileID);
  80. if (UNLIKELY(!StatePtr || !StatePtr->IsValid()))
  81. {
  82. UE_LOG(LogWwiseFileHandler, Error, TEXT("Could not open file %" PRIu32 " for streaming: File wasn't initialized prior to OpenStreaming."), io_pOpenData->fileID);
  83. return AK_FileNotFound;
  84. }
  85. State = *StatePtr;
  86. }
  87. AKRESULT Result = AK_Success;
  88. if (auto* StreamableFileStateInfo = State->GetStreamableFileStateInfo())
  89. {
  90. io_pOpenData->pFileDesc = StreamableFileStateInfo->GetFileDesc();
  91. }
  92. else
  93. {
  94. UE_LOG(LogWwiseFileHandler, Error, TEXT("Could not open file %" PRIu32 " for streaming: Could not get AkFileDesc."), io_pOpenData->fileID);
  95. Result = AK_UnknownFileError;
  96. }
  97. return Result;
  98. }
  99. void FWwiseFileHandlerBase::CloseStreaming(uint32 InShortId, FWwiseFileState& InFileState)
  100. {
  101. return DecrementFileStateUseAsync(InShortId, &InFileState, EWwiseFileStateOperationOrigin::Streaming, []{});
  102. }
  103. void FWwiseFileHandlerBase::IncrementFileStateUseAsync(uint32 InShortId, EWwiseFileStateOperationOrigin InOperationOrigin,
  104. FCreateStateFunction&& InCreate, FIncrementStateCallback&& InCallback)
  105. {
  106. FileHandlerExecutionQueue.Async(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileHandlerBase::IncrementFileStateUseAsync"), [this, InShortId, InOperationOrigin, InCreate = MoveTemp(InCreate), InCallback = MoveTemp(InCallback)]() mutable
  107. {
  108. IncrementFileStateUse(InShortId, InOperationOrigin, MoveTemp(InCreate), MoveTemp(InCallback));
  109. });
  110. }
  111. void FWwiseFileHandlerBase::DecrementFileStateUseAsync(uint32 InShortId, FWwiseFileState* InFileState, EWwiseFileStateOperationOrigin InOperationOrigin, FDecrementStateCallback&& InCallback)
  112. {
  113. FileHandlerExecutionQueue.Async(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileHandlerBase::DecrementFileStateUseAsync"), [this, InShortId, InFileState, InOperationOrigin, InCallback = MoveTemp(InCallback)]() mutable
  114. {
  115. DecrementFileStateUse(InShortId, InFileState, InOperationOrigin, MoveTemp(InCallback));
  116. });
  117. }
  118. void FWwiseFileHandlerBase::IncrementFileStateUse(uint32 InShortId, EWwiseFileStateOperationOrigin InOperationOrigin, FCreateStateFunction&& InCreate, FIncrementStateCallback&& InCallback)
  119. {
  120. SCOPED_WWISEFILEHANDLER_EVENT_F_3(TEXT("FWwiseFileHandlerBase::IncrementFileStateUse %s"), GetManagingTypeName());
  121. FWwiseFileStateSharedPtr State;
  122. {
  123. FRWScopeLock StateLock(FileStatesByIdLock, FRWScopeLockType::SLT_ReadOnly);
  124. if (const auto* StatePtr = FileStatesById.Find(InShortId))
  125. {
  126. State = *StatePtr;
  127. }
  128. }
  129. if (!State.IsValid())
  130. {
  131. FRWScopeLock StateLock(FileStatesByIdLock, FRWScopeLockType::SLT_Write);
  132. if (const auto* StatePtr = FileStatesById.Find(InShortId))
  133. {
  134. State = *StatePtr;
  135. }
  136. else
  137. {
  138. State = InCreate();
  139. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("Created new State for %s %" PRIu32 " [%p]"), GetManagingTypeName(), InShortId, State.Get());
  140. if (LIKELY(State.IsValid()))
  141. {
  142. FileStatesById.Add(InShortId, State);
  143. }
  144. }
  145. }
  146. if (UNLIKELY(!State.IsValid()))
  147. {
  148. UE_LOG(LogWwiseFileHandler, Verbose, TEXT("Trying to increment invalid state for %s %" PRIu32), GetManagingTypeName(), InShortId);
  149. SCOPED_WWISEFILEHANDLER_EVENT_4(TEXT("FWwiseFileHandlerBase::IncrementFileStateUse Callback"));
  150. InCallback(State, false);
  151. }
  152. else
  153. {
  154. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("Incrementing State for %s %" PRIu32), GetManagingTypeName(), InShortId);
  155. State->IncrementCountAsync(InOperationOrigin, [this, InOperationOrigin, State, InCallback = MoveTemp(InCallback)](bool bInResult) mutable
  156. {
  157. OnIncrementCountAsyncDone(bInResult, InOperationOrigin, State, MoveTemp(InCallback));
  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(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileHandlerBase::DecrementFileStateUse delete"), [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. FWwiseFileStateSharedPtr DeletingState;
  197. {
  198. FRWScopeLock StateLock(FileStatesByIdLock, FRWScopeLockType::SLT_Write);
  199. if (!InFileState.CanDelete())
  200. {
  201. UE_LOG(LogWwiseFileHandler, Verbose, TEXT("OnDeleteState %s %" PRIu32 " [%p]: Cannot delete State. Probably re-loaded between deletion request and now."),
  202. GetManagingTypeName(), InShortId, &InFileState);
  203. }
  204. else
  205. {
  206. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("OnDeleteState %s %" PRIu32 " [%p]: Deleting."), GetManagingTypeName(), InShortId, &InFileState);
  207. DeletingState = FileStatesById[InShortId]; // Will delete at the end of the scope, out of lock's harm way
  208. const auto RemovalCount = FileStatesById.Remove(InShortId);
  209. UE_CLOG(RemovalCount != 1, LogWwiseFileHandler, Error, TEXT("Removing a state for %s %" PRIu32 ", ended up deleting %" PRIi32 " states."),
  210. GetManagingTypeName(), InShortId, RemovalCount);
  211. }
  212. }
  213. // State will be deleted here (if required)
  214. }
  215. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileHandlerBase::OnDeleteState %s Callback"), GetManagingTypeName());
  216. InCallback();
  217. }
  218. void FWwiseFileHandlerBase::OnIncrementCountAsyncDone(bool bInResult, EWwiseFileStateOperationOrigin InOperationOrigin,
  219. FWwiseFileStateSharedPtr State, FIncrementStateCallback&& InCallback)
  220. {
  221. if (UNLIKELY(!bInResult) && LIKELY(State))
  222. {
  223. DecrementFileStateUse(State->GetShortId(), State.Get(), InOperationOrigin, [State, Callback = MoveTemp(InCallback)]()
  224. {
  225. SCOPED_WWISEFILEHANDLER_EVENT_4(TEXT("FWwiseFileHandlerBase::IncrementFileStateUse Callback Fail"));
  226. Callback(State, false);
  227. });
  228. }
  229. else
  230. {
  231. SCOPED_WWISEFILEHANDLER_EVENT_4(TEXT("FWwiseFileHandlerBase::IncrementFileStateUse Callback"));
  232. InCallback(State, bInResult);
  233. }
  234. }