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.

284 lines
6.5 KiB

  1. /*
  2. TxStream.cpp
  3. */
  4. #include "precomp.h"
  5. TxStream::Initialize ( UINT flags, UINT numBufs, DataPump *pdp, MEDIAPACKETINIT *papi )
  6. {
  7. UINT i;
  8. MediaPacket *pAP;
  9. m_RingSize = numBufs;
  10. if (flags & DP_FLAG_MMSYSTEM)
  11. {
  12. if (m_RingSize > MAX_TXRING_SIZE)
  13. return FALSE;
  14. }
  15. else if (flags & DP_FLAG_VIDEO)
  16. {
  17. if (m_RingSize > MAX_TXVRING_SIZE)
  18. return FALSE;
  19. }
  20. m_pDataPump = pdp;
  21. for (i=0; i < m_RingSize; i++)
  22. {
  23. if (flags & DP_FLAG_MMSYSTEM)
  24. {
  25. DBG_SAVE_FILE_LINE
  26. pAP = new AudioPacket;
  27. }
  28. else if (flags & DP_FLAG_VIDEO)
  29. {
  30. DBG_SAVE_FILE_LINE
  31. pAP = new VideoPacket;
  32. }
  33. else
  34. break;
  35. m_Ring[i] = pAP;
  36. papi->index = i;
  37. if (!pAP || pAP->Initialize(papi) != DPR_SUCCESS)
  38. break;
  39. }
  40. if (i < m_RingSize)
  41. {
  42. for (UINT j=0; j<=i; j++)
  43. {
  44. m_Ring[j]->Release();
  45. delete m_Ring[j];
  46. }
  47. return FALSE;
  48. }
  49. // queue is empty
  50. m_SendPos = m_FreePos = 0;
  51. m_PreSendCount = 1; // cached silent buffers
  52. m_TxFlags = 0;
  53. // initialize object critical section
  54. InitializeCriticalSection(&m_CritSect);
  55. return TRUE;
  56. }
  57. TxStream::PutNextRecorded(MediaPacket *pAP)
  58. {
  59. // insert into queue
  60. UINT thispos,pos;
  61. UINT unsent,cb;
  62. DWORD timestamp,ts;
  63. UINT spp;
  64. PVOID pUnused;
  65. BOOL fMarked;
  66. EnterCriticalSection(&m_CritSect);
  67. if (pAP->GetState() == MP_STATE_RECORDED) {
  68. if ( m_fTalkspurt == FALSE) {
  69. // beginning of a talkspurt
  70. thispos = pAP->GetIndex();
  71. timestamp = pAP->GetTimestamp();
  72. // figure out the samples per pkt
  73. //
  74. spp = 0; // in case the below call fails
  75. if (pAP->GetDevData(&pUnused,&cb) == DPR_SUCCESS) {
  76. spp = cb/2; // convert bytes to samples assuming 16 bit samples
  77. }
  78. // find the number of packets in send queue
  79. unsent = ModRing(thispos - m_SendPos);
  80. if (unsent > m_PreSendCount)
  81. unsent = m_PreSendCount;
  82. pos = ModRing(thispos - unsent);
  83. timestamp = timestamp - unsent*spp;
  84. // if there are (upto PreSendCount) unsent packets before this one, then
  85. // relabel 'silent' ones as 'recorded'.
  86. fMarked = FALSE;
  87. while (pos != thispos) {
  88. if (m_Ring[pos]->GetState() != MP_STATE_RECORDED) {
  89. // make sure the buffer is chronologically adjacent
  90. ts =m_Ring[pos]->GetTimestamp();
  91. if (ts == timestamp) {
  92. m_Ring[pos]->SetState(MP_STATE_RECORDED);
  93. if (!fMarked) {
  94. fMarked = TRUE;
  95. m_Ring[pos]->SetProp(MP_PROP_PREAMBLE, 1); // set the RTP Mark bit
  96. }
  97. LOG((LOGMSG_PRESEND,pos));
  98. }
  99. }
  100. timestamp += spp;
  101. pos = ModRing(pos+1);
  102. }
  103. m_fTalkspurt = TRUE;
  104. }
  105. } else {
  106. m_fTalkspurt = FALSE;
  107. }
  108. pAP->Busy(FALSE);
  109. LeaveCriticalSection(&m_CritSect);
  110. return TRUE;
  111. }
  112. // blocking call
  113. // Get Audio packet from head of Transmit queue
  114. // Called by the send thread
  115. #if 0
  116. MediaPacket *TxStream::GetNext()
  117. {
  118. DWORD waitResult;
  119. MediaPacket *pAP = NULL;
  120. UINT pos;
  121. while (1) {
  122. // Recorded Packets are queued between SendPos and FreePos
  123. // Packets owned by the Play device are marked busy
  124. EnterCriticalSection(&m_CritSect);
  125. while (m_SendPos != m_FreePos && !m_Ring[m_SendPos]->Busy()) {
  126. pos = m_SendPos;
  127. m_SendPos = ModRing(m_SendPos+1);
  128. // skip non-data (silence) packets
  129. if (m_Ring[pos]->GetState() == MP_STATE_RECORDED) {
  130. // found a packet
  131. pAP = m_Ring[pos];
  132. pAP->Busy(TRUE);
  133. LeaveCriticalSection(&m_CritSect);
  134. if (m_fPreamblePacket)
  135. {
  136. pAP->SetProp (MP_PROP_PREAMBLE, TRUE);
  137. m_fPreamblePacket = FALSE;
  138. }
  139. return (pAP);
  140. }
  141. }
  142. LeaveCriticalSection(&m_CritSect);
  143. // nothing in the queue
  144. if (m_TxFlags & DPTFLAG_STOP_SEND)
  145. break; // return NULL;
  146. waitResult = WaitForSingleObject(m_hQEvent, INFINITE);
  147. }
  148. return (NULL);
  149. }
  150. #endif
  151. MediaPacket *TxStream::GetNext()
  152. {
  153. DWORD waitResult;
  154. MediaPacket *pAP = NULL;
  155. UINT pos,recpos;
  156. {
  157. EnterCriticalSection(&m_CritSect);
  158. // Recorded Packets are queued between SendPos and FreePos
  159. // Packets owned by the Play device are marked busy
  160. pos = m_SendPos;
  161. while (pos != m_FreePos && !m_Ring[pos]->Busy()) {
  162. pos = ModRing(pos+1);
  163. }
  164. recpos = pos; // end marker
  165. if (recpos != m_SendPos) {
  166. // skip all but 'm_PreSendCount' silent packets.
  167. // (later we may decide some of these are not silent after all)
  168. while (ModRing(recpos-m_SendPos) > m_PreSendCount && m_Ring[m_SendPos]->GetState() != MP_STATE_RECORDED) {
  169. m_SendPos = ModRing(m_SendPos+1);
  170. }
  171. if (m_Ring[m_SendPos]->GetState() == MP_STATE_RECORDED) {
  172. // found a packet
  173. pAP = m_Ring[m_SendPos];
  174. pAP->Busy(TRUE);
  175. m_SendPos = ModRing(m_SendPos+1);
  176. }
  177. } // else recpos == m_SendPos
  178. LeaveCriticalSection(&m_CritSect);
  179. }
  180. return pAP;
  181. }
  182. MediaPacket *TxStream::GetFree()
  183. {
  184. UINT pos;
  185. MediaPacket *pAP;
  186. EnterCriticalSection(&m_CritSect);
  187. pos = ModRing(m_FreePos+1);
  188. if (pos == m_SendPos || m_Ring[pos]->Busy()) {
  189. LeaveCriticalSection(&m_CritSect);
  190. return NULL;
  191. }
  192. // ASSERT(m_Ring[pos]->GetState() == MP_STATE_RESET);
  193. // ASSERT(m_Ring[m_FreePos]->GetState() == MP_STATE_RESET);
  194. //
  195. pAP = m_Ring[m_FreePos];
  196. pAP->Busy(TRUE);
  197. m_FreePos = pos;
  198. LeaveCriticalSection(&m_CritSect);
  199. return pAP;
  200. }
  201. // called by the send thread to free an MediaPacket
  202. void TxStream::Release(MediaPacket *pAP)
  203. {
  204. pAP->Busy(FALSE);
  205. }
  206. // Try to empty the queue by dumping unsent packets.
  207. // However, we cant do anything about busy packets
  208. UINT TxStream::Reset(void)
  209. {
  210. UINT pos;
  211. BOOL success;
  212. EnterCriticalSection(&m_CritSect);
  213. pos = m_FreePos;
  214. // allow send thread to block on new packets
  215. m_TxFlags &= ~DPTFLAG_STOP_SEND;
  216. while (pos != m_SendPos && !m_Ring[pos]->Busy()) {
  217. pos = ModRing(pos+1);
  218. }
  219. if (pos == m_SendPos) {
  220. // good - no buffers with send thread
  221. while ( pos != m_FreePos && !m_Ring[pos]->Busy()) {
  222. m_Ring[pos]->MakeSilence();
  223. pos = ModRing(pos+1);
  224. }
  225. m_SendPos = pos;
  226. success = TRUE;
  227. } else {
  228. // bad - buffers have not been released by send thread
  229. // could sleep
  230. success = FALSE;
  231. }
  232. LOG((LOGMSG_TX_RESET, m_FreePos, m_SendPos));
  233. LeaveCriticalSection(&m_CritSect);
  234. return success;
  235. }
  236. void TxStream::Stop(void)
  237. {
  238. EnterCriticalSection(&m_CritSect);
  239. m_TxFlags |= DPTFLAG_STOP_SEND;
  240. LeaveCriticalSection(&m_CritSect);
  241. return;
  242. }
  243. TxStream::Destroy(void)
  244. {
  245. UINT i;
  246. for (i=0; i < m_RingSize; i++) {
  247. if (m_Ring[i]) {
  248. m_Ring[i]->Release();
  249. delete m_Ring[i];
  250. }
  251. }
  252. DeleteCriticalSection(&m_CritSect);
  253. return DPR_SUCCESS;
  254. }