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.

232 lines
4.6 KiB

  1. //
  2. // queue.cpp
  3. //
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999 All rights reserved.
  5. //
  6. #include <stdafx.h>
  7. #include "queue.h"
  8. ///////////////////////////////////////////////////////////////////////////////
  9. //=============================================================================
  10. // CBufferQueue Implementation
  11. //=============================================================================
  12. ///////////////////////////////////////////////////////////////////////////////
  13. CBufferQueue::CBufferQueue()
  14. : m_fEOS(FALSE),
  15. m_fActive(FALSE),
  16. m_lCount(0),
  17. m_lTail(0),
  18. m_lHead(0),
  19. m_lDepth(0),
  20. m_dwStartTime(0),
  21. m_dwSampleTime(0),
  22. m_ppBuffers(NULL)
  23. {
  24. InitializeCriticalSection(&m_CritSec);
  25. }
  26. BOOL CBufferQueue::Initialize(long lDepth)
  27. {
  28. EnterCriticalSection(&m_CritSec);
  29. m_ppBuffers = new IMediaSample * [lDepth];
  30. if (m_ppBuffers == NULL)
  31. {
  32. LeaveCriticalSection(&m_CritSec);
  33. return FALSE;
  34. }
  35. ZeroMemory(m_ppBuffers, sizeof(IMediaSample*) * lDepth);
  36. m_lDepth = lDepth;
  37. LeaveCriticalSection(&m_CritSec);
  38. return TRUE;
  39. }
  40. //
  41. // CBufferQueue::~CBufferQueue - delete allocated memory
  42. //
  43. CBufferQueue::~CBufferQueue()
  44. {
  45. EnterCriticalSection(&m_CritSec);
  46. Flush();
  47. delete [] m_ppBuffers;
  48. DeleteCriticalSection(&m_CritSec);
  49. }
  50. void CBufferQueue::EnQ(
  51. IMediaSample * pMS,
  52. DWORD dwStartTime,
  53. DWORD dwSampleTime
  54. )
  55. /*++
  56. Routine Description:
  57. Store a new sample in the queue.
  58. Arguments:
  59. pMS - a pointer to the media sample.
  60. dwStartTime - The schduled start time for this queue.
  61. dwSampleTime - The length of the sample measured in ms.
  62. Return Value:
  63. HRESULT.
  64. --*/
  65. {
  66. EnterCriticalSection(&m_CritSec);
  67. //
  68. // Validity checks
  69. //
  70. ASSERT(m_ppBuffers != NULL);
  71. ASSERT(pMS);
  72. //
  73. // Release a buffer if one is in the way.
  74. //
  75. if (m_ppBuffers[m_lTail] != NULL)
  76. {
  77. m_ppBuffers[m_lTail]->Release();
  78. // addjust the scheduled play time for the first sample in the queue.
  79. m_dwStartTime += m_dwSampleTime;
  80. }
  81. //
  82. // Put the data in the queue.
  83. //
  84. m_ppBuffers[m_lTail] = pMS;
  85. pMS->AddRef(); // Resease assumed!!!
  86. if (!m_fActive)
  87. {
  88. m_dwStartTime = dwStartTime;
  89. m_dwSampleTime = dwSampleTime;
  90. m_fActive = TRUE;
  91. }
  92. //
  93. // Adjust internal data
  94. //
  95. m_lTail = (m_lTail + 1) % m_lDepth;
  96. //
  97. // Head follows the tail if the Q is full
  98. //
  99. if (m_lCount == m_lDepth)
  100. {
  101. m_lHead = (m_lHead + 1) % m_lDepth;
  102. }
  103. else
  104. {
  105. m_lCount++;
  106. }
  107. DbgLog((LOG_TRACE, 0x3ff, TEXT("EnQ, Start: %d, Samples: %d"),
  108. m_dwStartTime, m_lCount));
  109. LeaveCriticalSection(&m_CritSec);
  110. }
  111. IMediaSample *CBufferQueue::DeQ(BOOL fAlways, DWORD dwCurrentTime)
  112. /*++
  113. Routine Description:
  114. Remove the first sample from the queue.
  115. Arguments:
  116. fAlways - If true, deq immediately, ignoring the time.
  117. dwCurrentTime - The current time.
  118. Return Value:
  119. HRESULT.
  120. --*/
  121. {
  122. EnterCriticalSection(&m_CritSec);
  123. //
  124. // Validity checks
  125. //
  126. ASSERT(m_ppBuffers != NULL);
  127. DbgLog((LOG_TRACE, 0x3ff, TEXT("DeQ, Current: %d, Start: %d, Samples: %d"),
  128. dwCurrentTime, m_dwStartTime, m_lCount));
  129. if (m_lCount == 0)
  130. {
  131. ASSERT(m_lHead == m_lTail);
  132. m_fActive = FALSE; // We don't have continous samples.
  133. LeaveCriticalSection(&m_CritSec);
  134. return NULL;
  135. }
  136. if (!fAlways
  137. && m_dwStartTime != dwCurrentTime
  138. && m_dwStartTime - dwCurrentTime < (ULONG_MAX >> 2)) //handle wrapping.
  139. {
  140. // The time has not come for this queue to deliver.
  141. LeaveCriticalSection(&m_CritSec);
  142. return NULL;
  143. }
  144. //
  145. // Remove Buffer
  146. //
  147. IMediaSample *pMS = m_ppBuffers[m_lHead];
  148. ASSERT(pMS);
  149. m_ppBuffers[m_lHead] = NULL;
  150. // addjust the start time after we removed the buffer.
  151. m_dwStartTime += m_dwSampleTime;
  152. //
  153. // Adjust internal data
  154. //
  155. m_lCount --;
  156. m_lHead = (m_lHead + 1) % m_lDepth;
  157. LeaveCriticalSection(&m_CritSec);
  158. return pMS;
  159. }
  160. //
  161. // Flush all the samples out of the queue.
  162. //
  163. void CBufferQueue::Flush()
  164. {
  165. EnterCriticalSection(&m_CritSec);
  166. for (int i = 0; i < m_lCount; i ++)
  167. {
  168. m_ppBuffers[m_lHead]->Release();
  169. m_ppBuffers[m_lHead] = NULL;
  170. m_lHead = (m_lHead + 1) % m_lDepth;
  171. }
  172. m_lHead = m_lTail = m_lCount = 0;
  173. m_dwStartTime = m_dwSampleTime = 0;
  174. m_fActive = FALSE;
  175. LeaveCriticalSection(&m_CritSec);
  176. }