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.

132 lines
4.0 KiB

  1. // Copyright (c) 1997 - 1998 Microsoft Corporation. All Rights Reserved.
  2. // Pump.cpp : Implementation of CStream
  3. #include "stdafx.h"
  4. #include "project.h"
  5. DWORD WINAPI WritePumpThreadStart(void *pvPump)
  6. {
  7. return ((CPump *)pvPump)->PumpMainLoop();
  8. }
  9. CPump::CPump(CStream *pStream) :
  10. m_pStream(pStream),
  11. m_hThread(NULL),
  12. m_hRunEvent(NULL),
  13. m_bShutDown(false)
  14. {}
  15. CPump::~CPump()
  16. {
  17. if (m_hThread) {
  18. m_CritSec.Lock();
  19. m_bShutDown = true;
  20. Run(true);
  21. m_CritSec.Unlock();
  22. WaitForSingleObject(m_hThread, INFINITE);
  23. }
  24. if (m_hRunEvent) {
  25. CloseHandle(m_hRunEvent);
  26. }
  27. }
  28. HRESULT CPump::CreatePump(CStream *pStream, CPump **ppPump)
  29. {
  30. CPump *pPump = new CPump(pStream);
  31. if (pPump) {
  32. pPump->m_hRunEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  33. if (pPump->m_hRunEvent) {
  34. DWORD dwId;
  35. pPump->m_hThread = CreateThread(NULL, 0, WritePumpThreadStart, (void *)pPump, 0, &dwId);
  36. if (pPump->m_hThread) {
  37. *ppPump = pPump;
  38. return S_OK;
  39. }
  40. }
  41. delete pPump;
  42. }
  43. *ppPump = pPump;
  44. return E_OUTOFMEMORY;
  45. }
  46. void CPump::Run(bool bRunning)
  47. {
  48. if (bRunning) {
  49. SetEvent(m_hRunEvent);
  50. } else {
  51. ResetEvent(m_hRunEvent);
  52. }
  53. }
  54. HRESULT CPump::PumpMainLoop()
  55. {
  56. while (true) {
  57. WaitForSingleObject(m_hRunEvent, INFINITE);
  58. m_CritSec.Lock();
  59. bool bShutDown = m_bShutDown;
  60. m_CritSec.Unlock();
  61. if (bShutDown) {
  62. return 0;
  63. }
  64. IMediaSample *pMediaSample;
  65. HRESULT hr = m_pStream->GetBuffer(&pMediaSample, NULL, NULL, 0);
  66. if (SUCCEEDED(hr)) {
  67. LONG lChopSize = m_pStream->GetChopSize();
  68. HRESULT hrReceived = S_OK;
  69. if (lChopSize != 0) {
  70. // Send data in smaller batches generating
  71. // appropriate timestamps
  72. CMediaSample *pSample = (CMediaSample *)pMediaSample;
  73. PBYTE pbStart;
  74. pMediaSample->GetPointer(&pbStart);
  75. // Make these const so we don't accidentally
  76. // update them
  77. PBYTE pbCurrent = pbStart;
  78. const LONG lLength = pSample->GetActualDataLength();
  79. const LONG lSize = pSample->GetSize();
  80. const REFERENCE_TIME rtStart = pSample->m_rtStartTime;
  81. const REFERENCE_TIME rtStop = pSample->m_rtEndTime;
  82. LONG lLeft = lLength;
  83. while (lLeft != 0) {
  84. LONG lToSend = min(lLeft, lChopSize);
  85. pSample->SetActualDataLength(lToSend);
  86. pSample->SetSizeAndPointer(pbCurrent, lToSend, lToSend);
  87. pSample->m_rtEndTime =
  88. pSample->m_rtStartTime +
  89. MulDiv((LONG)(rtStop -
  90. pSample->m_rtStartTime),
  91. lToSend,
  92. lLeft);
  93. hrReceived = m_pStream->m_pConnectedMemInputPin->Receive(pMediaSample);
  94. if (S_OK != hrReceived) {
  95. break;
  96. }
  97. pbCurrent += lToSend;
  98. pSample->m_rtStartTime = pSample->m_rtEndTime;
  99. lLeft -= lToSend;
  100. }
  101. // Put everything back
  102. pSample->m_rtStartTime = rtStart;
  103. pSample->m_rtEndTime = rtStop;
  104. pSample->SetSizeAndPointer(pbStart, lLength, lSize);
  105. } else {
  106. hrReceived = m_pStream->m_pConnectedMemInputPin->Receive(pMediaSample);
  107. }
  108. CSample *pSample = ((CMediaSample *)pMediaSample)->m_pSample;
  109. pSample->m_bReceived = true;
  110. if (hrReceived != S_OK) {
  111. AtlTrace(_T("Receive returned %i. Aborting I/O operation/n"), hrReceived);
  112. pSample->m_MediaSampleIoStatus = E_ABORT;
  113. }
  114. pMediaSample->Release();
  115. }
  116. };
  117. }