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.

684 lines
20 KiB

  1. #include "precomp.h"
  2. // #define LOGSTATISTICS_ON 1
  3. #define RTPTIMEPERMS 90 // RTP timestamps use a 90Khz clock
  4. DWORD g_iPost = 0UL;
  5. // Constants
  6. #define POLL_PERIOD 30
  7. void
  8. CALLBACK
  9. TimeCallback(
  10. UINT uID,
  11. UINT uMsg,
  12. HANDLE hEvent,
  13. DWORD dw1,
  14. DWORD dw2
  15. )
  16. {
  17. SetEvent (hEvent); // signal to initiate frame grab
  18. }
  19. DWORD SendVideoStream::CapturingThread (void )
  20. {
  21. DWORD lasttime;
  22. IBitmapSurface* pBS;
  23. VideoPacket *pPacket;
  24. DWORD dwWait;
  25. HANDLE hEvent;
  26. HCAPDEV hCapDev;
  27. DWORD_PTR dwPropVal;
  28. DWORD dwBeforeCapture;
  29. DWORD dwFrames = 0;
  30. DWORD dwOver = 0;
  31. DWORD dwStart;
  32. UINT u;
  33. UINT uPreambleCount = 2;
  34. UINT uTimeout = 0;
  35. DevMediaQueue dq;
  36. SendVideoStream *pMC = this;
  37. TxStream *pStream = pMC->m_SendStream;
  38. MediaControl *pMediaCtrl = pMC->m_InMedia;
  39. UINT timerID;
  40. LPBITMAPINFOHEADER pbmih;
  41. HRESULT hr = DPR_SUCCESS;
  42. #ifdef LOGSTATISTICS_ON
  43. char szDebug[256];
  44. HANDLE hDebugFile;
  45. DWORD d;
  46. DWORD dwDebugPrevious = 0UL;
  47. #endif
  48. DWORD dwDelta;
  49. FX_ENTRY ("DP::CaptTh:")
  50. // get thread context
  51. if (pStream == NULL || m_pVideoFilter == NULL || pMediaCtrl == NULL)
  52. {
  53. return DPR_INVALID_PARAMETER;
  54. }
  55. // get thresholds
  56. pMediaCtrl->GetProp (MC_PROP_TIMEOUT, &dwPropVal);
  57. uTimeout = (DWORD)dwPropVal;
  58. // set dq size
  59. dq.SetSize (MAX_TXVRING_SIZE);
  60. pMediaCtrl->GetProp (MC_PROP_MEDIA_DEV_HANDLE, &dwPropVal);
  61. if (!dwPropVal)
  62. {
  63. DEBUGMSG (ZONE_DP, ("%s: capture device not open (0x%lX)\r\n", _fx_));
  64. goto MyEndThread;
  65. }
  66. hCapDev = (HCAPDEV)dwPropVal;
  67. #if 0
  68. // hey, in the very beginning, let's 'Start' it
  69. hr = pMediaCtrl->Start ();
  70. if (hr != DPR_SUCCESS)
  71. {
  72. DEBUGMSG (ZONE_DP, ("%s: MedVidCtrl::Start failed, hr=0x%lX\r\n", _fx_, hr));
  73. goto MyEndThread;
  74. }
  75. #endif
  76. // update timestamp to account for the 'sleep' period
  77. dwPropVal = timeGetTime();
  78. pMC->m_SendTimestamp += ((DWORD)dwPropVal - pMC->m_SavedTickCount)*RTPTIMEPERMS;
  79. pMC->m_SavedTickCount = (DWORD)dwPropVal;
  80. // Enter critical section: QoS thread also reads the statistics
  81. EnterCriticalSection(&pMC->m_crsVidQoS);
  82. // Initialize QoS structure
  83. ZeroMemory(&pMC->m_Stats, 4UL * sizeof(DWORD));
  84. // Initialize oldest QoS callback timestamp
  85. pMC->m_Stats.dwNewestTs = pMC->m_Stats.dwOldestTs = (DWORD)dwPropVal;
  86. // Leave critical section
  87. LeaveCriticalSection(&pMC->m_crsVidQoS);
  88. // let's get into the loop
  89. pMC->m_fSending= TRUE;
  90. // get event handle
  91. if (!(hEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) {
  92. DEBUGMSG (ZONE_DP, ("%s: invalid event\r\n", _fx_));
  93. hr = DPR_CANT_CREATE_EVENT;
  94. goto MyEndThread;
  95. }
  96. if (!(timerID = timeSetEvent(POLL_PERIOD, 1, (LPTIMECALLBACK)&TimeCallback, (DWORD_PTR)hEvent, TIME_PERIODIC))) {
  97. DEBUGMSG (ZONE_DP, ("%s: failed to init MM timer\r\n", _fx_));
  98. CloseHandle (hEvent);
  99. hr = DPR_CANT_CREATE_EVENT;
  100. goto MyEndThread;
  101. }
  102. // force I-Frames to be sent for the first few frames
  103. // to make sure that the receiver gets one
  104. pMC->m_ThreadFlags |= DPTFLAG_SEND_PREAMBLE;
  105. pPacket = NULL;
  106. lasttime = timeGetTime();
  107. dwStart = lasttime;
  108. while (!(pMC->m_ThreadFlags & DPTFLAG_STOP_RECORD))
  109. {
  110. dwWait = WaitForSingleObject (hEvent, uTimeout);
  111. // see why I don't need to wait
  112. if ((dwWait != WAIT_TIMEOUT) && !(pMC->m_ThreadFlags & DPTFLAG_PAUSE_CAPTURE)) {
  113. if (!pPacket) {
  114. if (pPacket = (VideoPacket *)pStream->GetFree()) {
  115. if ((hr = pPacket->Record()) != DPR_SUCCESS) {
  116. DEBUGMSG (ZONE_DP, ("%s: Capture FAILED, hr=0x%lX\r\n", _fx_, hr));
  117. break;
  118. }
  119. }
  120. }
  121. dwBeforeCapture = timeGetTime();
  122. if (pPacket && pMC->m_pCaptureChain && dwBeforeCapture - lasttime >= pMC->m_frametime) {
  123. // If there's no frame ready, bail out of the loop and wait
  124. // until we get signaled.
  125. #ifdef LOGSTATISTICS_ON
  126. hDebugFile = CreateFile("C:\\Timings.txt", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
  127. SetFilePointer(hDebugFile, 0, NULL, FILE_END);
  128. wsprintf(szDebug, "Delta: %ld\r\n", dwBeforeCapture - dwDebugPrevious);
  129. WriteFile(hDebugFile, szDebug, strlen(szDebug), &d, NULL);
  130. CloseHandle(hDebugFile);
  131. dwDebugPrevious = dwBeforeCapture;
  132. #endif
  133. dwDelta = dwBeforeCapture - lasttime - pMC->m_frametime;
  134. #if 0
  135. if ((ci_state & CAPSTATE_INDLG) && lpbmih) {
  136. lpbmih->biSize = GetCaptureDeviceFormatHeaderSize(g_hcapdev);
  137. if (!GetCaptureDeviceFormat(g_hcapdev, lpbmih) ||
  138. g_lpbmi->biSize != lpbmih->biSize ||
  139. g_lpbmi->biSizeImage != lpbmih->biSizeImage)
  140. continue; // skip capture
  141. }
  142. #endif
  143. pMC->m_pCaptureChain->GrabFrame(&pBS);
  144. if (pBS) {
  145. // deal with captured frame
  146. if (!(pMC->m_DPFlags & DPFLAG_REAL_THING)) {
  147. dwWait = timeGetTime();
  148. dwOver += (dwWait - dwBeforeCapture);
  149. if (++dwFrames == 20) {
  150. dwWait -= dwStart;
  151. dwOver = (dwOver * 13) / 10; // 130%
  152. pMC->m_frametime = (pMC->m_frametime * dwOver) / dwWait;
  153. pMC->m_frametime = (pMC->m_frametime * 13) / 10; // 130%
  154. if (pMC->m_frametime < 50)
  155. pMC->m_frametime = 50;
  156. else if (pMC->m_frametime > 1000)
  157. pMC->m_frametime = 1000;
  158. dwOver = dwFrames = 0; // restart tracking
  159. dwStart = timeGetTime();
  160. }
  161. }
  162. if (pMC->m_fSending) {
  163. dwPropVal = timeGetTime(); // returns time in millisec
  164. // Enter critical section: QoS thread also reads the statistics
  165. EnterCriticalSection(&pMC->m_crsVidQoS);
  166. // If this is the first frame captured with a new frame rate value,
  167. // the delta isn't valid anymore -> reset it
  168. if (pMC->m_Stats.dwCount == 0)
  169. dwDelta = 0;
  170. // Update total number of frames captured
  171. pMC->m_Stats.dwCount++;
  172. // Add this capture time to total capture time
  173. // If we can access the CPU perf counters Ok, we won't use this value
  174. pMC->m_Stats.dwMsCap += (DWORD)dwPropVal - dwBeforeCapture;
  175. // Leave critical section
  176. LeaveCriticalSection(&pMC->m_crsVidQoS);
  177. // convert to RTP time units (1/90Khz for video)
  178. pMC->m_SendTimestamp += ((DWORD)dwPropVal- pMC->m_SavedTickCount) * RTPTIMEPERMS;
  179. pMC->m_SavedTickCount = (DWORD)dwPropVal;
  180. pPacket->SetProp(MP_PROP_TIMESTAMP,pMC->m_SendTimestamp);
  181. pPacket->SetSurface(pBS);
  182. pPacket->SetState(MP_STATE_RECORDED);
  183. pStream->PutNextRecorded (pPacket);
  184. pMC->Send();
  185. if (uPreambleCount) {
  186. if (!--uPreambleCount) {
  187. // return to default I-frame spacing
  188. pMC->m_ThreadFlags &= ~DPTFLAG_SEND_PREAMBLE;
  189. }
  190. }
  191. pPacket = NULL;
  192. // Indicate that another frame was sent
  193. UPDATE_COUNTER(g_pctrVideoSend, 1);
  194. }
  195. // release captured frame
  196. pBS->Release();
  197. lasttime = dwBeforeCapture - dwDelta;
  198. }
  199. #ifdef LOGSTATISTICS_ON
  200. else
  201. {
  202. hDebugFile = CreateFile("C:\\Timings.txt", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
  203. SetFilePointer(hDebugFile, 0, NULL, FILE_END);
  204. WriteFile(hDebugFile, "No Frame grabbed\r\n", 16, &d, NULL);
  205. CloseHandle(hDebugFile);
  206. }
  207. #endif
  208. }
  209. #ifdef LOGSTATISTICS_ON
  210. else
  211. {
  212. hDebugFile = CreateFile("C:\\Timings.txt", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
  213. SetFilePointer(hDebugFile, 0, NULL, FILE_END);
  214. if (!pPacket)
  215. WriteFile(hDebugFile, "No Frame Ready (pPacket is NULL)\r\n", 35, &d, NULL);
  216. else
  217. {
  218. if (!pMC->m_pCaptureChain)
  219. WriteFile(hDebugFile, "No Frame Ready (CapChain is NULL)\r\n", 33, &d, NULL);
  220. else
  221. WriteFile(hDebugFile, "No Frame Ready (Timings are bad)\r\n", 32, &d, NULL);
  222. }
  223. CloseHandle(hDebugFile);
  224. }
  225. #endif
  226. }
  227. }
  228. // Enter critical section: QoS thread also reads the statistics
  229. EnterCriticalSection(&pMC->m_crsVidQoS);
  230. // Reset number of captured frames
  231. pMC->m_Stats.dwCount = 0;
  232. // Leave critical section
  233. LeaveCriticalSection(&pMC->m_crsVidQoS);
  234. if (pPacket) {
  235. pPacket->Recycle();
  236. pStream->Release(pPacket);
  237. pPacket = NULL;
  238. }
  239. timeKillEvent(timerID);
  240. CloseHandle (hEvent);
  241. // Ensure no outstanding preview frames
  242. pMC->EndSend();
  243. // stop and reset capture device
  244. pMediaCtrl->Reset ();
  245. // save real time so we can update the timestamp when we restart
  246. pMC->m_SavedTickCount = timeGetTime();
  247. MyEndThread:
  248. pMC->m_fSending = FALSE;
  249. DEBUGMSG (ZONE_DP, ("%s: Exiting.\r\n", _fx_));
  250. return hr;
  251. }
  252. DWORD RecvVideoStream::RenderingThread ( void)
  253. {
  254. HRESULT hr = DPR_SUCCESS;
  255. MediaPacket * pPacket;
  256. DWORD dwWait;
  257. DWORD rtpTs, rtpSyncTs;
  258. HANDLE hEvent;
  259. DWORD_PTR dwPropVal;
  260. UINT uTimeout = 0;
  261. UINT uGoodPacketsQueued = 0;
  262. RecvVideoStream *pMC = this;
  263. RxStream *pStream = pMC->m_RecvStream;
  264. MediaControl *pMediaCtrl = pMC->m_OutMedia;
  265. FX_ENTRY ("DP::RenderingTh")
  266. if (pStream == NULL || pMediaCtrl == NULL)
  267. {
  268. return DPR_INVALID_PARAMETER;
  269. }
  270. // get event handle
  271. pMediaCtrl->GetProp (MC_PROP_EVENT_HANDLE, &dwPropVal);
  272. hEvent = (HANDLE) dwPropVal;
  273. if (hEvent == NULL)
  274. {
  275. DEBUGMSG (ZONE_DP, ("%s: invalid event\r\n", _fx_));
  276. return DPR_CANT_CREATE_EVENT;
  277. }
  278. // get thresholds
  279. pMediaCtrl->GetProp (MC_PROP_TIMEOUT, &dwPropVal);
  280. uTimeout = (DWORD)dwPropVal;
  281. pMC->m_RecvStream->FastForward(FALSE); // flush receive queue
  282. // Notification is not used. if needed do it thru Channel
  283. //if (pMC->m_Connection)
  284. // pMC->m_Connection->DoNotification(CONNECTION_OPEN_REND);
  285. pMC->m_fReceiving = TRUE;
  286. // Since we dont have reliable sender RTP timestamps yet,
  287. // follow the simplistic approach of playing
  288. // back frames as soon as they are available
  289. // with no attempt at reconstructing the timing
  290. // The RecvVidThread will signal an event when
  291. // it has received and decoded a frame. We wake up on
  292. // that event and call GetNextPlay().
  293. // This will keep the Recv queue moving with the
  294. // latest decoded packet ready to be given to the
  295. // app for rendering.
  296. while (!(pMC->m_ThreadFlags & DPTFLAG_STOP_PLAY))
  297. {
  298. dwWait = WaitForSingleObject (hEvent, uTimeout);
  299. ASSERT(dwWait != WAIT_FAILED);
  300. // see why I don't need to wait
  301. if (dwWait != WAIT_TIMEOUT) {
  302. if (pMC->m_DPFlags & DPFLAG_AV_SYNC) {
  303. // find out the timestamp of the frame to be played
  304. //
  305. NTP_TS ntpTs;
  306. rtpSyncTs = 0;
  307. #ifdef OLDSTUFF
  308. if (m_Audio.pRecvStream && m_Audio.pRecvStream->GetCurrentPlayNTPTime(&ntpTs) == DPR_SUCCESS)
  309. pMC->m_Net->NTPtoRTP(ntpTs,&rtpSyncTs);
  310. #endif
  311. }
  312. while (pStream->NextPlayablePacketTime(&rtpTs)) {
  313. // there is a playable packet in the queue
  314. if ((pMC->m_DPFlags & DPFLAG_AV_SYNC) && rtpSyncTs != 0) {
  315. LOG((LOGMSG_TESTSYNC,rtpTs, rtpSyncTs));
  316. if (TS_LATER(rtpTs,rtpSyncTs))
  317. break; // its time has not come
  318. }
  319. // get the packet.
  320. pPacket = pStream->GetNextPlay ();
  321. if (pPacket != NULL)
  322. {
  323. if (pPacket->GetState () != MP_STATE_DECODED) {
  324. pPacket->Recycle();
  325. pStream->Release(pPacket);
  326. } else
  327. {
  328. LOG((LOGMSG_VID_PLAY,pPacket->GetIndex(), GetTickCount()));
  329. EnterCriticalSection(&pMC->m_crs);
  330. pPacket->SetState(MP_STATE_PLAYING_BACK);
  331. pMC->m_PlaybackTimestamp = pPacket->GetTimestamp();
  332. if (pMC->m_pNextPacketToRender) {
  333. if (!pMC->m_pNextPacketToRender->m_fRendering) {
  334. // the app is not referencing the frame.
  335. pMC->m_pNextPacketToRender->Recycle();
  336. pStream->Release(pMC->m_pNextPacketToRender);
  337. } else {
  338. // it will get Recycled and Released later when the app
  339. // calls ReleaseFrame()
  340. }
  341. uGoodPacketsQueued--;
  342. }
  343. pMC->m_pNextPacketToRender = pPacket;
  344. LeaveCriticalSection(&pMC->m_crs);
  345. if(pMC->m_pfFrameReadyCallback)
  346. {
  347. (pMC->m_pfFrameReadyCallback)((DWORD_PTR)pMC->m_hRenderEvent);
  348. }
  349. else if (pMC->m_hRenderEvent)
  350. SetEvent(pMC->m_hRenderEvent);
  351. uGoodPacketsQueued++;
  352. // Indicate that another frame was sent
  353. UPDATE_COUNTER(g_pctrVideoReceive, 1);
  354. }
  355. } // if (pPacket != NULL)
  356. } // while
  357. }
  358. }
  359. pMC->m_fReceiving = FALSE;
  360. // Notification is not used. if needed do it thru Channel
  361. //if (pMC->m_Connection)
  362. // pMC->m_Connection->DoNotification(CONNECTION_CLOSE_REND);
  363. // wait till all frames being rendered are returned
  364. // typically wont be more than one
  365. while (pMC->m_cRendering || pMC->m_pNextPacketToRender) {
  366. EnterCriticalSection(&pMC->m_crs);
  367. if (pMC->m_pNextPacketToRender && !pMC->m_pNextPacketToRender->m_fRendering) {
  368. // the app is not referencing the current frame.
  369. pMC->m_pNextPacketToRender->Recycle();
  370. pStream->Release(pMC->m_pNextPacketToRender);
  371. // no more frames till the thread is restarted
  372. pMC->m_pNextPacketToRender = NULL;
  373. LeaveCriticalSection(&pMC->m_crs);
  374. } else {
  375. // wait till the app Releases it
  376. //
  377. LeaveCriticalSection(&pMC->m_crs);
  378. Sleep(100);
  379. DEBUGMSG(ZONE_DP, ("%s: Waiting for final ReleaseFrame()\n",_fx_));
  380. }
  381. }
  382. // reset the event we're waiting on.
  383. ResetEvent (hEvent);
  384. DEBUGMSG(ZONE_DP, ("%s: Exiting.\n", _fx_));
  385. return hr;
  386. }
  387. DWORD SendVideoStream::Send(void)
  388. {
  389. BOOL fNewPreviewFrame = FALSE, bRet;
  390. MediaPacket *pVP;
  391. DWORD dwBeforeEncode;
  392. DWORD dwAfterEncode;
  393. UINT uBytesSent;
  394. MMRESULT mmr;
  395. DWORD dwEncodeFlags;
  396. #ifdef LOGSTATISTICS_ON
  397. char szDebug[256];
  398. DWORD dwDebugSaveBits;
  399. #endif
  400. while (pVP = m_SendStream->GetNext()) {
  401. EnterCriticalSection(&m_crs);
  402. if (m_pNextPacketToRender) {
  403. // free the last preview packet if its not being referenced
  404. // thru the IVideoRender API.
  405. // if it is being referenced ( fRendering is set), then it
  406. // will be freed in IVideoRender->ReleaseFrame()
  407. if (!m_pNextPacketToRender->m_fRendering) {
  408. m_pNextPacketToRender->Recycle();
  409. m_SendStream->Release(m_pNextPacketToRender);
  410. }
  411. }
  412. m_pNextPacketToRender = pVP;
  413. fNewPreviewFrame = TRUE;
  414. LeaveCriticalSection(&m_crs);
  415. if (!(m_ThreadFlags & DPTFLAG_PAUSE_SEND)) {
  416. dwBeforeEncode = timeGetTime();
  417. if (m_ThreadFlags & DPTFLAG_SEND_PREAMBLE)
  418. dwEncodeFlags = VCM_STREAMCONVERTF_FORCE_KEYFRAME;
  419. else
  420. dwEncodeFlags = 0;
  421. mmr = m_pVideoFilter->Convert((VideoPacket*)pVP, VP_ENCODE, dwEncodeFlags);
  422. if (mmr == MMSYSERR_NOERROR)
  423. {
  424. pVP->SetState(MP_STATE_ENCODED);
  425. }
  426. // Save the perfs in our stats structure for QoS
  427. dwAfterEncode = timeGetTime() - dwBeforeEncode;
  428. //HACKHACK bugbug, until we support fragmentation, set the marker bit always.
  429. pVP->SetProp (MP_PROP_PREAMBLE,TRUE);
  430. if (mmr == MMSYSERR_NOERROR)
  431. {
  432. SendPacket((VideoPacket*)pVP, &uBytesSent);
  433. }
  434. else
  435. {
  436. uBytesSent = 0;
  437. }
  438. // reset the packet and return it to the free queue
  439. pVP->m_fMark=0;
  440. pVP->SetState(MP_STATE_RESET);
  441. m_SendStream->Release(pVP);
  442. UPDATE_COUNTER(g_pctrVideoSendBytes, uBytesSent * 8);
  443. // Enter critical section: QoS thread also reads the statistics
  444. EnterCriticalSection(&m_crsVidQoS);
  445. // Add this compression time to total compression time
  446. // If we can access the CPU perf counters Ok, we won't use this value
  447. m_Stats.dwMsComp += dwAfterEncode;
  448. #ifdef LOGSTATISTICS_ON
  449. dwDebugSaveBits = m_Stats.dwBits;
  450. #endif
  451. // Add this new frame size to the cumulated size
  452. m_Stats.dwBits += uBytesSent * 8;
  453. #ifdef LOGSTATISTICS_ON
  454. wsprintf(szDebug, " V: dwBits = %ld up from %ld (file: %s line: %ld)\r\n", m_Stats.dwBits, dwDebugSaveBits, __FILE__, __LINE__);
  455. OutputDebugString(szDebug);
  456. #endif
  457. // Leave critical section
  458. LeaveCriticalSection(&m_crsVidQoS);
  459. //LOG((LOGMSG_SENT,GetTickCount()));
  460. }
  461. //m_SendStream->Release(pVP);
  462. }
  463. // Signal the IVideoRender event if we have a new frame.
  464. if (fNewPreviewFrame)
  465. {
  466. if(m_pfFrameReadyCallback)
  467. {
  468. (m_pfFrameReadyCallback)((DWORD_PTR)m_hRenderEvent);
  469. }
  470. else if(m_hRenderEvent)
  471. SetEvent(m_hRenderEvent);
  472. }
  473. return DPR_SUCCESS;
  474. }
  475. /* Wait till all preview packets are released by the UI.
  476. Typically there wont be more than one
  477. */
  478. void SendVideoStream::EndSend()
  479. {
  480. while (m_cRendering || m_pNextPacketToRender) {
  481. EnterCriticalSection(&m_crs);
  482. // free the last preview packet if its not being referenced
  483. // thru the IVideoRender API.
  484. if (m_pNextPacketToRender && !m_pNextPacketToRender->m_fRendering) {
  485. m_pNextPacketToRender->Recycle();
  486. m_SendStream->Release(m_pNextPacketToRender);
  487. m_pNextPacketToRender = NULL;
  488. LeaveCriticalSection(&m_crs);
  489. } else {
  490. LeaveCriticalSection(&m_crs);
  491. Sleep(100);
  492. DEBUGMSG(ZONE_DP,("DP::EndSendVideo: Waiting for final Release Frame\n"));
  493. }
  494. }
  495. }
  496. HRESULT SendVideoStream::SendPacket(VideoPacket *pVP, UINT *puBytesSent)
  497. {
  498. PS_QUEUE_ELEMENT psq;
  499. UINT uLength;
  500. DWORD dwPacketSize = 0;
  501. DWORD dwHdrSize = 0;
  502. DWORD dwHdrSizeAlloc = 0;
  503. DWORD dwPacketCount = 0;
  504. int nPacketsSent=0;
  505. UINT uPacketIndex, fMark=0;
  506. MMRESULT mmr;
  507. PBYTE pHdrInfo, netData, netDataPacket;
  508. *puBytesSent = 0;
  509. if (pVP->GetState() != MP_STATE_ENCODED)
  510. {
  511. DEBUGMSG (ZONE_VCM, ("SendVideoStream::SendPacket: Packet not compressed\r\n"));
  512. return E_FAIL;
  513. }
  514. // m_Net->QueryInterface(IID_IRTPSend, (void**)&pIRTPSend);
  515. ASSERT(m_pRTPSend);
  516. // these stay the same for video
  517. psq.pMP = pVP;
  518. psq.dwPacketType = PS_VIDEO;
  519. // psq.pRTPSend = pIRTPSend;
  520. psq.pRTPSend = m_pRTPSend;
  521. pVP->GetNetData((void**)(&netData), &uLength);
  522. ASSERT(netData);
  523. m_pVideoFilter->GetPayloadHeaderSize(&dwHdrSizeAlloc);
  524. do
  525. {
  526. if (dwHdrSizeAlloc)
  527. {
  528. pHdrInfo = (BYTE*)MemAlloc(dwHdrSizeAlloc);
  529. }
  530. if(pHdrInfo == NULL)
  531. {
  532. return E_FAIL;
  533. }
  534. mmr = m_pVideoFilter->FormatPayload(netData,
  535. uLength,
  536. &netDataPacket,
  537. &dwPacketSize,
  538. &dwPacketCount,
  539. &fMark,
  540. &pHdrInfo,
  541. &dwHdrSize);
  542. if (mmr == MMSYSERR_NOERROR)
  543. {
  544. psq.data = netDataPacket;
  545. psq.dwSize = dwPacketSize;
  546. psq.fMark = fMark;
  547. psq.pHeaderInfo = pHdrInfo;
  548. psq.dwHdrSize = dwHdrSize;
  549. m_pDP->m_PacketSender.m_SendQueue.PushRear(psq);
  550. *puBytesSent = *puBytesSent + dwPacketSize + sizeof(RTP_HDR) + IP_HEADER_SIZE + UDP_HEADER_SIZE;
  551. }
  552. else
  553. {
  554. MemFree((BYTE *)pHdrInfo);
  555. }
  556. } while (mmr == MMSYSERR_NOERROR);
  557. while (m_pDP->m_PacketSender.SendPacket())
  558. {
  559. ;
  560. }
  561. // pIRTPSend->Release();
  562. return S_OK;
  563. };
  564.