Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

414 lines
10 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: dvcsplay.cpp
  6. * Content: Implementation of CDVCSPlayer class
  7. * History:
  8. * Date By Reason
  9. * ============
  10. * 07/22/99 rodtoll created
  11. * 10/05/99 rodtoll Added comments, dpf's.
  12. * 10/29/99 rodtoll Bug #113726 - Integrate Voxware Codecs, updating to use new
  13. * pluggable codec architecture.
  14. * 01/14/2000 rodtoll Updated to support multiple targets
  15. * 03/28/2000 rodtoll Updated to use new player class as base
  16. * rodtoll Moved a bunch of logic out of server into this class
  17. * 11/16/2000 rodtoll Bug #40587 - DPVOICE: Mixing server needs to use multi-processors
  18. ***************************************************************************/
  19. #include "dxvoicepch.h"
  20. #define IsEmpty(x) (x.next == x.prev && x.next == &x)
  21. #define CONVERTTORECORD(x,y,z) ((y *)(x->pvObject))->z
  22. #undef DPF_MODNAME
  23. #define DPF_MODNAME "CDVCSPlayer::CDVCSPlayer"
  24. CDVCSPlayer::CDVCSPlayer(
  25. ): m_lpOutBoundAudioConverter(NULL),
  26. m_bLastSent(NULL),
  27. m_bMsgNum((BYTE)-1),
  28. m_bSeqNum(0),
  29. m_targetSize(0),
  30. m_pblMixingActivePlayers(NULL),
  31. m_pblMixingSpeakingPlayers(NULL),
  32. m_pblMixingHearingPlayers(NULL),
  33. m_pdwHearCount(NULL),
  34. m_pfDecompressed(NULL),
  35. m_pfSilence(NULL),
  36. m_pfNeedsDecompression(NULL),
  37. m_pppCanHear(NULL),
  38. m_pdwMaxCanHear(NULL),
  39. m_pSourceFrame(NULL),
  40. m_sourceUnCompressed(NULL),
  41. m_targetCompressed(NULL),
  42. m_pfMixed(NULL),
  43. m_dwNumMixingThreads(0),
  44. m_pbMsgNumToSend(NULL),
  45. m_pbSeqNumToSend(NULL),
  46. m_pdwResultLength(NULL),
  47. m_pfMixToBeReused(NULL)
  48. {
  49. }
  50. #undef DPF_MODNAME
  51. #define DPF_MODNAME "CDVCSPlayer::~CDVCSPlayer"
  52. CDVCSPlayer::~CDVCSPlayer()
  53. {
  54. }
  55. #undef DPF_MODNAME
  56. #define DPF_MODNAME "CDVCSPlayer::ComparePlayerMix"
  57. //
  58. // ComparePlayerMix
  59. //
  60. // Compares the mix of one player to the mix of another.
  61. //
  62. BOOL CDVCSPlayer::ComparePlayerMix( DWORD dwThreadIndex, CDVCSPlayer *lpdvPlayer )
  63. {
  64. DNASSERT( lpdvPlayer != NULL );
  65. if( lpdvPlayer->m_pdwHearCount[dwThreadIndex] != m_pdwHearCount[dwThreadIndex] )
  66. {
  67. return FALSE;
  68. }
  69. for( int index = 0; index < m_pdwHearCount[dwThreadIndex]; index++ )
  70. {
  71. if( lpdvPlayer->m_pppCanHear[dwThreadIndex][index] != m_pppCanHear[dwThreadIndex][index] )
  72. {
  73. return FALSE;
  74. }
  75. }
  76. return TRUE;
  77. }
  78. void CDVCSPlayer::CompleteRun( DWORD dwThreadIndex )
  79. {
  80. if( m_pSourceFrame[dwThreadIndex] )
  81. {
  82. m_pSourceFrame[dwThreadIndex]->Return();
  83. m_pSourceFrame[dwThreadIndex] = NULL;
  84. }
  85. }
  86. void CDVCSPlayer::ResetForNextRun( DWORD dwThreadIndex, BOOL fDequeue )
  87. {
  88. BOOL fLostFrame;
  89. m_pdwHearCount[dwThreadIndex] = 0;
  90. m_pfSilence[dwThreadIndex] = FALSE;
  91. m_pReuseMixFromThisPlayer[dwThreadIndex] = NULL;
  92. if( !fDequeue )
  93. {
  94. m_pSourceFrame[dwThreadIndex] = NULL;
  95. }
  96. else
  97. {
  98. DNASSERT( !m_pSourceFrame[dwThreadIndex] );
  99. m_pSourceFrame[dwThreadIndex] = Dequeue(&fLostFrame, &m_pfSilence[dwThreadIndex]);
  100. }
  101. m_pfMixed[dwThreadIndex] = FALSE;
  102. m_pfNeedsDecompression[dwThreadIndex] = FALSE;
  103. m_pfDecompressed[dwThreadIndex] = FALSE;
  104. m_pfMixToBeReused[dwThreadIndex] = FALSE;
  105. m_pdwResultLength[dwThreadIndex] = NULL;
  106. }
  107. HRESULT CDVCSPlayer::Initialize( const DVID dvidPlayer, const DWORD dwHostOrder, DWORD dwFlags, PVOID pvContext,
  108. DWORD dwCompressedSize, DWORD dwUnCompressedSize,
  109. CLockedFixedPool<CDVCSPlayer> *pCSOwner,
  110. DWORD dwNumMixingThreads )
  111. {
  112. HRESULT hr;
  113. DWORD dwIndex;
  114. m_pCSOwner = pCSOwner;
  115. hr = CVoicePlayer::Initialize( dvidPlayer, dwHostOrder, dwFlags, pvContext, NULL );
  116. if( FAILED( hr ) )
  117. {
  118. DPFX(DPFPREP, 0, "Initialize failed on player hr=0x%x", hr );
  119. return hr;
  120. }
  121. m_pdwHearCount = new DWORD[dwNumMixingThreads];
  122. m_pfSilence = new BOOL[dwNumMixingThreads];
  123. m_pdwMaxCanHear = new DWORD[dwNumMixingThreads];
  124. m_pSourceFrame = new CFrame*[dwNumMixingThreads];
  125. m_pfMixed = new BOOL[dwNumMixingThreads];
  126. m_pblMixingActivePlayers = new BILINK[dwNumMixingThreads];
  127. m_pblMixingHearingPlayers = new BILINK[dwNumMixingThreads];
  128. m_pblMixingSpeakingPlayers = new BILINK[dwNumMixingThreads];
  129. m_sourceUnCompressed = new BYTE[dwNumMixingThreads*dwUnCompressedSize];
  130. m_targetCompressed = new BYTE[dwNumMixingThreads*dwCompressedSize];
  131. m_pfNeedsDecompression = new BOOL[dwNumMixingThreads];
  132. m_pfDecompressed = new BOOL[dwNumMixingThreads];
  133. m_dwNumMixingThreads = dwNumMixingThreads;
  134. m_pbMsgNumToSend = new BYTE[dwNumMixingThreads];
  135. m_pbSeqNumToSend = new BYTE[dwNumMixingThreads];
  136. m_pdwUnCompressedBufferOffset = new DWORD[dwNumMixingThreads];
  137. m_pdwCompressedBufferOffset = new DWORD[dwNumMixingThreads];
  138. m_pReuseMixFromThisPlayer = new CDVCSPlayer*[dwNumMixingThreads];
  139. m_pdwResultLength = new DWORD[dwNumMixingThreads];
  140. m_pfMixToBeReused = new BOOL[dwNumMixingThreads];
  141. if( !m_pblMixingActivePlayers || !m_pdwHearCount || !m_pfSilence ||
  142. !m_pdwMaxCanHear || !m_pSourceFrame || !m_sourceUnCompressed ||
  143. !m_targetCompressed || !m_pfMixed || !m_pfNeedsDecompression ||
  144. !m_pfDecompressed || !m_pbMsgNumToSend || !m_pbSeqNumToSend ||
  145. !m_pdwUnCompressedBufferOffset || !m_pdwCompressedBufferOffset ||
  146. !m_pReuseMixFromThisPlayer || !m_pdwResultLength || !m_pfMixToBeReused ||
  147. !m_pblMixingHearingPlayers || !m_pblMixingSpeakingPlayers )
  148. {
  149. DPFX(DPFPREP, 0, "Memory alloc failure" );
  150. hr = DVERR_OUTOFMEMORY;
  151. goto INITIALIZE_FAILURE;
  152. }
  153. // Create the Can Hear arrays
  154. m_pppCanHear = new CDVCSPlayer**[dwNumMixingThreads];
  155. ZeroMemory( m_pppCanHear, sizeof(CDVCSPlayer*)*dwNumMixingThreads );
  156. // Resize canhear arrays and setup compressed/uncompressed offsets
  157. for( dwIndex = 0; dwIndex < dwNumMixingThreads; dwIndex++ )
  158. {
  159. m_pdwUnCompressedBufferOffset[dwIndex] = dwIndex * dwUnCompressedSize;
  160. m_pdwCompressedBufferOffset[dwIndex] = dwIndex * dwCompressedSize;
  161. m_pSourceFrame[dwIndex] = 0;
  162. m_pdwMaxCanHear[dwIndex] = 0;
  163. InitBilink( &m_pblMixingActivePlayers[dwIndex], this );
  164. InitBilink( &m_pblMixingSpeakingPlayers[dwIndex], this );
  165. InitBilink( &m_pblMixingHearingPlayers[dwIndex], this );
  166. ResetForNextRun(dwIndex,FALSE);
  167. hr = ResizeIfRequired(dwIndex,1);
  168. if( FAILED( hr ) )
  169. {
  170. DPFX(DPFPREP, 0, "Error resizing target array hr=0x%x", hr );
  171. goto INITIALIZE_FAILURE;
  172. }
  173. }
  174. return hr;
  175. INITIALIZE_FAILURE:
  176. DeInitialize();
  177. return hr;
  178. }
  179. HRESULT CDVCSPlayer::DeInitialize()
  180. {
  181. DWORD dwIndex;
  182. if( m_pblMixingActivePlayers )
  183. {
  184. #ifdef DEBUG
  185. for( dwIndex = 0; dwIndex < m_dwNumMixingThreads; dwIndex++ )
  186. {
  187. DNASSERT( (IsEmpty( m_pblMixingActivePlayers[dwIndex] )) );
  188. DNASSERT( !m_pSourceFrame[dwIndex] );
  189. }
  190. #endif
  191. delete [] m_pblMixingActivePlayers;
  192. m_pblMixingActivePlayers = NULL;
  193. }
  194. if( m_pblMixingSpeakingPlayers )
  195. {
  196. delete [] m_pblMixingSpeakingPlayers;
  197. m_pblMixingSpeakingPlayers = NULL;
  198. }
  199. if( m_pblMixingHearingPlayers )
  200. {
  201. delete [] m_pblMixingHearingPlayers;
  202. m_pblMixingHearingPlayers = NULL;
  203. }
  204. if( m_lpOutBoundAudioConverter )
  205. {
  206. m_lpOutBoundAudioConverter->Release();
  207. m_lpOutBoundAudioConverter = NULL;
  208. }
  209. if( m_pppCanHear )
  210. {
  211. for( dwIndex = 0; dwIndex < m_dwNumMixingThreads; dwIndex++ )
  212. {
  213. if( m_pppCanHear[dwIndex] )
  214. {
  215. delete [] m_pppCanHear[dwIndex];
  216. m_pppCanHear[dwIndex] = NULL;
  217. }
  218. }
  219. delete [] m_pppCanHear;
  220. m_pppCanHear = NULL;
  221. }
  222. if( m_pdwHearCount )
  223. {
  224. delete [] m_pdwHearCount;
  225. m_pdwHearCount = NULL;
  226. }
  227. if( m_pdwResultLength )
  228. {
  229. delete [] m_pdwResultLength;
  230. m_pdwResultLength = NULL;
  231. }
  232. if( m_pfSilence )
  233. {
  234. delete [] m_pfSilence;
  235. m_pfSilence = NULL;
  236. }
  237. if( m_pdwUnCompressedBufferOffset )
  238. {
  239. delete [] m_pdwUnCompressedBufferOffset;
  240. m_pdwUnCompressedBufferOffset = NULL;
  241. }
  242. if( m_pReuseMixFromThisPlayer )
  243. {
  244. delete [] m_pReuseMixFromThisPlayer;
  245. m_pReuseMixFromThisPlayer = NULL;
  246. }
  247. if( m_pdwCompressedBufferOffset )
  248. {
  249. delete [] m_pdwCompressedBufferOffset;
  250. m_pdwCompressedBufferOffset = NULL;
  251. }
  252. if( m_pdwMaxCanHear )
  253. {
  254. delete [] m_pdwMaxCanHear;
  255. m_pdwMaxCanHear = NULL;
  256. }
  257. if( m_sourceUnCompressed )
  258. {
  259. delete [] m_sourceUnCompressed;
  260. m_sourceUnCompressed = NULL;
  261. }
  262. if( m_pfMixToBeReused )
  263. {
  264. delete [] m_pfMixToBeReused;
  265. m_pfMixToBeReused = NULL;
  266. }
  267. if( m_pbMsgNumToSend )
  268. {
  269. delete [] m_pbMsgNumToSend;
  270. m_pbMsgNumToSend = NULL;
  271. }
  272. if( m_pbSeqNumToSend )
  273. {
  274. delete [] m_pbSeqNumToSend;
  275. m_pbSeqNumToSend = NULL;
  276. }
  277. if( m_targetCompressed )
  278. {
  279. delete [] m_targetCompressed;
  280. m_targetCompressed = NULL;
  281. }
  282. if( m_pfMixed )
  283. {
  284. delete [] m_pfMixed;
  285. m_pfMixed = NULL;
  286. }
  287. if( m_pfNeedsDecompression )
  288. {
  289. delete [] m_pfNeedsDecompression;
  290. m_pfNeedsDecompression = NULL;
  291. }
  292. if( m_pfDecompressed )
  293. {
  294. delete [] m_pfDecompressed;
  295. m_pfDecompressed = NULL;
  296. }
  297. if( m_pSourceFrame )
  298. {
  299. delete [] m_pSourceFrame;
  300. m_pSourceFrame = NULL;
  301. }
  302. FreeResources();
  303. m_pCSOwner->Release( this );
  304. return DV_OK;
  305. }
  306. HRESULT CDVCSPlayer::HandleMixingReceive(
  307. PDVPROTOCOLMSG_SPEECHHEADER pdvSpeechHeader, PBYTE pbData,
  308. DWORD dwSize, PDVID pdvidTargets, DWORD dwNumTargets )
  309. {
  310. CFrame tmpFrame;
  311. tmpFrame.SetSeqNum( pdvSpeechHeader->bSeqNum );
  312. tmpFrame.SetMsgNum( pdvSpeechHeader->bMsgNum );
  313. tmpFrame.SetIsSilence( FALSE );
  314. tmpFrame.SetFrameLength( dwSize );
  315. tmpFrame.UserOwn_SetData( pbData, dwSize );
  316. tmpFrame.UserOwn_SetTargets( pdvidTargets, dwNumTargets );
  317. Lock();
  318. // STATSBLOCK: Begin
  319. //m_pStatsBlob->m_dwPRESpeech++;
  320. // STATSBLOCK: End
  321. m_lpInputQueue->Enqueue( tmpFrame );
  322. m_dwLastData = GetTickCount();
  323. DPFX(DPFPREP, DVF_MIXER_DEBUG_LEVEL, "Received speech is buffered!" );
  324. m_dwNumReceivedFrames++;
  325. UnLock();
  326. return DV_OK;
  327. }
  328. HRESULT CDVCSPlayer::CompressOutBound( PVOID pvInputBuffer, DWORD dwInputBufferSize, PVOID pvOutputBuffer, DWORD *pdwOutputSize )
  329. {
  330. HRESULT hr;
  331. hr = m_lpOutBoundAudioConverter->Convert( pvInputBuffer, dwInputBufferSize, pvOutputBuffer, pdwOutputSize, FALSE );
  332. if( FAILED( hr ) )
  333. {
  334. DPFX(DPFPREP, 0, "Failed converting audio hr=0x%x", hr );
  335. return hr;
  336. }
  337. return hr;
  338. }