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.

698 lines
18 KiB

  1. /*
  2. RXSTREAM.C
  3. */
  4. #include "precomp.h"
  5. extern UINT g_MinWaveAudioDelayMs; // minimum millisecs of introduced playback delay
  6. extern UINT g_MaxAudioDelayMs; // maximum milliesecs of introduced playback delay
  7. RxStream::RxStream(UINT size)
  8. {
  9. UINT i;
  10. for (i =0; i < size; i++) {
  11. m_Ring[i] = NULL;
  12. }
  13. // initialize object critical section
  14. InitializeCriticalSection(&m_CritSect);
  15. }
  16. RxStream::~RxStream()
  17. {
  18. DeleteCriticalSection(&m_CritSect);
  19. }
  20. RxStream::Initialize(
  21. UINT flags,
  22. UINT size, // MB power of 2
  23. IRTPRecv *pRTP,
  24. MEDIAPACKETINIT *papi,
  25. ULONG ulSamplesPerPacket,
  26. ULONG ulSamplesPerSec,
  27. AcmFilter *pAcmFilter) // this param may be NULL for video
  28. {
  29. UINT i;
  30. MediaPacket *pAP;
  31. m_fPreamblePacket = TRUE;
  32. m_pDecodeBufferPool = NULL;
  33. m_RingSize = size;
  34. m_dwFlags = flags;
  35. if (flags & DP_FLAG_MMSYSTEM)
  36. {
  37. if (m_RingSize > MAX_RXRING_SIZE)
  38. return FALSE;
  39. }
  40. else if (flags & DP_FLAG_VIDEO)
  41. {
  42. if (m_RingSize > MAX_RXVRING_SIZE)
  43. return FALSE;
  44. if (!IsSameFormat (papi->pStrmConvSrcFmt, papi->pStrmConvDstFmt)) {
  45. // the video decode bufs are not allocated per MediaPacket object.
  46. // instead we use a BufferPool with a few buffers.
  47. papi->fDontAllocRawBufs = TRUE;
  48. DBG_SAVE_FILE_LINE
  49. m_pDecodeBufferPool = new BufferPool;
  50. // Three seems to be the minimum number of frame bufs
  51. // One is being rendered and at least two are needed
  52. // so the rendering can catch up with the received frames
  53. // (another alternative is to dump frames to catch up)
  54. if (m_pDecodeBufferPool->Initialize(3,
  55. sizeof(NETBUF)+papi->cbSizeRawData + papi->cbOffsetRawData) != S_OK)
  56. {
  57. DEBUGMSG(ZONE_DP,("Couldnt initialize decode bufpool!\n"));
  58. delete m_pDecodeBufferPool;
  59. m_pDecodeBufferPool = NULL;
  60. return FALSE;
  61. }
  62. }
  63. }
  64. m_pRTP = pRTP;
  65. for (i=0; i < m_RingSize; i++)
  66. {
  67. if (flags & DP_FLAG_MMSYSTEM)
  68. {
  69. DBG_SAVE_FILE_LINE
  70. pAP = new AudioPacket;
  71. }
  72. else if (flags & DP_FLAG_VIDEO)
  73. {
  74. DBG_SAVE_FILE_LINE
  75. pAP = new VideoPacket;
  76. }
  77. m_Ring[i] = pAP;
  78. papi->index = i;
  79. if (!pAP || pAP->Initialize(papi) != DPR_SUCCESS)
  80. break;
  81. }
  82. if (i < m_RingSize)
  83. {
  84. for (UINT j=0; j<=i; j++)
  85. {
  86. if (m_Ring[j]) {
  87. m_Ring[j]->Release();
  88. delete m_Ring[j];
  89. }
  90. }
  91. return FALSE;
  92. }
  93. m_SamplesPerPkt = ulSamplesPerPacket;
  94. m_SamplesPerSec = ulSamplesPerSec;
  95. // initialize pointers
  96. m_PlaySeq = 0;
  97. m_PlayT = 0;
  98. m_MaxT = m_PlayT - 1; // m_MaxT < m_PlayT indicates queue is empty
  99. m_MaxPos = 0;
  100. m_PlayPos = 0;
  101. m_FreePos = m_RingSize - 1;
  102. m_MinDelayPos = m_SamplesPerSec*g_MinWaveAudioDelayMs/1000/m_SamplesPerPkt; // fixed 250 ms delay
  103. if (m_MinDelayPos < 3) m_MinDelayPos = 3;
  104. m_MaxDelayPos = m_SamplesPerSec*g_MaxAudioDelayMs/1000/m_SamplesPerPkt; //fixed 750 ms delay
  105. m_DelayPos = m_MinDelayPos;
  106. m_ScaledAvgVarDelay = 0;
  107. m_SilenceDurationT = 0;
  108. //m_DeltaT = MAX_TIMESTAMP;
  109. m_pAudioFilter = pAcmFilter;
  110. // go ahead and cache the WAVEFORMATEX structures
  111. // it's handy to have around
  112. if (m_dwFlags & DP_FLAG_AUDIO)
  113. {
  114. m_wfxSrc = *(WAVEFORMATEX*)(papi->pStrmConvSrcFmt);
  115. m_wfxDst = *(WAVEFORMATEX*)(papi->pStrmConvDstFmt);
  116. }
  117. m_nBeeps = 0;
  118. return TRUE;
  119. }
  120. #define PLAYOUT_DELAY_FACTOR 2
  121. void RxStream::UpdateVariableDelay(DWORD sendT, DWORD arrT)
  122. {
  123. LONG deltaA, deltaS;
  124. DWORD delay,delayPos;
  125. // m_ArrivalT0 and m_SendT0 are the arrival and send timestamps of the packet
  126. // with the shortest trip delay. We could have just stored (m_ArrivalT0 - m_SendT0)
  127. // but since the local and remote clocks are completely unsynchronized, there would
  128. // be signed/unsigned complications.
  129. deltaS = sendT - m_SendT0;
  130. deltaA = arrT - m_ArrivalT0;
  131. if (deltaA < deltaS) {
  132. // this packet took less time
  133. delay = deltaS - deltaA;
  134. // replace shortest trip delay times
  135. m_SendT0 = sendT;
  136. m_ArrivalT0 = arrT;
  137. } else {
  138. // variable delay is how much longer this packet took
  139. delay = deltaA - deltaS;
  140. }
  141. // update average variable delay according to
  142. // m_AvgVarDelay = m_AvgVarDelay + (delay - m_AvgVarDelay)*1/16;
  143. // however we are storing the scaled average, with a scaling
  144. // factor of 16. So the calculation becomes
  145. m_ScaledAvgVarDelay = m_ScaledAvgVarDelay + (delay - m_ScaledAvgVarDelay/16);
  146. // now calculate delayPos
  147. delayPos = m_MinDelayPos + PLAYOUT_DELAY_FACTOR * m_ScaledAvgVarDelay/16/m_SamplesPerPkt;
  148. if (delayPos >= m_MaxDelayPos) delayPos = m_MaxDelayPos;
  149. LOG((LOGMSG_JITTER,delay, m_ScaledAvgVarDelay/16, delayPos));
  150. if (m_DelayPos != delayPos) {
  151. DEBUGMSG(ZONE_VERBOSE,("Changing m_DelayPos from %d to %d\n",m_DelayPos, delayPos));
  152. m_DelayPos = delayPos;
  153. }
  154. UPDATE_COUNTER(g_pctrAudioJBDelay, m_DelayPos*(m_SamplesPerPkt*1000)/m_SamplesPerSec);
  155. }
  156. // This function is only used for audio packets
  157. HRESULT
  158. RxStream::PutNextNetIn(WSABUF *pWsaBuf, DWORD timestamp, UINT seq, UINT fMark, BOOL *pfSkippedData, BOOL *pfSyncPoint)
  159. {
  160. DWORD deltaTicks;
  161. MediaPacket *pAP;
  162. HRESULT hr;
  163. UINT samples;
  164. NETBUF netbuf;
  165. netbuf.data = (PBYTE) pWsaBuf->buf + sizeof(RTP_HDR);
  166. netbuf.length = pWsaBuf->len - sizeof(RTP_HDR);
  167. EnterCriticalSection(&m_CritSect);
  168. deltaTicks = (timestamp - m_PlayT)/m_SamplesPerPkt;
  169. if (deltaTicks > ModRing(m_FreePos - m_PlayPos)) {
  170. // the packet is too late or packet overrun
  171. // if the timestamp is earlier than the max. received so far
  172. // then reject it if there are packets queued up
  173. if (TS_EARLIER(timestamp, m_MaxT) && !IsEmpty()) {
  174. hr = DPR_LATE_PACKET; // deltaTicks is -ve
  175. goto ErrorExit;
  176. }
  177. // restart the receive stream with this packet
  178. Reset(timestamp);
  179. m_SendT0 = timestamp;
  180. m_ArrivalT0 = MsToTimestamp(timeGetTime());
  181. deltaTicks = (timestamp - m_PlayT)/m_SamplesPerPkt;
  182. }
  183. // insert into ring
  184. pAP = m_Ring[ModRing(m_PlayPos+deltaTicks)];
  185. if (pAP->Busy() || pAP->GetState() != MP_STATE_RESET) {
  186. hr = DPR_DUPLICATE_PACKET;
  187. goto ErrorExit;
  188. }
  189. // update number of bits received
  190. UPDATE_COUNTER(g_pctrAudioReceiveBytes,(netbuf.length + sizeof(RTP_HDR) + IP_HEADER_SIZE + UDP_HEADER_SIZE)*8);
  191. hr = pAP->Receive(&netbuf, timestamp, seq, fMark);
  192. if (hr != DPR_SUCCESS)
  193. goto ErrorExit;
  194. // m_pRTP->FreePacket(pWsaBuf); // return the buffer to RTP
  195. if (TS_LATER(timestamp, m_MaxT)) { // timestamp > m_MaxT
  196. if (timestamp - m_MaxT > m_SamplesPerPkt * 4) {
  197. // probably beginning of talkspurt - reset minimum delay timestamps
  198. // Note: we should use the Mark flag in RTP header to detect this
  199. m_SendT0 = timestamp;
  200. m_ArrivalT0 = MsToTimestamp(timeGetTime());
  201. }
  202. m_MaxT = timestamp;
  203. m_MaxPos = ModRing(m_PlayPos + deltaTicks);
  204. }
  205. // Calculate variable delay (sort of jitter)
  206. UpdateVariableDelay(timestamp, MsToTimestamp(timeGetTime()));
  207. LeaveCriticalSection(&m_CritSect);
  208. StartDecode();
  209. // Some implementations packetize audio in smaller chunks than they negotiated
  210. // We deal with this by checking the length of the decoded packet and change
  211. // the constant m_SamplesPerPkt. Hopefully this will only happen once per session
  212. // (and never for NM-to-NM calls). Randomly varying packet sizes are still going
  213. // to sound lousy, because the recv queue management has the implicit assumption
  214. // that all packets (at least those in the queue) have the same length
  215. if (pAP->GetState() == MP_STATE_DECODED && (samples = pAP->GetDevDataSamples())) {
  216. if (samples != m_SamplesPerPkt) {
  217. // we're getting different sized (typically smaller) packets than we expected
  218. DEBUGMSG(ZONE_DP,("Changing SamplesPerPkt from %d to %d\n",m_SamplesPerPkt, samples));
  219. m_SamplesPerPkt = samples;
  220. m_MinDelayPos = m_SamplesPerSec*g_MinWaveAudioDelayMs/1000/m_SamplesPerPkt; // fixed 250 ms delay
  221. if (m_MinDelayPos < 2) m_MinDelayPos = 2;
  222. m_MaxDelayPos = m_SamplesPerSec*g_MaxAudioDelayMs/1000/m_SamplesPerPkt; //fixed 750 ms delay
  223. }
  224. }
  225. return DPR_SUCCESS;
  226. ErrorExit:
  227. // m_pRTP->FreePacket(pWsaBuf);
  228. LeaveCriticalSection(&m_CritSect);
  229. return hr;
  230. }
  231. // called when restarting after a pause (fSilenceOnly == FALSE) or
  232. // to catch up when latency is getting too much (fSilenceOnly == TRUE)
  233. // determine new play position by skipping any
  234. // stale packets
  235. HRESULT RxStream::FastForward( BOOL fSilenceOnly)
  236. {
  237. UINT pos;
  238. DWORD timestamp = 0;
  239. // restart the receive stream
  240. EnterCriticalSection(&m_CritSect);
  241. if (!TS_EARLIER(m_MaxT ,m_PlayT)) {
  242. // there are buffers waiting to be played
  243. // dump them!
  244. if (ModRing(m_MaxPos - m_PlayPos) <= m_DelayPos)
  245. goto Exit; // not too many stale packets
  246. for (pos=m_PlayPos;pos != ModRing(m_MaxPos -m_DelayPos);pos = ModRing(pos+1)) {
  247. if (m_Ring[pos]->Busy()
  248. || (m_Ring[pos]->GetState() != MP_STATE_RESET
  249. && (fSilenceOnly ||ModRing(m_MaxPos-pos) <= m_MaxDelayPos)))
  250. { // non-empty packet
  251. if (m_Ring[pos]->Busy()) // uncommon case
  252. goto Exit; // bailing out
  253. timestamp =m_Ring[pos]->GetTimestamp();
  254. break;
  255. }
  256. m_Ring[pos]->Recycle(); // free NETBUF and Reset state
  257. LOG((LOGMSG_RX_SKIP,pos));
  258. }
  259. if (timestamp) // starting from non-empty packet
  260. m_PlayT = timestamp;
  261. else // starting from (possibly) empty packet
  262. m_PlayT = m_MaxT - m_DelayPos*m_SamplesPerPkt;
  263. // probably also need to update FreePos
  264. if (m_FreePos == ModRing(m_PlayPos-1))
  265. m_FreePos = ModRing(pos-1);
  266. m_PlayPos = pos;
  267. /*
  268. if (pos == ModRing(m_MaxPos+1)) {
  269. DEBUGMSG(1,("Reset:: m_MaxT inconsisten!\n"));
  270. }
  271. */
  272. LOG((LOGMSG_RX_RESET2,m_MaxT,m_PlayT,m_PlayPos));
  273. }
  274. Exit:
  275. LeaveCriticalSection(&m_CritSect);
  276. return DPR_SUCCESS;
  277. }
  278. HRESULT
  279. RxStream::Reset(DWORD timestamp)
  280. {
  281. UINT pos;
  282. DWORD T;
  283. // restart the receive stream
  284. EnterCriticalSection(&m_CritSect);
  285. LOG((LOGMSG_RX_RESET,m_MaxT,m_PlayT,m_PlayPos));
  286. if (!TS_EARLIER(m_MaxT, m_PlayT)) {
  287. // there are buffers waiting to be played
  288. // dump them!
  289. // Empty the RxStream and set PlayT appropriately
  290. for (pos = m_PlayPos;
  291. pos != ModRing(m_PlayPos-1);
  292. pos = ModRing(pos+1))
  293. {
  294. if (m_Ring[pos]->Busy ())
  295. {
  296. ERRORMESSAGE(("RxStream::Reset: packet is busy, pos=%d\r\n", pos));
  297. ASSERT(1);
  298. }
  299. T = m_Ring[pos]->GetTimestamp();
  300. m_Ring[pos]->Recycle(); // free NETBUF and Reset state
  301. if (T == m_MaxT)
  302. break;
  303. }
  304. }
  305. if (timestamp !=0)
  306. m_PlayT = timestamp - m_DelayPos*m_SamplesPerPkt;
  307. m_MaxT = m_PlayT - 1; // max must be less than play
  308. LOG((LOGMSG_RX_RESET2,m_MaxT,m_PlayT,m_PlayPos));
  309. LeaveCriticalSection(&m_CritSect);
  310. return DPR_SUCCESS;
  311. }
  312. BOOL RxStream::IsEmpty()
  313. {
  314. BOOL fEmpty;
  315. EnterCriticalSection(&m_CritSect);
  316. if (TS_EARLIER(m_MaxT, m_PlayT) || m_RingSize == 0)
  317. fEmpty = TRUE;
  318. else if (m_dwFlags & DP_FLAG_AUTO_SILENCE_DETECT)
  319. {
  320. UINT pos;
  321. // we could have received packets that
  322. // are deemed silent. Walk the packets between
  323. // PlayPos and MaxPos and check if they're all empty
  324. pos = m_PlayPos;
  325. fEmpty = TRUE;
  326. do {
  327. if (m_Ring[pos]->Busy() || (m_Ring[pos]->GetState() != MP_STATE_RESET ))
  328. {
  329. fEmpty = FALSE; // no point scanning further
  330. break;
  331. }
  332. pos = ModRing(pos+1);
  333. } while (pos != ModRing(m_MaxPos+1));
  334. }
  335. else
  336. {
  337. // not doing receive silence detection
  338. // every received packet counts
  339. fEmpty = FALSE;
  340. }
  341. LeaveCriticalSection(&m_CritSect);
  342. return fEmpty;
  343. }
  344. void RxStream::StartDecode()
  345. {
  346. MediaPacket *pAP;
  347. MMRESULT mmr;
  348. // if we have a separate decode thread this will signal it.
  349. // for now we insert the decode loop here
  350. while (pAP = GetNextDecode())
  351. {
  352. // if (pAP->Decode() != DPR_SUCCESS)
  353. // {
  354. // pAP->Recycle();
  355. // }
  356. mmr = m_pAudioFilter->Convert((AudioPacket *)pAP, AP_DECODE);
  357. if (mmr != MMSYSERR_NOERROR)
  358. {
  359. pAP->Recycle();
  360. }
  361. else
  362. {
  363. pAP->SetState(MP_STATE_DECODED);
  364. if (m_dwFlags & DP_FLAG_AUTO_SILENCE_DETECT) {
  365. // dont play the packet if we have received at least a quarter second of silent packets.
  366. // This will enable switch to talk (in half-duplex mode).
  367. DWORD dw;
  368. pAP->GetSignalStrength(&dw);
  369. if (m_AudioMonitor.SilenceDetect((WORD)dw)) {
  370. m_SilenceDurationT += m_SamplesPerPkt;
  371. if (m_SilenceDurationT > m_SamplesPerSec/4)
  372. pAP->Recycle();
  373. } else {
  374. m_SilenceDurationT = 0;
  375. }
  376. }
  377. }
  378. Release(pAP);
  379. }
  380. }
  381. MediaPacket *RxStream::GetNextDecode(void)
  382. {
  383. MediaPacket *pAP = NULL;
  384. UINT pos;
  385. NETBUF *pBuf;
  386. EnterCriticalSection(&m_CritSect);
  387. // do we have any packets in the queue
  388. if (! TS_EARLIER(m_MaxT , m_PlayT)) {
  389. pos = m_PlayPos;
  390. do {
  391. if (!m_Ring[pos]->Busy() && m_Ring[pos]->GetState() == MP_STATE_NET_IN_STREAM ) {
  392. if (m_pDecodeBufferPool) {
  393. // MediaPacket needs to be given a decode buffer
  394. if ( pBuf = (NETBUF *)m_pDecodeBufferPool->GetBuffer()) {
  395. // init the buffer
  396. pBuf->pool = m_pDecodeBufferPool;
  397. pBuf->length = m_pDecodeBufferPool->GetMaxBufferSize()-sizeof(NETBUF);
  398. pBuf->data = (PBYTE)(pBuf + 1);
  399. m_Ring[pos]->SetDecodeBuffer(pBuf);
  400. } else {
  401. break; // no buffers available
  402. }
  403. }
  404. pAP = m_Ring[pos];
  405. pAP->Busy(TRUE);
  406. break;
  407. }
  408. pos = ModRing(pos+1);
  409. } while (pos != ModRing(m_MaxPos+1));
  410. }
  411. LeaveCriticalSection(&m_CritSect);
  412. return pAP;
  413. }
  414. MediaPacket *RxStream::GetNextPlay(void)
  415. {
  416. MediaPacket *pAP = NULL;
  417. UINT pos;
  418. EnterCriticalSection(&m_CritSect);
  419. pAP = m_Ring[m_PlayPos];
  420. if (pAP->Busy() || (pAP->GetState() != MP_STATE_RESET && pAP->GetState() != MP_STATE_DECODED)) {
  421. // bad - the next packet is not decoded yet
  422. pos = ModRing(m_FreePos-1);
  423. if (pos != m_PlayPos && !m_Ring[m_FreePos]->Busy()
  424. && m_Ring[m_FreePos]->GetState() == MP_STATE_RESET) {
  425. // give an empty buffer from the end
  426. pAP = m_Ring[m_FreePos];
  427. m_FreePos = pos;
  428. } else {
  429. // worse - no free packets
  430. // this can only happen if packets are not released
  431. // or we-re backed up all the way with new packets
  432. // Reset?
  433. LeaveCriticalSection(&m_CritSect);
  434. return NULL;
  435. }
  436. } else {
  437. // If there are empty buffer(s) at the head of the q followed
  438. // by a talkspurt (non-empty buffers) and if the talkspurt is excessively
  439. // delayed then squeeze out the silence.
  440. //
  441. if (pAP->GetState() == MP_STATE_RESET)
  442. FastForward(TRUE); // skip silence packets if necessary
  443. pAP = m_Ring[m_PlayPos]; // in case the play position changed
  444. }
  445. if (pAP->GetState() == MP_STATE_RESET) {
  446. // give missing packets a timestamp
  447. pAP->SetProp(MP_PROP_TIMESTAMP,m_PlayT);
  448. }
  449. pAP->Busy(TRUE);
  450. m_PlayPos = ModRing(m_PlayPos+1);
  451. m_PlayT += m_SamplesPerPkt;
  452. // the worst hack in all of NAC.DLL - the injection of the
  453. // DTMF "feedback tone". Clearly, this waveout stream stuff needs
  454. // to be rewritten!
  455. if (m_nBeeps > 0)
  456. {
  457. PVOID pBuffer=NULL;
  458. UINT uSize=0;
  459. WAVEFORMATEX wfx;
  460. if ((pAP) && (m_dwFlags & DP_FLAG_AUDIO))
  461. {
  462. pAP->GetDevData(&pBuffer, &uSize);
  463. if (pBuffer)
  464. {
  465. MakeDTMFBeep(&m_wfxDst, (PBYTE)pBuffer, uSize);
  466. pAP->SetState(MP_STATE_DECODED);
  467. pAP->SetRawActual(uSize);
  468. }
  469. }
  470. m_nBeeps--;
  471. }
  472. LeaveCriticalSection(&m_CritSect);
  473. return pAP;
  474. }
  475. void RxStream::InjectBeeps(int nBeeps)
  476. {
  477. EnterCriticalSection(&m_CritSect);
  478. m_nBeeps = nBeeps;
  479. LeaveCriticalSection(&m_CritSect);
  480. }
  481. /*************************************************************************
  482. Function: PeekPrevPlay(void)
  483. Purpose : Get previous audio packet played back.
  484. Returns : Pointer to that packet.
  485. Params : None.
  486. Comments:
  487. History : Date Reason
  488. 06/02/96 Created - PhilF
  489. *************************************************************************/
  490. MediaPacket *RxStream::PeekPrevPlay(void)
  491. {
  492. MediaPacket *pAP = NULL;
  493. EnterCriticalSection(&m_CritSect);
  494. // Get packet previously scheduled for playback from the ring
  495. pAP = m_Ring[ModRing(m_PlayPos+m_RingSize-2)];
  496. LeaveCriticalSection(&m_CritSect);
  497. return pAP;
  498. }
  499. /*************************************************************************
  500. Function: PeekNextPlay(void)
  501. Purpose : Get next next audio packet to be played.
  502. Returns : Pointer to that packet.
  503. Params : None.
  504. Comments:
  505. History : Date Reason
  506. 06/02/96 Created - PhilF
  507. *************************************************************************/
  508. MediaPacket *RxStream::PeekNextPlay(void)
  509. {
  510. MediaPacket *pAP = NULL;
  511. EnterCriticalSection(&m_CritSect);
  512. // Get packet next scheduled for playback from the ring
  513. pAP = m_Ring[ModRing(m_PlayPos)];
  514. LeaveCriticalSection(&m_CritSect);
  515. return pAP;
  516. }
  517. HRESULT RxStream::GetSignalStrength(PDWORD pdw)
  518. {
  519. MediaPacket *pAP;
  520. EnterCriticalSection(&m_CritSect);
  521. pAP = m_Ring[m_PlayPos];
  522. if (!pAP || pAP->Busy() || pAP->GetState() != MP_STATE_DECODED)
  523. *pdw = 0;
  524. else {
  525. pAP->GetSignalStrength(pdw);
  526. }
  527. LeaveCriticalSection(&m_CritSect);
  528. return DPR_SUCCESS;
  529. }
  530. // Scan thru the ring, looking for the next
  531. // decoded packet and report its RTP timestamp
  532. BOOL RxStream::NextPlayablePacketTime(DWORD *pTS)
  533. {
  534. UINT pos;
  535. if (IsEmpty())
  536. return FALSE;
  537. pos = m_PlayPos;
  538. do {
  539. if (m_Ring[pos]->Busy())
  540. return FALSE; // no point scanning further
  541. if (m_Ring[pos]->GetState() == MP_STATE_DECODED ) {
  542. *pTS = m_Ring[pos]->GetTimestamp();
  543. return TRUE;
  544. }
  545. pos = ModRing(pos+1);
  546. } while (pos != ModRing(m_MaxPos+1));
  547. // no decoded packets
  548. return FALSE;
  549. }
  550. void RxStream::Release(MediaPacket *pAP)
  551. {
  552. UINT pos;
  553. DWORD thisPos;
  554. DWORD T;
  555. EnterCriticalSection(&m_CritSect);
  556. if (pAP->GetState() == MP_STATE_DECODED) {
  557. // if its playout time has pAPt reset it
  558. T = pAP->GetTimestamp();
  559. if (TS_EARLIER(T ,m_PlayT)) {
  560. pAP->MakeSilence();
  561. }
  562. }
  563. pAP->Busy(FALSE);
  564. // Advance the free position if we are freeing the next one
  565. pos = ModRing(m_FreePos+1);
  566. thisPos = pAP->GetIndex();
  567. if (pos == thisPos) {
  568. // Releasing one packet may advance FreePos several
  569. while (pos != m_PlayPos && !m_Ring[pos]->Busy()) {
  570. m_FreePos = pos;
  571. pos = ModRing(pos+1);
  572. }
  573. }
  574. LeaveCriticalSection(&m_CritSect);
  575. }
  576. HRESULT
  577. RxStream::SetLastGoodSeq(UINT seq)
  578. {
  579. return DPR_SUCCESS;
  580. }
  581. RxStream::Destroy(void)
  582. {
  583. UINT i;
  584. EnterCriticalSection(&m_CritSect);
  585. for (i=0; i < m_RingSize; i++) {
  586. if (m_Ring[i]) {
  587. m_Ring[i]->Release();
  588. delete m_Ring[i];
  589. m_Ring[i] = NULL;
  590. }
  591. }
  592. m_RingSize = 0;
  593. if (m_pDecodeBufferPool) {
  594. delete m_pDecodeBufferPool;
  595. m_pDecodeBufferPool = NULL;
  596. }
  597. LeaveCriticalSection(&m_CritSect);
  598. return DPR_SUCCESS;
  599. }