📄 splitter.cpp
字号:
//==========================================================================;//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR// PURPOSE.//// Copyright (c) 1996 - 1997 Microsoft Corporation. All Rights Reserved.////--------------------------------------------------------------------------;#include "stdafx.h"#include <streams.h>#include "pullpin.h"#include "alloc.h"#include "splitter.h"/* Ignore warnings about this pointers being used in member initialization lists*/#pragma warning(disable:4355)/* Splitter output pin methds *//* -- Constructor -- */CSplitterOutputPin::CSplitterOutputPin( CBaseSplitterFilter *pFilter, HRESULT *phr, LPCWSTR pName) : CBaseOutputPin( NAME("CSplitterOutputPin"), pFilter, &pFilter->m_csFilter, phr, pName), m_Notify(this), m_bDiscontinuity(FALSE), m_pOutputQueue(NULL), m_lTypes(NAME("CSplitterFilter::m_lTypes")){}CSplitterOutputPin::~CSplitterOutputPin(){ while (m_lTypes.GetCount() != 0) { delete m_lTypes.RemoveHead(); }}/* Override revert to normal ref counting These pins cannot be finally Release()'d while the input pin is connected */STDMETHODIMP_(ULONG)CSplitterOutputPin::NonDelegatingAddRef(){ return CUnknown::NonDelegatingAddRef();}/* Override to do normal ref counting */STDMETHODIMP_(ULONG)CSplitterOutputPin::NonDelegatingRelease(){ return CUnknown::NonDelegatingRelease();}STDMETHODIMP CSplitterOutputPin::Notify(IBaseFilter* pSender, Quality q){
return S_OK;
}// override this to set the buffer size and count. Return an error// if the size/count is not to your liking.HRESULT CSplitterOutputPin::DecideBufferSize( IMemAllocator * pAlloc, ALLOCATOR_PROPERTIES * pProp){ pProp->cBuffers = 100; pProp->cbBuffer = 65536; /* Don't care about size */ pProp->cbAlign = 1; pProp->cbPrefix = 0; ALLOCATOR_PROPERTIES propActual; return pAlloc->SetProperties(pProp, &propActual);}//// Override DecideAllocator because we insist on our own allocator since// it's 0 cost in terms of bytes//HRESULT CSplitterOutputPin::DecideAllocator( IMemInputPin *pPin, IMemAllocator **ppAlloc){ HRESULT hr = InitAllocator(ppAlloc); if (SUCCEEDED(hr)) { ALLOCATOR_PROPERTIES propRequest; ZeroMemory(&propRequest, sizeof(propRequest)); hr = DecideBufferSize(*ppAlloc, &propRequest); if (SUCCEEDED(hr)) { // tell downstream pins that modification // in-place is not permitted hr = pPin->NotifyAllocator(*ppAlloc, TRUE); if (SUCCEEDED(hr)) { return NOERROR; } } } /* Likewise we may not have an interface to release */ if (*ppAlloc) { (*ppAlloc)->Release(); *ppAlloc = NULL; } return hr;}// override this to control the connection// We use the subsample allocator derived from the input pin's allocatorHRESULT CSplitterOutputPin::InitAllocator(IMemAllocator **ppAlloc){ ASSERT(m_pAllocator == NULL); HRESULT hr = NOERROR; *ppAlloc = new CSubAllocator(NULL, &hr, Filter()->Allocator()); if (*ppAlloc == NULL) { return E_OUTOFMEMORY; } if (FAILED(hr)) { delete *ppAlloc; *ppAlloc = NULL; return hr; } /* Get a reference counted IID_IMemAllocator interface */ (*ppAlloc)->AddRef(); return NOERROR;}// Check if we accept a media type - only accept 1 for nowHRESULT CSplitterOutputPin::CheckMediaType(const CMediaType *pmt){ POSITION pos = m_lTypes.GetHeadPosition(); while (pos) { CMediaType *pmtList = m_lTypes.GetNext(pos); if (*pmtList == *pmt) { return S_OK; } } return S_FALSE;}// returns the preferred formats for a pinHRESULT CSplitterOutputPin::GetMediaType( int iPosition, CMediaType *pMediaType){ POSITION pos = m_lTypes.GetHeadPosition(); while (pos) { CMediaType *pmtList = m_lTypes.GetNext(pos); if (iPosition-- == 0) { *pMediaType = *pmtList; return S_OK; } } return VFW_S_NO_MORE_ITEMS;}/* Add a media type that's supported */HRESULT CSplitterOutputPin::AddMediaType( CMediaType const *pmt){ CMediaType *pmtNew = new CMediaType(*pmt); if (pmtNew) { if (m_lTypes.AddTail(pmtNew)) { return S_OK; } } delete pmtNew; return E_OUTOFMEMORY;}/* Output pin - Deliver a sample */HRESULT CSplitterOutputPin::SendSample( const BYTE * pbData, LONG lData, REFERENCE_TIME rtStart, BOOL bSync){ /* Get a sample from the allocator */ if (!IsConnected()) { return S_FALSE; } CMediaSample *pSample = Allocator()->GetSample((PBYTE)pbData, lData); ASSERT(pSample != NULL); if (bSync) { REFERENCE_TIME rtStop = rtStart + 1; pSample->SetTime(&rtStart, &rtStop); /* Allow for some decoders that only take not of sync points */ pSample->SetSyncPoint(TRUE); } /* First send newsegment etc if discontinuity */ if (m_bDiscontinuity) { m_bDiscontinuity = FALSE; pSample->SetDiscontinuity(TRUE); /* HACK - fix this for seeking */ m_pOutputQueue->NewSegment(0, 0x7F00000000000000, 1.0); } /* Output queue will release the sample */ return m_pOutputQueue->Receive(pSample);}/* Base splitter class methods *//* -- Constructor -- */CBaseSplitterFilter::CBaseSplitterFilter( TCHAR *pName, LPUNKNOWN pUnk, REFCLSID rclsid, HRESULT *phr) : CBaseFilter(pName, pUnk, &m_csFilter, rclsid, phr), m_OutputPins(NAME("CBaseSplitterFilter::m_OutputPins")), m_Notify(this), m_pInput(NULL), m_pParser(NULL){}/* -- Destructor -- */CBaseSplitterFilter::~CBaseSplitterFilter(){ ASSERT(m_State == State_Stopped); /* -- Destroy all pins */ DestroyInputPin(); DestroyOutputPins();}//// Override Pause() so we can prevent the input pin from starting// the puller before we're ready (ie have exited stopped state)//// Starting the puller in Active() caused a hole where the first// samples could be rejected becase we seemed to be in 'stopped'// state//STDMETHODIMPCBaseSplitterFilter::Pause(){ CAutoLock lockFilter(&m_csFilter); if (m_State == State_Stopped) { // and do the normal inactive processing POSITION pos = m_OutputPins.GetHeadPosition(); while (pos) { CSplitterOutputPin *pPin = m_OutputPins.GetNext(pos); if (pPin->IsConnected()) { pPin->Active(); } } CAutoLock lockStreaming(&m_csStream); // Activate our input pin only if we're connected if (m_pInput->IsConnected()) { m_pInput->Active(); } m_State = State_Paused; // Initialize our state ResetAllocatorAndParser(); } else { m_State = State_Paused; } return S_OK;}/* Stop the filter We override this for efficiency and so that we can manage the locking correctly*/STDMETHODIMP CBaseSplitterFilter::Stop(){ // must get this one first - it serializes state changes CAutoLock lockFilter(&m_csFilter); if (m_State == State_Stopped) { return NOERROR; } // decommit the input pin or we can deadlock if (m_pInput != NULL) { m_pInput->Inactive(); } // now hold the Receive critsec to prevent further Receive and EOS calls, CAutoLock lockStreaming(&m_csStream); // and do the normal inactive processing POSITION pos = m_OutputPins.GetHeadPosition(); while (pos) { CSplitterOutputPin *pPin = m_OutputPins.GetNext(pos); if (pPin->IsConnected()) { pPin->Inactive(); } } ResetAllocatorAndParser(); m_State = State_Stopped; return S_OK;}/* -- Return number of pins */int CBaseSplitterFilter::GetPinCount(){ CAutoLock lck(&m_csPins); return (m_pInput != NULL ? 1 : 0) + m_OutputPins.GetCount();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -