BaseMuxerInputPin.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:7k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2005 Gabest
  3.  * http://www.gabest.org
  4.  *
  5.  *  This Program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2, or (at your option)
  8.  *  any later version.
  9.  *   
  10.  *  This Program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  *  GNU General Public License for more details.
  14.  *   
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21. #include "StdAfx.h"
  22. #include <mmreg.h>
  23. #include "BaseMuxer.h"
  24. #include "......DSUtilDSUtil.h"
  25. #include "........includemoreuuids.h"
  26. #include <initguid.h>
  27. #include "........includeoggOggDS.h"
  28. #define MAXQUEUESIZE 100
  29. //
  30. // CBaseMuxerInputPin
  31. //
  32. CBaseMuxerInputPin::CBaseMuxerInputPin(LPCWSTR pName, CBaseFilter* pFilter, CCritSec* pLock, HRESULT* phr)
  33. : CBaseInputPin(NAME("CBaseMuxerInputPin"), pFilter, pLock, phr, pName)
  34. , m_rtDuration(0)
  35. , m_evAcceptPacket(TRUE)
  36. {
  37. static int s_iID = 0;
  38. m_iID = s_iID++;
  39. }
  40. CBaseMuxerInputPin::~CBaseMuxerInputPin()
  41. {
  42. }
  43. STDMETHODIMP CBaseMuxerInputPin::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  44. {
  45. CheckPointer(ppv, E_POINTER);
  46. return 
  47. QI(IPropertyBag)
  48. QI(IPropertyBag2)
  49. QI(IDSMPropertyBag)
  50. __super::NonDelegatingQueryInterface(riid, ppv);
  51. }
  52. bool CBaseMuxerInputPin::IsSubtitleStream()
  53. {
  54. return m_mt.majortype == MEDIATYPE_Subtitle || m_mt.majortype == MEDIATYPE_Text;
  55. }
  56. void CBaseMuxerInputPin::PushPacket(CAutoPtr<MuxerPacket> pPacket)
  57. {
  58. for(int i = 0; m_pFilter->IsActive() && !m_bFlushing
  59. && !m_evAcceptPacket.Wait(1) 
  60. && i < 1000; 
  61. i++);
  62. if(!m_pFilter->IsActive() || m_bFlushing)
  63. return;
  64. CAutoLock cAutoLock(&m_csQueue);
  65. m_queue.AddTail(pPacket);
  66. if(m_queue.GetCount() >= MAXQUEUESIZE)
  67. m_evAcceptPacket.Reset();
  68. }
  69. CAutoPtr<MuxerPacket> CBaseMuxerInputPin::PopPacket()
  70. {
  71. CAutoPtr<MuxerPacket> pPacket;
  72. CAutoLock cAutoLock(&m_csQueue);
  73. if(m_queue.GetCount()) 
  74. pPacket = m_queue.RemoveHead();
  75. if(m_queue.GetCount() < MAXQUEUESIZE)
  76. m_evAcceptPacket.Set();
  77. return pPacket;
  78. }
  79. HRESULT CBaseMuxerInputPin::CheckMediaType(const CMediaType* pmt)
  80. {
  81. if(pmt->formattype == FORMAT_WaveFormatEx)
  82. {
  83. WORD wFormatTag = ((WAVEFORMATEX*)pmt->pbFormat)->wFormatTag;
  84. if((wFormatTag == WAVE_FORMAT_PCM 
  85. || wFormatTag == WAVE_FORMAT_EXTENSIBLE
  86. || wFormatTag == WAVE_FORMAT_IEEE_FLOAT)
  87. && pmt->subtype != FOURCCMap(wFormatTag)
  88. && pmt->subtype != MEDIASUBTYPE_DVD_LPCM_AUDIO
  89. && pmt->subtype != MEDIASUBTYPE_DOLBY_AC3
  90. && pmt->subtype != MEDIASUBTYPE_DTS)
  91. {
  92. return E_INVALIDARG;
  93. }
  94. }
  95. return pmt->majortype == MEDIATYPE_Video
  96. || pmt->majortype == MEDIATYPE_Audio && pmt->formattype != FORMAT_VorbisFormat
  97. || pmt->majortype == MEDIATYPE_Text && pmt->subtype == MEDIASUBTYPE_NULL && pmt->formattype == FORMAT_None
  98. || pmt->majortype == MEDIATYPE_Subtitle
  99. ? S_OK
  100. : E_INVALIDARG;
  101. }
  102. HRESULT CBaseMuxerInputPin::BreakConnect()
  103. {
  104. HRESULT hr = __super::BreakConnect();
  105. if(FAILED(hr)) return hr;
  106. RemoveAll();
  107. // TODO: remove extra disconnected pins, leave one
  108. return hr;
  109. }
  110. HRESULT CBaseMuxerInputPin::CompleteConnect(IPin* pReceivePin)
  111. {
  112. HRESULT hr = __super::CompleteConnect(pReceivePin);
  113. if(FAILED(hr)) return hr;
  114. // duration
  115. m_rtDuration = 0;
  116. CComQIPtr<IMediaSeeking> pMS;
  117. if((pMS = GetFilterFromPin(pReceivePin)) || (pMS = pReceivePin))
  118. pMS->GetDuration(&m_rtDuration);
  119. // properties
  120. for(CComPtr<IPin> pPin = pReceivePin; pPin; pPin = GetUpStreamPin(GetFilterFromPin(pPin)))
  121. {
  122. if(CComQIPtr<IDSMPropertyBag> pPB = pPin)
  123. {
  124. ULONG cProperties = 0;
  125. if(SUCCEEDED(pPB->CountProperties(&cProperties)) && cProperties > 0)
  126. {
  127. for(ULONG iProperty = 0; iProperty < cProperties; iProperty++)
  128. {
  129. PROPBAG2 PropBag;
  130. memset(&PropBag, 0, sizeof(PropBag));
  131. ULONG cPropertiesReturned = 0;
  132. if(FAILED(pPB->GetPropertyInfo(iProperty, 1, &PropBag, &cPropertiesReturned)))
  133. continue;
  134. HRESULT hr;
  135. CComVariant var;
  136. if(SUCCEEDED(pPB->Read(1, &PropBag, NULL, &var, &hr)) && SUCCEEDED(hr))
  137. SetProperty(PropBag.pstrName, &var);
  138. CoTaskMemFree(PropBag.pstrName);
  139. }
  140. }
  141. }
  142. }
  143. ((CBaseMuxerFilter*)m_pFilter)->AddInput();
  144. return S_OK;
  145. }
  146. HRESULT CBaseMuxerInputPin::Active()
  147. {
  148. m_rtMaxStart = _I64_MIN;
  149. m_fEOS = false;
  150. m_evAcceptPacket.Set();
  151. return __super::Active();
  152. }
  153. HRESULT CBaseMuxerInputPin::Inactive()
  154. {
  155. CAutoLock cAutoLock(&m_csQueue);
  156. m_queue.RemoveAll();
  157. return __super::Inactive();
  158. }
  159. STDMETHODIMP CBaseMuxerInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
  160. {
  161. CAutoLock cAutoLock(&m_csReceive);
  162. return __super::NewSegment(tStart, tStop, dRate);
  163. }
  164. STDMETHODIMP CBaseMuxerInputPin::Receive(IMediaSample* pSample)
  165. {
  166. CAutoLock cAutoLock(&m_csReceive);
  167. HRESULT hr = __super::Receive(pSample);
  168. if(FAILED(hr)) return hr;
  169. CAutoPtr<MuxerPacket> pPacket(new MuxerPacket(this));
  170. long len = pSample->GetActualDataLength();
  171. BYTE* pData = NULL;
  172. if(FAILED(pSample->GetPointer(&pData)) || !pData)
  173. return S_OK;
  174. pPacket->pData.SetSize(len);
  175. memcpy(pPacket->pData.GetData(), pData, len);
  176. if(S_OK == pSample->IsSyncPoint() || m_mt.majortype == MEDIATYPE_Audio && !m_mt.bTemporalCompression)
  177. {
  178. pPacket->flags |= MuxerPacket::syncpoint;
  179. }
  180. if(S_OK == pSample->GetTime(&pPacket->rtStart, &pPacket->rtStop))
  181. {
  182. pPacket->flags |= MuxerPacket::timevalid;
  183. pPacket->rtStart += m_tStart; 
  184. pPacket->rtStop += m_tStart;
  185. if((pPacket->flags & MuxerPacket::syncpoint) && pPacket->rtStart < m_rtMaxStart)
  186. {
  187. pPacket->flags &= ~MuxerPacket::syncpoint;
  188. pPacket->flags |= MuxerPacket::bogus;
  189. }
  190. m_rtMaxStart = max(m_rtMaxStart,  pPacket->rtStart);
  191. }
  192. if(S_OK == pSample->IsDiscontinuity())
  193. {
  194. pPacket->flags |= MuxerPacket::discontinuity;
  195. }
  196. PushPacket(pPacket);
  197. return S_OK;
  198. }
  199. STDMETHODIMP CBaseMuxerInputPin::EndOfStream()
  200. {
  201. CAutoLock cAutoLock(&m_csReceive);
  202. HRESULT hr = __super::EndOfStream();
  203. if(FAILED(hr)) return hr;
  204. ASSERT(!m_fEOS);
  205. CAutoPtr<MuxerPacket> pPacket(new MuxerPacket(this));
  206. pPacket->flags |= MuxerPacket::eos;
  207. PushPacket(pPacket);
  208. m_fEOS = true;
  209. return hr;
  210. }