BaseMuxerInputPin.cpp

00001 /* 
00002  *      Copyright (C) 2003-2005 Gabest
00003  *      http://www.gabest.org
00004  *
00005  *  This Program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2, or (at your option)
00008  *  any later version.
00009  *   
00010  *  This Program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013  *  GNU General Public License for more details.
00014  *   
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with GNU Make; see the file COPYING.  If not, write to
00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
00018  *  http://www.gnu.org/copyleft/gpl.html
00019  *
00020  */
00021 
00022 #include "StdAfx.h"
00023 #include <mmreg.h>
00024 #include "BaseMuxer.h"
00025 #include "..\..\..\DSUtil\DSUtil.h"
00026 #include "..\..\..\..\include\moreuuids.h"
00027 
00028 #include <initguid.h>
00029 #include "..\..\..\..\include\ogg\OggDS.h"
00030 
00031 #define MAXQUEUESIZE 100
00032 
00033 //
00034 // CBaseMuxerInputPin
00035 //
00036 
00037 CBaseMuxerInputPin::CBaseMuxerInputPin(LPCWSTR pName, CBaseFilter* pFilter, CCritSec* pLock, HRESULT* phr)
00038         : CBaseInputPin(NAME("CBaseMuxerInputPin"), pFilter, pLock, phr, pName)
00039         , m_rtDuration(0)
00040         , m_evAcceptPacket(TRUE)
00041 {
00042         static int s_iID = 0;
00043         m_iID = s_iID++;
00044 }
00045 
00046 CBaseMuxerInputPin::~CBaseMuxerInputPin()
00047 {
00048 }
00049 
00050 STDMETHODIMP CBaseMuxerInputPin::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00051 {
00052         CheckPointer(ppv, E_POINTER);
00053 
00054         return 
00055                 QI(IPropertyBag)
00056                 QI(IPropertyBag2)
00057                 QI(IDSMPropertyBag)
00058                 __super::NonDelegatingQueryInterface(riid, ppv);
00059 }
00060 
00061 bool CBaseMuxerInputPin::IsSubtitleStream()
00062 {
00063         return m_mt.majortype == MEDIATYPE_Subtitle || m_mt.majortype == MEDIATYPE_Text;
00064 }
00065 
00066 void CBaseMuxerInputPin::PushPacket(CAutoPtr<MuxerPacket> pPacket)
00067 {
00068         for(int i = 0; m_pFilter->IsActive() && !m_bFlushing
00069                 && !m_evAcceptPacket.Wait(1) 
00070                 && i < 1000; 
00071                 i++);
00072 
00073         if(!m_pFilter->IsActive() || m_bFlushing)
00074                 return;
00075 
00076         CAutoLock cAutoLock(&m_csQueue);
00077 
00078         m_queue.AddTail(pPacket);
00079 
00080         if(m_queue.GetCount() >= MAXQUEUESIZE)
00081                 m_evAcceptPacket.Reset();
00082 }
00083 
00084 CAutoPtr<MuxerPacket> CBaseMuxerInputPin::PopPacket()
00085 {
00086         CAutoPtr<MuxerPacket> pPacket;
00087 
00088         CAutoLock cAutoLock(&m_csQueue);
00089 
00090         if(m_queue.GetCount()) 
00091                 pPacket = m_queue.RemoveHead();
00092         if(m_queue.GetCount() < MAXQUEUESIZE)
00093                 m_evAcceptPacket.Set();
00094 
00095         return pPacket;
00096 }
00097 
00098 HRESULT CBaseMuxerInputPin::CheckMediaType(const CMediaType* pmt)
00099 {
00100         if(pmt->formattype == FORMAT_WaveFormatEx)
00101         {
00102                 WORD wFormatTag = ((WAVEFORMATEX*)pmt->pbFormat)->wFormatTag;
00103                 if((wFormatTag == WAVE_FORMAT_PCM 
00104                 || wFormatTag == WAVE_FORMAT_EXTENSIBLE
00105                 || wFormatTag == WAVE_FORMAT_IEEE_FLOAT)
00106                 && pmt->subtype != FOURCCMap(wFormatTag)
00107                 && pmt->subtype != MEDIASUBTYPE_DVD_LPCM_AUDIO
00108                 && pmt->subtype != MEDIASUBTYPE_DOLBY_AC3
00109                 && pmt->subtype != MEDIASUBTYPE_DTS)
00110                 {
00111                         return E_INVALIDARG;
00112                 }
00113         }
00114 
00115         return pmt->majortype == MEDIATYPE_Video
00116                 || pmt->majortype == MEDIATYPE_Audio && pmt->formattype != FORMAT_VorbisFormat
00117                 || pmt->majortype == MEDIATYPE_Text && pmt->subtype == MEDIASUBTYPE_NULL && pmt->formattype == FORMAT_None
00118                 || pmt->majortype == MEDIATYPE_Subtitle
00119                 ? S_OK
00120                 : E_INVALIDARG;
00121 }
00122 
00123 HRESULT CBaseMuxerInputPin::BreakConnect()
00124 {
00125         HRESULT hr = __super::BreakConnect();
00126         if(FAILED(hr)) return hr;
00127 
00128         RemoveAll();
00129 
00130         // TODO: remove extra disconnected pins, leave one
00131 
00132         return hr;
00133 }
00134 
00135 HRESULT CBaseMuxerInputPin::CompleteConnect(IPin* pReceivePin)
00136 {
00137         HRESULT hr = __super::CompleteConnect(pReceivePin);
00138         if(FAILED(hr)) return hr;
00139 
00140         // duration
00141 
00142         m_rtDuration = 0;
00143         CComQIPtr<IMediaSeeking> pMS;
00144         if((pMS = GetFilterFromPin(pReceivePin)) || (pMS = pReceivePin))
00145                 pMS->GetDuration(&m_rtDuration);
00146 
00147         // properties
00148 
00149         for(CComPtr<IPin> pPin = pReceivePin; pPin; pPin = GetUpStreamPin(GetFilterFromPin(pPin)))
00150         {
00151                 if(CComQIPtr<IDSMPropertyBag> pPB = pPin)
00152                 {
00153                         ULONG cProperties = 0;
00154                         if(SUCCEEDED(pPB->CountProperties(&cProperties)) && cProperties > 0)
00155                         {
00156                                 for(ULONG iProperty = 0; iProperty < cProperties; iProperty++)
00157                                 {
00158                                         PROPBAG2 PropBag;
00159                                         memset(&PropBag, 0, sizeof(PropBag));
00160                                         ULONG cPropertiesReturned = 0;
00161                                         if(FAILED(pPB->GetPropertyInfo(iProperty, 1, &PropBag, &cPropertiesReturned)))
00162                                                 continue;
00163 
00164                                         HRESULT hr;
00165                                         CComVariant var;
00166                                         if(SUCCEEDED(pPB->Read(1, &PropBag, NULL, &var, &hr)) && SUCCEEDED(hr))
00167                                                 SetProperty(PropBag.pstrName, &var);
00168 
00169                                         CoTaskMemFree(PropBag.pstrName);
00170                                 }
00171                         }
00172                 }
00173         }
00174 
00175         ((CBaseMuxerFilter*)m_pFilter)->AddInput();
00176 
00177         return S_OK;
00178 }
00179 
00180 HRESULT CBaseMuxerInputPin::Active()
00181 {
00182         m_rtMaxStart = _I64_MIN;
00183         m_fEOS = false;
00184         m_evAcceptPacket.Set();
00185         return __super::Active();
00186 }
00187 
00188 HRESULT CBaseMuxerInputPin::Inactive()
00189 {
00190         CAutoLock cAutoLock(&m_csQueue);
00191         m_queue.RemoveAll();
00192         return __super::Inactive();
00193 }
00194 
00195 STDMETHODIMP CBaseMuxerInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
00196 {
00197         CAutoLock cAutoLock(&m_csReceive);
00198 
00199         return __super::NewSegment(tStart, tStop, dRate);
00200 }
00201 
00202 STDMETHODIMP CBaseMuxerInputPin::Receive(IMediaSample* pSample)
00203 {
00204         CAutoLock cAutoLock(&m_csReceive);
00205 
00206         HRESULT hr = __super::Receive(pSample);
00207         if(FAILED(hr)) return hr;
00208 
00209         CAutoPtr<MuxerPacket> pPacket(new MuxerPacket(this));
00210 
00211         long len = pSample->GetActualDataLength();
00212 
00213         BYTE* pData = NULL;
00214         if(FAILED(pSample->GetPointer(&pData)) || !pData)
00215                 return S_OK;
00216 
00217         pPacket->pData.SetSize(len);
00218         memcpy(pPacket->pData.GetData(), pData, len);
00219 
00220         if(S_OK == pSample->IsSyncPoint() || m_mt.majortype == MEDIATYPE_Audio && !m_mt.bTemporalCompression)
00221         {
00222                 pPacket->flags |= MuxerPacket::syncpoint;
00223         }
00224 
00225         if(S_OK == pSample->GetTime(&pPacket->rtStart, &pPacket->rtStop))
00226         {
00227                 pPacket->flags |= MuxerPacket::timevalid;
00228 
00229                 pPacket->rtStart += m_tStart; 
00230                 pPacket->rtStop += m_tStart;
00231 
00232                 if((pPacket->flags & MuxerPacket::syncpoint) && pPacket->rtStart < m_rtMaxStart)
00233                 {
00234                         pPacket->flags &= ~MuxerPacket::syncpoint;
00235                         pPacket->flags |= MuxerPacket::bogus;
00236                 }
00237 
00238                 m_rtMaxStart = max(m_rtMaxStart,  pPacket->rtStart);
00239         }
00240 
00241         if(S_OK == pSample->IsDiscontinuity())
00242         {
00243                 pPacket->flags |= MuxerPacket::discontinuity;
00244         }
00245 
00246         PushPacket(pPacket);
00247 
00248         return S_OK;
00249 }
00250 
00251 STDMETHODIMP CBaseMuxerInputPin::EndOfStream()
00252 {
00253         CAutoLock cAutoLock(&m_csReceive);
00254 
00255         HRESULT hr = __super::EndOfStream();
00256         if(FAILED(hr)) return hr;
00257 
00258         ASSERT(!m_fEOS);
00259 
00260         CAutoPtr<MuxerPacket> pPacket(new MuxerPacket(this));
00261         pPacket->flags |= MuxerPacket::eos;
00262         PushPacket(pPacket);
00263 
00264         m_fEOS = true;
00265 
00266         return hr;
00267 }
00268 

Generated on Tue Dec 13 14:47:08 2005 for guliverkli by  doxygen 1.4.5