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.

424 lines
11 KiB

  1. /*
  2. RVSTREAM.C
  3. */
  4. #include "precomp.h"
  5. #define PLAYOUT_DELAY_FACTOR 2
  6. #ifndef MAX_MISORDER
  7. #define MAX_MISORDER 30
  8. #endif
  9. void FreeNetBufList(NETBUF *pNB, IRTPRecv *pRTP)
  10. {
  11. NETBUF *pNBTemp;
  12. while (pNB) {
  13. pNBTemp = pNB;
  14. pNB = pNB->next;
  15. if (pRTP) pRTP->FreePacket(*(WSABUF **)(pNBTemp + 1));
  16. pNBTemp->pool->ReturnBuffer(pNBTemp);
  17. }
  18. }
  19. void AppendNetBufList(NETBUF *pFirstNB, NETBUF *pNB)
  20. {
  21. NETBUF *pNB1 = pFirstNB;
  22. while (pNB1->next) {
  23. ASSERT(pNB != pNB1);
  24. pNB1 = pNB1->next;
  25. }
  26. ASSERT(pNB != pNB1);
  27. pNB1->next = pNB;
  28. }
  29. int RVStream::Initialize(UINT flags, UINT size, IRTPRecv *pRTP, MEDIAPACKETINIT *papi, ULONG ulSamplesPerPacket, ULONG ulSamplesPerSec, VcmFilter *pVideoFilter)
  30. {
  31. m_pVideoFilter = pVideoFilter;
  32. return ((RxStream*)this)->Initialize(flags, size, pRTP, papi, ulSamplesPerPacket, ulSamplesPerSec);
  33. }
  34. /*
  35. Queues a received RTP packet.
  36. The packet is described by pNetBuf.
  37. This routine will take care of freeing pNetBuf (even in error cases)
  38. */
  39. HRESULT
  40. RVStream::PutNextNetIn(WSABUF *pWsaBuf, DWORD timestamp, UINT seq, UINT fMark, BOOL *pfSkippedData, BOOL *pfSyncPoint)
  41. {
  42. FX_ENTRY("RVStream::PutNextNetIn");
  43. UINT pos;
  44. MediaPacket *pAP;
  45. NETBUF *pNB_Packet;
  46. HRESULT hr;
  47. NETBUF *pNetBuf = (NETBUF *)m_NetBufPool.GetBuffer();
  48. ASSERT(pNetBuf);
  49. EnterCriticalSection(&m_CritSect);
  50. *pfSkippedData = FALSE;
  51. *pfSyncPoint = FALSE;
  52. if (pNetBuf == NULL)
  53. {
  54. hr = E_OUTOFMEMORY;
  55. WARNING_OUT(("RVStream::PutNextNetIn - Out of memory in buffer pool"));
  56. m_pRTP->FreePacket(pWsaBuf);
  57. goto ErrorExit;
  58. }
  59. *(WSABUF **)(pNetBuf+1) = pWsaBuf; // cache the WSABUF pointer so it can be returned later
  60. pNetBuf->data = (PBYTE) pWsaBuf->buf + sizeof(RTP_HDR);
  61. pNetBuf->length = pWsaBuf->len - sizeof(RTP_HDR);
  62. pNetBuf->next = NULL;
  63. pNetBuf->pool = &m_NetBufPool;
  64. hr = ReassembleFrame(pNetBuf, seq, fMark);
  65. if (hr != DPR_SUCCESS)
  66. {
  67. // free pNetBuf since its not yet on m_NetBufList.
  68. // m_NetBufList will be freed at ErrorExit
  69. ::FreeNetBufList(pNetBuf,m_pRTP);
  70. goto ErrorExit;
  71. }
  72. // not the end of the frame
  73. if (!fMark)
  74. {
  75. LeaveCriticalSection(&m_CritSect);
  76. return S_FALSE; // success, but not a new frame yet
  77. }
  78. // If we get here we think we have a complete encoded video frame (fMark was
  79. // set on the last packet)
  80. // if the ring is full or the timestamp is earlier, dump everything.This may be too drastic
  81. // and the reset action could be refined to dump only the older
  82. // packets. However, need to make sure the ring doesnt get "stuck"
  83. pos = ModRing(m_MaxPos+1);
  84. if (pos == m_FreePos || TS_EARLIER(timestamp, m_MaxT)) {
  85. Reset(seq,timestamp);
  86. *pfSkippedData = TRUE;
  87. pos = ModRing(m_MaxPos + 1); // check again
  88. if (pos == m_FreePos) {
  89. hr = DPR_OUT_OF_MEMORY;
  90. m_LastGoodSeq -= MAX_MISORDER; //make sure we dont accidentally synchronize
  91. goto ErrorExit;
  92. }
  93. }
  94. // insert frame into ring
  95. pAP = m_Ring[pos];
  96. if (pAP->Busy() || pAP->GetState() != MP_STATE_RESET) {
  97. hr = DPR_DUPLICATE_PACKET;
  98. goto ErrorExit;
  99. }
  100. // new stuff
  101. hr = RestorePacket(m_NetBufList, pAP, timestamp, seq, fMark, pfSyncPoint);
  102. if (FAILED(hr))
  103. {
  104. goto ErrorExit;
  105. }
  106. if (*pfSyncPoint)
  107. {
  108. DEBUGMSG (ZONE_IFRAME, ("%s: Received a keyframe\r\n", _fx_));
  109. }
  110. ::FreeNetBufList(m_NetBufList,m_pRTP);
  111. m_NetBufList = NULL;
  112. #ifdef DEBUG
  113. if (!TS_LATER(timestamp, m_MaxT))
  114. {
  115. DEBUGMSG (ZONE_DP, ("PutNextNetIn(): Reconstructed frame's timestamp <= to previous frame's!\r\n"));
  116. }
  117. #endif
  118. m_MaxT = timestamp;
  119. m_MaxPos = pos; // advance m_MaxPos
  120. // end new stuff
  121. LeaveCriticalSection(&m_CritSect);
  122. StartDecode();
  123. return hr;
  124. ErrorExit:
  125. // if we're in the middle of assembling a frame, free buffers
  126. if (m_NetBufList){
  127. ::FreeNetBufList(m_NetBufList,m_pRTP);
  128. m_NetBufList = NULL;
  129. }
  130. LeaveCriticalSection(&m_CritSect);
  131. return hr;
  132. }
  133. // Called to force the release of any accumulated NETBUFs back to the owner (RTP).
  134. // This can be called at shutdown or to escape from a out-of-buffer situation
  135. BOOL RVStream::ReleaseNetBuffers()
  136. {
  137. ::FreeNetBufList(m_NetBufList, m_pRTP);
  138. m_NetBufList = NULL;
  139. return TRUE;
  140. }
  141. // Take a packet and reassemble it into a frame.
  142. // Doesnt currently process out-of-order packets (ie) the entire frame is
  143. // discarded
  144. // The NETBUF is held onto, unless an error is returned
  145. HRESULT
  146. RVStream::ReassembleFrame(NETBUF *pNetBuf, UINT seq, UINT fMark)
  147. {
  148. ++m_LastGoodSeq;
  149. if (seq != m_LastGoodSeq) {
  150. // dont handle out of sequence packets
  151. if (fMark)
  152. m_LastGoodSeq = (WORD)seq;
  153. else
  154. --m_LastGoodSeq; // LastGoodSeq left unchanged
  155. return DPR_OUT_OF_SEQUENCE;
  156. }
  157. if (m_NetBufList ) {
  158. // append to list of fragments
  159. ::AppendNetBufList(m_NetBufList,pNetBuf);
  160. } else {
  161. // start of frame
  162. m_NetBufList = pNetBuf;
  163. }
  164. return DPR_SUCCESS;
  165. }
  166. HRESULT
  167. RVStream::SetLastGoodSeq(UINT seq)
  168. {
  169. m_LastGoodSeq = seq ? (WORD)(seq-1) : (WORD)0xFFFF;
  170. return DPR_SUCCESS;
  171. }
  172. // called when restarting after a pause (fSilenceOnly == FALSE) or
  173. // to catch up when latency is getting too much (fSilenceOnly == TRUE)
  174. // determine new play position by skipping any
  175. // stale packets
  176. HRESULT RVStream::FastForward( BOOL fSilenceOnly)
  177. {
  178. UINT pos;
  179. DWORD timestamp = 0;
  180. // restart the receive stream
  181. EnterCriticalSection(&m_CritSect);
  182. if (!TS_EARLIER(m_MaxT , m_PlayT)) {
  183. // there are buffers waiting to be played
  184. // dump them!
  185. if (ModRing(m_MaxPos - m_PlayPos) <= m_DelayPos)
  186. goto Exit; // not too many stale packets;
  187. for (pos=m_PlayPos;pos != ModRing(m_MaxPos -m_DelayPos);pos = ModRing(pos+1),m_PlaySeq++) {
  188. if (m_Ring[pos]->Busy()
  189. || (m_Ring[pos]->GetState() != MP_STATE_RESET
  190. && (fSilenceOnly ||ModRing(m_MaxPos-pos) <= m_MaxDelayPos)))
  191. { // non-empty packet
  192. if (m_Ring[pos]->Busy()) // uncommon case
  193. goto Exit; // bailing out
  194. timestamp = m_Ring[pos]->GetTimestamp();
  195. break;
  196. }
  197. m_Ring[pos]->Recycle(); // free NETBUF and Reset state
  198. LOG((LOGMSG_RX_SKIP,pos));
  199. }
  200. if (timestamp) {// starting from non-empty packet
  201. m_PlayT = timestamp;
  202. //m_Ring[pos]->GetProp(MP_PROP_SEQNUM, &m_PlaySeq);
  203. } else { // starting from (possibly) empty packet
  204. m_PlayT++;
  205. }
  206. // probably also need to update FreePos
  207. if (m_FreePos == ModRing(m_PlayPos-1))
  208. m_FreePos = ModRing(pos-1);
  209. m_PlayPos = pos;
  210. /*
  211. if (pos == ModRing(m_MaxPos+1)) {
  212. DEBUGMSG(1,("Reset:: m_MaxT inconsisten!\n"));
  213. }
  214. */
  215. LOG((LOGMSG_RX_RESET2,m_MaxT,m_PlayT,m_PlayPos));
  216. }
  217. Exit:
  218. LeaveCriticalSection(&m_CritSect);
  219. return DPR_SUCCESS;
  220. }
  221. HRESULT
  222. RVStream::Reset(UINT seq,DWORD timestamp)
  223. {
  224. UINT pos;
  225. HRESULT hr;
  226. // restart the receive stream
  227. EnterCriticalSection(&m_CritSect);
  228. LOG((LOGMSG_RX_RESET,m_MaxPos,m_PlayT,m_PlayPos));
  229. /*if (!TS_EARLIER(m_MaxT , m_PlayT)) */
  230. {
  231. // there are buffers waiting to be played
  232. // dump them!
  233. // Empty the RVStream and set PlayT appropriately
  234. for (pos = m_PlayPos;
  235. pos != m_FreePos;
  236. pos = ModRing(pos+1))
  237. {
  238. if (m_Ring[pos]->Busy ())
  239. {
  240. DEBUGMSG (1, ("RVStream::Reset: packet is busy, pos=%d\r\n", pos));
  241. ASSERT(1);
  242. hr = DPR_INVALID_PARAMETER;
  243. goto Failed;
  244. }
  245. m_Ring[pos]->Recycle(); // free NETBUF and Reset state
  246. }
  247. }
  248. m_MaxPos = ModRing(m_PlayPos-1);
  249. m_PlayT = timestamp;
  250. m_MaxT = m_PlayT -1; // m_MaxT must be less than m_PlayT
  251. m_PlaySeq = seq;
  252. LOG((LOGMSG_RX_RESET2,m_MaxPos,m_PlayT,m_PlayPos));
  253. hr = DPR_SUCCESS;
  254. Failed:
  255. LeaveCriticalSection(&m_CritSect);
  256. return hr;
  257. }
  258. MediaPacket *RVStream::GetNextPlay(void)
  259. {
  260. MediaPacket *pAP = NULL;
  261. UINT pos,seq;
  262. DWORD timestamp = 0, dwVal;
  263. EnterCriticalSection(&m_CritSect);
  264. pAP = m_Ring[m_PlayPos];
  265. if (pAP->Busy() ||
  266. (pAP->GetState() != MP_STATE_RESET && pAP->GetState() != MP_STATE_DECODED)
  267. || ModRing(m_PlayPos+1) == m_FreePos) {
  268. LeaveCriticalSection(&m_CritSect);
  269. return NULL;
  270. } else {
  271. // If there are empty buffer(s) at the head of the q followed
  272. // by a talkspurt (non-empty buffers) and if the talkspurt is excessively
  273. // delayed then squeeze out the silence.
  274. //
  275. if (pAP->GetState() == MP_STATE_RESET)
  276. FastForward(TRUE); // skip silence packets if necessary
  277. pAP = m_Ring[m_PlayPos]; // in case the play position changed
  278. if (pAP->GetState() == MP_STATE_DECODED) {
  279. timestamp = pAP->GetTimestamp();
  280. seq = pAP->GetSeqNum();
  281. }
  282. }
  283. pAP->Busy(TRUE);
  284. m_PlayPos = ModRing(m_PlayPos+1);
  285. if (timestamp) {
  286. m_PlayT = timestamp+1;
  287. m_PlaySeq = seq+1;
  288. } else {
  289. m_PlaySeq++;
  290. // we dont really know the timestamp of the next frame to play
  291. // without looking at it, and it may not have arrived
  292. // so m_PlayT is just a lower bound
  293. m_PlayT++;
  294. }
  295. LeaveCriticalSection(&m_CritSect);
  296. return pAP;
  297. }
  298. RVStream::Destroy()
  299. {
  300. ASSERT (!m_NetBufList);
  301. //::FreeNetBufList(m_NetBufList,m_pRTP);
  302. m_NetBufList = NULL;
  303. RxStream::Destroy();
  304. return DPR_SUCCESS;
  305. }
  306. void RVStream::StartDecode()
  307. {
  308. MediaPacket *pVP;
  309. MMRESULT mmr;
  310. // if we have a separate decode thread this will signal it.
  311. // for now we insert the decode loop here
  312. while (pVP = GetNextDecode())
  313. {
  314. mmr = m_pVideoFilter->Convert((VideoPacket*)pVP, VP_DECODE);
  315. if (mmr != MMSYSERR_NOERROR)
  316. pVP->Recycle();
  317. else
  318. pVP->SetState(MP_STATE_DECODED);
  319. Release(pVP);
  320. }
  321. }
  322. HRESULT RVStream::RestorePacket(NETBUF *pNetBuf, MediaPacket *pVP, DWORD timestamp, UINT seq, UINT fMark, BOOL *pfReceivedKeyframe)
  323. {
  324. VOID *pNet;
  325. UINT uSizeNet;
  326. WSABUF bufDesc[MAX_VIDEO_FRAGMENTS]; // limit to at most 32 fragments
  327. UINT i;
  328. DWORD dwReceivedBytes=0;
  329. NETBUF *pnb;
  330. DWORD dwLength;
  331. DWORD_PTR dwPropVal;
  332. MMRESULT mmr;
  333. i = 0;
  334. pnb = pNetBuf;
  335. while (pnb && i < MAX_VIDEO_FRAGMENTS) {
  336. bufDesc[i].buf = (char *)pnb->data;
  337. bufDesc[i].len = pnb->length;
  338. dwReceivedBytes += pnb->length + sizeof(RTP_HDR) + IP_HEADER_SIZE + UDP_HEADER_SIZE;
  339. pnb = pnb->next;
  340. i++;
  341. }
  342. ASSERT(!pnb); // fail if we get a frame with more than MAX_VIDEO_FRAGMENTS
  343. // Write the bits per second counter
  344. UPDATE_COUNTER(g_pctrVideoReceiveBytes, dwReceivedBytes * 8);
  345. pVP->GetNetData(&pNet, &uSizeNet);
  346. // Initialize length to maximum reconstructed frame size
  347. pVP->GetProp(MP_PROP_MAX_NET_LENGTH, &dwPropVal);
  348. dwLength = (DWORD)dwPropVal;
  349. if (pnb==NULL)
  350. {
  351. mmr = m_pVideoFilter->RestorePayload(bufDesc, i, (BYTE*)pNet, &dwLength, pfReceivedKeyframe);
  352. if (mmr == MMSYSERR_NOERROR)
  353. {
  354. pVP->SetNetLength(dwLength);
  355. pVP->Receive(NULL, timestamp, seq, fMark);
  356. return S_OK;
  357. }
  358. }
  359. return E_FAIL;
  360. }
  361.