Leaked source code of windows server 2003
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.

404 lines
9.4 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1999 - 1999 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: vplayer.h
  6. * Content: Voice Player Entry
  7. *
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 03/26/00 rodtoll Created
  12. * 07/09/2000 rodtoll Added signature bytes
  13. * 09/05/2001 simonpow Bug #463972. Added constuct/destruct methods to enable
  14. * allocations and de-allocations via CFixedPool objects
  15. * 02/21/2002 simonpow Bug #549974. Added rate control for incoming speech pkts
  16. ***************************************************************************/
  17. #include "dxvoicepch.h"
  18. #undef DPF_MODNAME
  19. #define DPF_MODNAME "CVoicePlayer::Construct"
  20. BOOL CVoicePlayer::PoolAllocFunction(void * pvItem, void * )
  21. {
  22. CVoicePlayer * pNewPlayer=(CVoicePlayer * ) pvItem;
  23. pNewPlayer->CVoicePlayer::CVoicePlayer();
  24. pNewPlayer->Reset();
  25. return TRUE;
  26. }
  27. #undef DPF_MODNAME
  28. #define DPF_MODNAME "CVoicePlayer::Destruct"
  29. void CVoicePlayer::PoolDeallocFunction(void * pvItem)
  30. {
  31. ((CVoicePlayer * ) pvItem)->CVoicePlayer::~CVoicePlayer();
  32. }
  33. CVoicePlayer::CVoicePlayer()
  34. {
  35. m_dwSignature = VSIG_VOICEPLAYER;
  36. }
  37. CVoicePlayer::~CVoicePlayer()
  38. {
  39. if (IsInitialized())
  40. DeInitialize();
  41. m_dwSignature = VSIG_VOICEPLAYER_FREE;
  42. }
  43. void CVoicePlayer::Reset()
  44. {
  45. m_dwFlags = 0;
  46. m_dvidPlayer = 0;
  47. m_lRefCount = 0;
  48. m_lpInBoundAudioConverter = NULL;
  49. m_lpInputQueue = NULL;
  50. m_dwLastData = 0;
  51. m_dwHostOrderID = 0xFFFFFFFF;
  52. m_bLastPeak = 0;
  53. m_dwLastPlayback = 0;
  54. m_dwNumSilentFrames = 0;
  55. m_dwTransportFlags = 0;
  56. m_dwNumLostFrames = 0;
  57. m_dwNumSpeechFrames = 0;
  58. m_dwNumReceivedFrames = 0;
  59. m_pvPlayerContext = NULL;
  60. m_blNotifyList.Initialize();
  61. m_blPlayList.Initialize();
  62. m_dwNumTargets = 0;
  63. m_pdvidTargets = NULL;
  64. m_lSpeechPktsInCurrentBucket=0;
  65. m_lCurrentSpeechPktBucket=0;
  66. }
  67. #undef DPF_MODNAME
  68. #define DPF_MODNAME "CVoicePlayer::SetPlayerTargets"
  69. //
  70. // Assumes the array has been checked for validity
  71. //
  72. HRESULT CVoicePlayer::SetPlayerTargets( PDVID pdvidTargets, DWORD dwNumTargets )
  73. {
  74. Lock();
  75. delete [] m_pdvidTargets;
  76. if( dwNumTargets == 0 )
  77. {
  78. m_pdvidTargets = NULL;
  79. }
  80. else
  81. {
  82. m_pdvidTargets = new DVID[dwNumTargets];
  83. if( m_pdvidTargets == NULL )
  84. {
  85. m_pdvidTargets = NULL;
  86. m_dwNumTargets = 0;
  87. DPFX(DPFPREP, DVF_ERRORLEVEL, "Error allocating memory" );
  88. UnLock();
  89. return DVERR_OUTOFMEMORY;
  90. }
  91. memcpy( m_pdvidTargets, pdvidTargets, sizeof(DVID)*dwNumTargets );
  92. }
  93. m_dwNumTargets = dwNumTargets;
  94. UnLock();
  95. return DV_OK;
  96. }
  97. HRESULT CVoicePlayer::Initialize( const DVID dvidPlayer, const DWORD dwHostOrder, DWORD dwFlags, PVOID pvContext,
  98. CFixedPool *pOwner )
  99. {
  100. Reset();
  101. if (!DNInitializeCriticalSection( &m_csLock ))
  102. {
  103. return DVERR_OUTOFMEMORY;
  104. }
  105. m_lRefCount = 1;
  106. m_pOwner = pOwner;
  107. m_dvidPlayer = dvidPlayer;
  108. m_dwHostOrderID = dwHostOrder;
  109. m_dwLastData = GetTickCount();
  110. m_dwLastPlayback = 0;
  111. m_dwTransportFlags = dwFlags;
  112. m_pvPlayerContext = pvContext;
  113. m_lSpeechPktsInCurrentBucket=0;
  114. m_lCurrentSpeechPktBucket=0;
  115. m_dwFlags |= VOICEPLAYER_FLAGS_INITIALIZED;
  116. return DV_OK;
  117. }
  118. void CVoicePlayer::GetStatistics( PVOICEPLAYER_STATISTICS pStats )
  119. {
  120. memset( pStats, 0x00, sizeof( VOICEPLAYER_STATISTICS ) );
  121. // Get queue statistics
  122. if( m_lpInputQueue != NULL )
  123. {
  124. Lock();
  125. m_lpInputQueue->GetStatistics( &pStats->queueStats );
  126. UnLock();
  127. }
  128. pStats->dwNumLostFrames = m_dwNumLostFrames;
  129. pStats->dwNumSilentFrames = m_dwNumSilentFrames;
  130. pStats->dwNumSpeechFrames = m_dwNumSpeechFrames;
  131. pStats->dwNumReceivedFrames = m_dwNumReceivedFrames;
  132. return;
  133. }
  134. HRESULT CVoicePlayer::CreateQueue( PQUEUE_PARAMS pQueueParams )
  135. {
  136. HRESULT hr;
  137. DNEnterCriticalSection( &CDirectVoiceEngine::s_csSTLLock );
  138. m_lpInputQueue = new CInputQueue2();
  139. if( m_lpInputQueue == NULL )
  140. {
  141. DPFX(DPFPREP, 0, "Error allocating memory" );
  142. return DVERR_OUTOFMEMORY;
  143. }
  144. hr = m_lpInputQueue->Initialize( pQueueParams );
  145. if( FAILED( hr ) )
  146. {
  147. DPFX(DPFPREP, 0, "Failed initializing queue hr=0x%x", hr );
  148. delete m_lpInputQueue;
  149. m_lpInputQueue = NULL;
  150. return hr;
  151. }
  152. DNLeaveCriticalSection( &CDirectVoiceEngine::s_csSTLLock );
  153. return hr;
  154. }
  155. HRESULT CVoicePlayer::CreateInBoundConverter( const GUID &guidCT, PWAVEFORMATEX pwfxTargetFormat )
  156. {
  157. HRESULT hr;
  158. hr = DVCDB_CreateConverter( guidCT, pwfxTargetFormat, &m_lpInBoundAudioConverter );
  159. if( FAILED( hr ) )
  160. {
  161. DPFX(DPFPREP, 0, "Error creating audio converter hr=0x%x" , hr );
  162. return hr;
  163. }
  164. if( pwfxTargetFormat->wBitsPerSample == 8)
  165. {
  166. m_dwFlags |= VOICEPLAYER_FLAGS_TARGETIS8BIT;
  167. }
  168. return hr;
  169. }
  170. HRESULT CVoicePlayer::DeInitialize()
  171. {
  172. FreeResources();
  173. m_pOwner->Release( this );
  174. return DV_OK;
  175. }
  176. HRESULT CVoicePlayer::HandleReceive( PDVPROTOCOLMSG_SPEECHHEADER pdvSpeechHeader, PBYTE pbData, DWORD dwSize )
  177. {
  178. CFrame tmpFrame;
  179. tmpFrame.SetSeqNum( pdvSpeechHeader->bSeqNum );
  180. tmpFrame.SetMsgNum( pdvSpeechHeader->bMsgNum );
  181. tmpFrame.SetIsSilence( FALSE );
  182. tmpFrame.SetFrameLength( dwSize );
  183. tmpFrame.UserOwn_SetData( pbData, dwSize );
  184. Lock();
  185. DPFX(DPFPREP, DVF_CLIENT_SEQNUM_DEBUG_LEVEL, "SEQ: Receive: Msg [%d] Seq [%d]", pdvSpeechHeader->bMsgNum, pdvSpeechHeader->bSeqNum );
  186. // STATSBLOCK: Begin
  187. //m_stats.m_dwPRESpeech++;
  188. // STATSBLOCK: End
  189. m_lpInputQueue->Enqueue( tmpFrame );
  190. m_dwLastData = GetTickCount();
  191. DPFX(DPFPREP, DVF_INFOLEVEL, "Received speech is buffered!" );
  192. m_dwNumReceivedFrames++;
  193. UnLock();
  194. return DV_OK;
  195. }
  196. CFrame *CVoicePlayer::Dequeue(BOOL *pfLost, BOOL *pfSilence)
  197. {
  198. CFrame *frTmpFrame;
  199. Lock();
  200. frTmpFrame = m_lpInputQueue->Dequeue();
  201. UnLock();
  202. if( !frTmpFrame->GetIsSilence() )
  203. {
  204. *pfSilence = FALSE;
  205. m_dwLastPlayback = GetTickCount();
  206. m_dwNumSpeechFrames++;
  207. }
  208. else
  209. {
  210. m_dwNumSilentFrames++;
  211. *pfSilence = TRUE;
  212. }
  213. if( frTmpFrame->GetIsLost() )
  214. {
  215. *pfLost = TRUE;
  216. m_dwNumLostFrames++;
  217. }
  218. else
  219. {
  220. *pfLost = FALSE;
  221. }
  222. return frTmpFrame;
  223. }
  224. HRESULT CVoicePlayer::DeCompressInBound( CFrame *frCurrentFrame, PVOID pvBuffer, PDWORD pdwBufferSize )
  225. {
  226. HRESULT hr;
  227. hr = m_lpInBoundAudioConverter->Convert( frCurrentFrame->GetDataPointer(), frCurrentFrame->GetFrameLength(), pvBuffer, pdwBufferSize, frCurrentFrame->GetIsSilence() );
  228. if( FAILED( hr ) )
  229. {
  230. DPFX(DPFPREP, 0, "Failed converting audio hr=0x%x", hr );
  231. return hr;
  232. }
  233. return hr;
  234. }
  235. HRESULT CVoicePlayer::GetNextFrameAndDecompress( PVOID pvBuffer, PDWORD pdwBufferSize, BOOL *pfLost, BOOL *pfSilence, DWORD *pdwSeqNum, DWORD *pdwMsgNum )
  236. {
  237. CFrame *frTmpFrame;
  238. BYTE bLastPeak;
  239. HRESULT hr;
  240. frTmpFrame = Dequeue(pfLost,pfSilence );
  241. *pdwSeqNum = frTmpFrame->GetSeqNum();
  242. *pdwMsgNum = frTmpFrame->GetMsgNum();
  243. hr = DeCompressInBound( frTmpFrame, pvBuffer, pdwBufferSize );
  244. frTmpFrame->Return();
  245. if( FAILED( hr ) )
  246. {
  247. DPFX(DPFPREP, 0, "Failed converting audio hr=0x%x", hr );
  248. return hr;
  249. }
  250. if( *pfSilence )
  251. {
  252. m_bLastPeak = 0;
  253. }
  254. else
  255. {
  256. m_bLastPeak = FindPeak( (PBYTE) pvBuffer, *pdwBufferSize, Is8BitUnCompressed() );
  257. }
  258. return hr;
  259. }
  260. void CVoicePlayer::FreeResources()
  261. {
  262. DNDeleteCriticalSection( &m_csLock );
  263. DNEnterCriticalSection( &CDirectVoiceEngine::s_csSTLLock );
  264. if( m_lpInputQueue != NULL )
  265. {
  266. delete m_lpInputQueue;
  267. m_lpInputQueue = NULL;
  268. }
  269. DNLeaveCriticalSection( &CDirectVoiceEngine::s_csSTLLock );
  270. if( m_lpInBoundAudioConverter != NULL )
  271. {
  272. m_lpInBoundAudioConverter->Release();
  273. m_lpInBoundAudioConverter = NULL;
  274. }
  275. if( m_pdvidTargets != NULL )
  276. {
  277. delete [] m_pdvidTargets;
  278. m_pdvidTargets = NULL;
  279. }
  280. Reset();
  281. }
  282. #undef DPF_MODNAME
  283. #define DPF_MODNAME "CVoicePlayer::FindAndRemovePlayerTarget"
  284. //
  285. // FindAndRemovePlayerTarget
  286. //
  287. // Searches the list of targets for this player and removes the specified player if it is part
  288. // of the list. The pfFound variable is set to TRUE if the player specfied was in the target
  289. // list, false otherwise.
  290. //
  291. BOOL CVoicePlayer::FindAndRemovePlayerTarget( DVID dvidTargetToRemove )
  292. {
  293. BOOL fFound = FALSE;
  294. Lock();
  295. for( DWORD dwTargetIndex = 0; dwTargetIndex < m_dwNumTargets; dwTargetIndex++ )
  296. {
  297. if( m_pdvidTargets[dwTargetIndex] == dvidTargetToRemove )
  298. {
  299. if( m_dwNumTargets == 1 )
  300. {
  301. delete [] m_pdvidTargets;
  302. m_pdvidTargets = NULL;
  303. }
  304. // Shortcut, move last element into the current element
  305. // prevents re-allocation. (However, it wastes an element of
  306. // target space) *Shrug*. If this is the last element in the list
  307. // we're removing this will simply provide an unessessary duplication
  308. // of the last element. (But num targets is correct so that's ok).
  309. else
  310. {
  311. m_pdvidTargets[dwTargetIndex] = m_pdvidTargets[m_dwNumTargets-1];
  312. }
  313. m_dwNumTargets--;
  314. fFound = TRUE;
  315. break;
  316. }
  317. }
  318. UnLock();
  319. return fFound;
  320. }