splitter.h
资源名称:h264src.zip [点击查看]
上传用户:sunbaby
上传日期:2013-05-31
资源大小:242k
文件大小:15k
源码类别:
mpeg/mp3
开发平台:
Visual C++
- //==========================================================================;
- //
- // 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.
- //
- //--------------------------------------------------------------------------;
- /* Parser class - this class defines the object that actually splits
- out the data
- */
- /* CBaseParser class
- This is the object that determines the nature of the data
- and actually splits the stream
- */
- /* Simple stream reader class */
- class CParseReader
- {
- public:
- /* Set the position */
- virtual HRESULT Length(LONGLONG *pLength) = 0;
- virtual HRESULT SetPointer(LONGLONG) = 0;
- virtual HRESULT Read(PBYTE pbData, DWORD cbData) = 0;
- };
- /* Parsing reader from CAsyncReader */
- class CParseReaderFromAsync : public CParseReader
- {
- public:
- CParseReaderFromAsync(IAsyncReader *pRdr) :
- m_pReader(pRdr), m_llPos(0) {};
- HRESULT Length(LONGLONG *pLength)
- {
- LONGLONG llAvailable;
- return m_pReader->Length(pLength, &llAvailable);
- }
- HRESULT SetPointer(LONGLONG llPos)
- {
- m_llPos = 0;
- return S_OK;
- }
- HRESULT Read(PBYTE pbData, DWORD cbData)
- {
- HRESULT hr = m_pReader->SyncRead(m_llPos, (LONG)cbData, pbData);
- if (S_OK == hr) {
- m_llPos += cbData;
- }
- return hr;
- }
- private:
- IAsyncReader *m_pReader;
- LONGLONG m_llPos;
- };
- class CParserNotify;
- class CBaseParser
- {
- public:
- /* Instantiate a parser
- pNotify - to call back the calling object to create streams etc
- */
- CBaseParser(CParserNotify *pNotify,
- HRESULT *phr) : m_pNotify(pNotify) {};
- /* Initialize a parser
- pmt - type of stream if known - can be NULL
- pRdr - way to read the source medium - can be NULL
- */
- virtual HRESULT Init(
- CParseReader *pRdr
- ) = 0;
- /* Get the size and count of buffers preferred based on the
- actual content
- */
- virtual void GetSizeAndCount(LONG *plSize, LONG *plCount) = 0;
- /* Call this to reinitialize for a new stream */
- virtual void StreamReset() = 0;
- /* Call this to pass new stream data :
- pbData - pointer to data
- lData - length of data
- plProcessed - Amount of data consumed
- */
- virtual HRESULT Process(
- const BYTE *pbData,
- LONG lData,
- LONG *plProcessed
- ) = 0;
- protected:
- CParserNotify * const m_pNotify;
- };
- /* Parser calls back to create streams and spit out
- buffers
- */
- class CStreamNotify;
- class CParserNotify
- {
- public:
- /* Create an output stream with type *pmt, notifications
- to this stream passed to the **pStreamNotify object
- */
- virtual HRESULT CreateStream(
- LPCWSTR pszName,
- CStreamNotify **pStreamNotify) = 0;
- };
- class CStreamNotify
- {
- public:
- virtual HRESULT SendSample(
- const BYTE *pbData,
- LONG lData,
- REFERENCE_TIME rtStart,
- BOOL bSync
- ) = 0;
- /* Add a media type that's supported */
- virtual HRESULT AddMediaType(CMediaType const *pmt) = 0;
- /* Return the current type */
- virtual void CurrentMediaType(AM_MEDIA_TYPE *pmt) = 0;
- };
- /* Splitter filter base classes */
- /* Design :
- A splitter filter will have 1 input pin and multiple output pins
- CBaseSplitterFilter defines a base filter with 1 input pin and
- a list of output pins.
- This base class provides for pin enumeration, correct distribution
- of EndOfStream and handling of errors.
- The object structure is :
- IsA
- CBaseSplitterFilter <-------- CBaseFilter
- Allocators:
- This class relies on use CSequentialAllocator
- The input pin is designed around CPullPin which hooks up
- to IAsyncReader on the upstream output pin
- */
- class CBaseSplitterFilter;
- class CBaseParser;
- /* Input pin stuff
- The input pin deletes all the output pins when it's disconnected
- On connection the output pins are created based on the media type
- and possibly on the file content
- The base class handles things like flushing and end of stream
- */
- /* Special output pin type to handle lifetime */
- class CSplitterOutputPin : public CBaseOutputPin
- {
- public:
- // Constructor
- CSplitterOutputPin(
- CBaseSplitterFilter *pFilter,
- HRESULT *phr,
- LPCWSTR pName);
- ~CSplitterOutputPin();
- // CUnknown methods
- STDMETHODIMP_(ULONG) NonDelegatingAddRef();
- STDMETHODIMP_(ULONG) NonDelegatingRelease();
- // CBaseOutputPin methods - we just override these to do
- // our own hack allocator
- STDMETHOD(Notify)(IBaseFilter* pSender, Quality q);
- // override this to set the buffer size and count. Return an error
- // if the size/count is not to your liking
- virtual HRESULT DecideBufferSize(
- IMemAllocator * pAlloc,
- ALLOCATOR_PROPERTIES * pProp);
- // negotiate the allocator and its buffer size/count
- // calls DecideBufferSize to call SetCountAndSize
- virtual HRESULT DecideAllocator(IMemInputPin * pPin, IMemAllocator ** pAlloc);
- // override this to control the connection
- virtual HRESULT InitAllocator(IMemAllocator **ppAlloc);
- // Check the media type proposed
- HRESULT CheckMediaType(const CMediaType *);
- // returns the preferred formats for a pin
- HRESULT GetMediaType(int iPosition,CMediaType *pMediaType);
- // Send sample generated by parser
- HRESULT SendSample(
- const BYTE *pbData,
- LONG lData,
- REFERENCE_TIME rtStart,
- BOOL bSync
- );
- /* Add a media type */
- HRESULT AddMediaType(
- CMediaType const *pmt
- );
- HRESULT DeliverEndOfStream()
- {
- m_pOutputQueue->EOS();
- return S_OK;
- }
- // Delete our output queue on inactive
- HRESULT Inactive()
- {
- HRESULT hr = CBaseOutputPin::Inactive();
- if (FAILED(hr)) {
- return hr;
- }
- delete m_pOutputQueue;
- m_pOutputQueue = NULL;
- return S_OK;
- }
- /* Wrapper to call output queue to flush samples */
- void SendAnyway()
- {
- if (NULL != m_pOutputQueue) {
- m_pOutputQueue->SendAnyway();
- }
- }
- // Override Active and EndFlush to set the discontinuity flag
- HRESULT Active()
- {
- m_bDiscontinuity = TRUE;
- /* If we're not connected we don't participate so it's OK */
- if (!IsConnected()) {
- return S_OK;
- }
- HRESULT hr = CBaseOutputPin::Active();
- if (FAILED(hr)) {
- return hr;
- }
- /* Create our batch list */
- ASSERT(m_pOutputQueue == NULL);
- hr = S_OK;
- m_pOutputQueue = new COutputQueue(GetConnected(), // input pin
- &hr, // return code
- FALSE, // Auto detect
- TRUE, // ignored
- 50, // batch size
- TRUE, // exact batch
- 50); // queue size
- if (m_pOutputQueue == NULL) {
- return E_OUTOFMEMORY;
- }
- if (FAILED(hr)) {
- delete m_pOutputQueue;
- m_pOutputQueue = NULL;
- }
- return hr;
- }
- HRESULT DeliverBeginFlush()
- {
- /* We're already locked via the input pin */
- m_pOutputQueue->BeginFlush();
- return S_OK;
- }
- HRESULT DeliverEndFlush()
- {
- /* We're already locked via the input pin */
- m_bDiscontinuity = TRUE;
- m_pOutputQueue->EndFlush();
- return S_OK;
- }
- // Get our notify object
- CStreamNotify *GetNotify()
- {
- return &m_Notify;
- }
- protected:
- // Get a pointer to our allocator
- CSubAllocator *Allocator()
- {
- return (CSubAllocator *)m_pAllocator;
- }
- // Get a properly cast pointer to our filter
- CBaseSplitterFilter *Filter()
- {
- return (CBaseSplitterFilter *)m_pFilter;
- }
- protected:
- // Stream notify stuff
- class CImplStreamNotify : public CStreamNotify
- {
- public:
- CImplStreamNotify(CSplitterOutputPin *pPin) : m_pPin(pPin) {}
- HRESULT SendSample(
- const BYTE *pbData,
- LONG lData,
- REFERENCE_TIME rtStart,
- BOOL bSync
- )
- {
- return m_pPin->SendSample(pbData, lData, rtStart, bSync);
- }
- HRESULT AddMediaType(CMediaType const *pmt)
- {
- return m_pPin->AddMediaType(pmt);
- }
- void CurrentMediaType(AM_MEDIA_TYPE *pmt)
- {
- m_pPin->ConnectionMediaType(pmt);
- }
- private:
- CSplitterOutputPin * const m_pPin;
- };
- CImplStreamNotify m_Notify;
- // Remember when to send NewSegment and discontinuity */
- BOOL m_bDiscontinuity;
- // Output queue
- COutputQueue *m_pOutputQueue;
- // List of media types we support
- CGenericList<CMediaType> m_lTypes;
- };
- /* Base CSplitterInputPin on CPullPin
- */
- class CSplitterInputPin : public CBaseInputPin
- {
- public:
- CSplitterInputPin(
- CBaseSplitterFilter *pFilter,
- HRESULT *phr);
- /* NonDelegating IUnknown methods - we don't support IMemInputPin */
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv)
- {
- if (riid == IID_IMemInputPin) {
- return E_NOINTERFACE;
- }
- return CBaseInputPin::NonDelegatingQueryInterface(riid, ppv);
- }
- /* IPin methods */
- STDMETHODIMP EndOfStream();
- STDMETHODIMP BeginFlush();
- STDMETHODIMP EndFlush();
- STDMETHODIMP Receive(IMediaSample *pSample);
- /* IMemInputPin methods */
- /* Where we're told which allocator we are using */
- STDMETHODIMP NotifyAllocator(IMemAllocator *pAllocator)
- {
- if (pAllocator != (IMemAllocator *)m_pAllocator) {
- return E_FAIL;
- } else {
- return S_OK;
- }
- }
- /* Say if we're blocking */
- STDMETHODIMP ReceiveCanBlock()
- {
- return S_FALSE;
- }
- /* CBasePin methods */
- HRESULT BreakConnect(); // Override to release puller
- HRESULT CheckConnect(IPin *pPin); // Override to connect to puller
- HRESULT Active();
- HRESULT Inactive();
- HRESULT CheckMediaType(const CMediaType *pmt);
- HRESULT CompleteConnect(IPin *pReceivePin);
- /* Report filter from reader */
- void NotifyError(HRESULT hr)
- {
- if (FAILED(hr)) {
- m_pFilter->NotifyEvent(EC_ERRORABORT, hr, 0);
- }
- EndOfStream();
- };
- /* Convenient way to get the allocator */
- CSequentialAllocator *Allocator()
- {
- return (CSequentialAllocator *)m_pAllocator;
- }
- /* Point to our media type */
- CMediaType *MediaType()
- {
- return &m_mt;
- }
- /* Return our async reader */
- IAsyncReader *Reader()
- {
- IAsyncReader *pReader = m_puller.GetReader();
- pReader->Release();
- return pReader;
- }
- private:
- // Get a properly case pointer to our filter
- CBaseSplitterFilter *Filter()
- {
- return (CBaseSplitterFilter *)m_pFilter;
- }
- // class to pull data from IAsyncReader if we detect that interface
- // on the output pin
- class CImplPullPin : public CPullPin
- {
- // forward everything to containing pin
- CSplitterInputPin * const m_pPin;
- public:
- CImplPullPin(CSplitterInputPin* pPin)
- : m_pPin(pPin)
- {
- };
- // forward this to the pin's IMemInputPin::Receive
- HRESULT Receive(IMediaSample* pSample) {
- return m_pPin->Receive(pSample);
- };
- // override this to handle end-of-stream
- HRESULT EndOfStream(void) {
- return m_pPin->EndOfStream();
- };
- // these errors have already been reported to the filtergraph
- // by the upstream filter so ignore them
- void OnError(HRESULT hr) {
- // ignore VFW_E_WRONG_STATE since this happens normally
- // during stopping and seeking
- if (hr != VFW_E_WRONG_STATE) {
- m_pPin->NotifyError(hr);
- }
- };
- // flush the pin and all downstream
- HRESULT BeginFlush() {
- return m_pPin->BeginFlush();
- };
- // Tell the next guy we've finished flushing
- HRESULT EndFlush() {
- return m_pPin->EndFlush();
- };
- };
- CImplPullPin m_puller;
- };
- class CBaseSplitterFilter : public CBaseFilter
- {
- friend class CSplitterOutputPin;
- friend class CSplitterInputPin;
- public:
- // Constructor and destructor
- CBaseSplitterFilter(
- TCHAR *pName,
- LPUNKNOWN pUnk,
- REFCLSID rclsid,
- HRESULT *phr);
- ~CBaseSplitterFilter();
- // IMediaFilter methods - override these to manage locking
- STDMETHODIMP Stop();
- STDMETHODIMP Pause();
- /* Stream control stuff */
- virtual HRESULT BeginFlush();
- virtual HRESULT EndFlush();
- virtual void EndOfStream();
- virtual HRESULT Receive(IMediaSample *pSample);
- virtual HRESULT CheckInputType(const CMediaType *pmt) = 0;
- virtual HRESULT CompleteConnect(IPin *pReceivePin);
- // Create the parser
- virtual CBaseParser *CreateParser(
- CParserNotify *pNotify,
- CMediaType *pType) = 0;
- // CBaseFilter methods
- int GetPinCount(); // 0 pins
- CBasePin *GetPin(int iPin);
- /* Add a new output pin */
- BOOL AddOutputPin(CSplitterOutputPin *pOutputPin);
- /* Destroy the output pins */
- void DestroyOutputPins();
- /* Destroy the input pin */
- void DestroyInputPin();
- /* Notify to create a new stream
- Called back through CParseNotify
- */
- HRESULT CreateStream(
- LPCWSTR pszName,
- CStreamNotify **ppStreamNotify
- );
- /* Called when BreakConnect called on the input pin */
- virtual void BreakConnect();
- protected:
- /* Utility to get the allocator */
- CSequentialAllocator *Allocator()
- {
- return InputPin()->Allocator();
- }
- /* Reset the states of the allocator and parser
- ready to receive a new stream
- */
- void ResetAllocatorAndParser()
- {
- Allocator()->Flush();
- m_pParser->StreamReset();
- }
- CSplitterInputPin *InputPin()
- {
- return (CSplitterInputPin *)m_pInput;
- }
- protected:
- // Our input pin - created by derived classes
- CBaseInputPin *m_pInput;
- // Our output pin list - Derived classes append to this
- CGenericList<CSplitterOutputPin> m_OutputPins;
- // Filter locking
- CCritSec m_csFilter;
- // Streaming lock
- CCritSec m_csStream;
- // Pin database lock
- CCritSec m_csPins;
- // Parser - created when we're connected
- CBaseParser *m_pParser;
- // Parser notify - use member variable to avoid mulitple inheritance
- class CImplParserNotify : public CParserNotify
- {
- public:
- CImplParserNotify(CBaseSplitterFilter *pFilter) : m_pFilter(pFilter) {};
- HRESULT CreateStream(
- LPCWSTR pszName,
- CStreamNotify **ppStreamNotify
- )
- {
- return m_pFilter->CreateStream(pszName, ppStreamNotify);
- }
- private:
- CBaseSplitterFilter * const m_pFilter;
- };
- CImplParserNotify m_Notify;
- };