CFilterMpeg2VD.cpp
上传用户:hhs829
上传日期:2022-06-17
资源大小:586k
文件大小:12k
- //
- // CFilterMpeg2VD.cpp
- //
- #include <streams.h> // quartz, includes windows
- // Eliminate two expected level 4 warnings from the Microsoft compiler.
- // The class does not have an assignment or copy operator, and so cannot
- // be passed by value. This is normal. This file compiles clean at the
- // highest (most picky) warning level (-W4).
- #pragma warning(disable: 4511 4512)
- #include <measure.h> // performance measurement (MSR_)
- #include <initguid.h>
- #if (1100 > _MSC_VER)
- #include <olectlid.h>
- #else
- #include <olectl.h>
- #endif
- #include <dvdmedia.h>
- #include <stdio.h>
- #include "CFilterMpeg2VD.h"
- #include "CMpegInputPin.h"
- #include "CDecodedStream.h"
- #include "CFilterMpeg2VDProp.h"
- // {AFF8F523-DB02-495c-A1A1-605A505500A5}
- DEFINE_GUID(CLSID_FilterMpeg2VD,
- 0xaff8f523, 0xdb02, 0x495c, 0xa1, 0xa1, 0x60, 0x5a, 0x50, 0x55, 0x0, 0xa5);
- // {8EDE98CF-17A3-471b-98AB-C944727E50BA}
- DEFINE_GUID(CLSID_FilterMpeg2VDProp,
- 0x8ede98cf, 0x17a3, 0x471b, 0x98, 0xab, 0xc9, 0x44, 0x72, 0x7e, 0x50, 0xba);
- //
- // setup data
- //
- const AMOVIESETUP_MEDIATYPE sudPinTypes =
- {
- &MEDIATYPE_Video, // Major type
- &MEDIASUBTYPE_NULL // Minor type
- };
- const AMOVIESETUP_PIN psudPins[] =
- {
- {
- L"Input", // String pin name
- FALSE, // Is it rendered
- FALSE, // Is it an output
- FALSE, // Allowed none
- FALSE, // Allowed many
- &CLSID_NULL, // Connects to filter
- L"Output", // Connects to pin
- 1, // Number of types
- &sudPinTypes }, // The pin details
- { L"Output", // String pin name
- FALSE, // Is it rendered
- TRUE, // Is it an output
- FALSE, // Allowed none
- FALSE, // Allowed many
- &CLSID_NULL, // Connects to filter
- L"Input", // Connects to pin
- 1, // Number of types
- &sudPinTypes // The pin details
- }
- };
- const AMOVIESETUP_FILTER sudFilter =
- {
- &CLSID_FilterMpeg2VD, // Filter CLSID
- L"HQ MPEG-2 Video Decoder", // Filter name
- MERIT_PREFERRED, // Its merit
- 2, // Number of pins
- psudPins // Pin details
- };
- // List of class IDs and creator functions for the class factory. This
- // provides the link between the OLE entry point in the DLL and an object
- // being created. The class factory will call the static CreateInstance
- CFactoryTemplate g_Templates[] =
- {
- {
- L"HQ MPEG-2 Video Decoder",
- &CLSID_FilterMpeg2VD,
- CFilterMpeg2VD::CreateInstance,
- NULL,
- &sudFilter
- }/*,
- {
- L"HQ Mpeg2 VD Property Page",
- &CLSID_FilterMpeg2VDProp,
- CFilterMpeg2VDProp::CreateInstance
- }*/
- };
- int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
- static int decoderInstances = 0;
- // ----------------------------------------------------------------------------
- // Filter implementation
- // ----------------------------------------------------------------------------
- CFilterMpeg2VD::CFilterMpeg2VD(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr) :
- CSource(tszName, punk, CLSID_FilterMpeg2VD)
- {
- decoderInstances++;
- mSampleDuration = 0;
- mImageWidth = 0;
- mImageHeight = 0;
- mOutputImageSize = 0;
- mIsFlushing = FALSE;
- mEOSDelivered = FALSE;
- mEOSReceived = FALSE;
- *phr = NOERROR;
- mMpegInputPin = NULL;
- CDecodedStream * outStream = new CDecodedStream(NAME("Output"), phr, this);
- if (outStream == NULL)
- {
- *phr = E_OUTOFMEMORY;
- }
- else
- {
- outStream->SetController(&mMpegController);
- }
- }
- CFilterMpeg2VD::~CFilterMpeg2VD()
- {
- if (mMpegInputPin)
- {
- delete mMpegInputPin;
- mMpegInputPin = NULL;
- }
- decoderInstances--;
- }
- //
- // CreateInstance
- //
- // Override CClassFactory method.
- // Provide the way for COM to create a CNullInPlace object
- //
- CUnknown * WINAPI CFilterMpeg2VD::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
- {
- #if 0
- char szCreatorPath[256], szCreatorName[256];
- ::strcpy(szCreatorPath, "");
- ::strcpy(szCreatorName, "");
- HMODULE hModule = ::GetModuleHandle(NULL);
- ::GetModuleFileName(hModule, szCreatorPath, 256);
- char * backSlash = ::strrchr(szCreatorPath, '\');
- if (backSlash)
- {
- strcpy(szCreatorName, backSlash);
- }
- ::_strlwr(szCreatorName);
- // Please specify your app name with lowercase
- if (::strstr(szCreatorName, "graphedt") == NULL)
- {
- *phr = E_FAIL;
- return NULL;
- }
- #endif
- // Never use more than two instances of this decoder in the same application
- // Beccause of global variable problems!
- // 2002-12-26
- if (decoderInstances == 1)
- {
- *phr = E_FAIL;
- return NULL;
- }
- CFilterMpeg2VD *pNewObject = new CFilterMpeg2VD(NAME("Filter Mpeg2 VD"), punk, phr);
- if (pNewObject == NULL)
- {
- *phr = E_OUTOFMEMORY;
- }
- return pNewObject;
- }
- //
- // Basic COM - used here to reveal our own interfaces
- STDMETHODIMP CFilterMpeg2VD::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
- {
- CheckPointer(ppv, E_POINTER);
-
- // if (riid == IID_ISpecifyPropertyPages)
- // {
- // return GetInterface((ISpecifyPropertyPages *) this, ppv);
- // }
- // else
- {
- return CSource::NonDelegatingQueryInterface(riid, ppv);
- }
- } // NonDelegatingQueryInterface
- int CFilterMpeg2VD::GetPinCount()
- {
- return 2;
- }
- CBasePin * CFilterMpeg2VD::GetPin(int n)
- {
- if (mMpegInputPin == NULL)
- {
- HRESULT hr = NOERROR;
- mMpegInputPin = new CMpegInputPin(NAME("Input"), this, &hr);
- ASSERT(mMpegInputPin);
- }
- switch (n)
- {
- case 0:
- return mMpegInputPin;
- case 1:
- return m_paStreams[0];
- default:
- return NULL;
- }
- }
- STDMETHODIMP CFilterMpeg2VD::FindPin(LPCWSTR Id, IPin ** ppPin)
- {
- return CBaseFilter::FindPin(Id, ppPin);
- }
- STDMETHODIMP CFilterMpeg2VD::Stop()
- {
- CAutoLock lck1(&m_cStateLock);
- if (m_State == State_Stopped)
- {
- return NOERROR;
- }
- // Succeed the Stop if we are not completely connected
- ASSERT(mMpegInputPin == NULL || m_paStreams[0] != NULL);
- if (mMpegInputPin == NULL || mMpegInputPin->IsConnected() == FALSE ||
- m_paStreams[0]->IsConnected() == FALSE)
- {
- m_State = State_Stopped;
- mEOSDelivered = FALSE;
- return NOERROR;
- }
- // Important!!! Refuse to receive any more samples
- mMpegController.FlushAllPending();
- // decommit the input pin before locking or we can deadlock
- mMpegInputPin->Inactive();
- // synchronize with Receive calls
- CAutoLock lck2(&m_csReceive);
- OutputPin()->BeginFlush();
- OutputPin()->Inactive();
- OutputPin()->EndFlush();
- // allow a class derived from CTransformFilter
- // to know about starting and stopping streaming
- HRESULT hr = StopStreaming();
- if (SUCCEEDED(hr))
- {
- // complete the state transition
- m_State = State_Stopped;
- mEOSDelivered = FALSE;
- }
- return hr;
- }
- STDMETHODIMP CFilterMpeg2VD::Pause()
- {
- CAutoLock lck(&m_cStateLock);
-
- HRESULT hr = NOERROR;
- if (m_State == State_Paused)
- {
- // (This space left deliberately blank)
- }
-
- // If we have no input pin or it isn't yet connected then when we are
- // asked to pause we deliver an end of stream to the downstream filter.
- // This makes sure that it doesn't sit there forever waiting for
- // samples which we cannot ever deliver without an input connection.
- else if (mMpegInputPin == NULL || mMpegInputPin->IsConnected() == FALSE)
- {
- if(m_paStreams[0]->IsConnected() && mEOSDelivered == FALSE)
- {
- m_paStreams[0]->DeliverEndOfStream();
- mEOSDelivered = TRUE;
- }
- m_State = State_Paused;
- }
- // We may have an input connection but no output connection
- // However, if we have an input pin we do have an output pin
- else if (m_paStreams[0]->IsConnected() == FALSE)
- {
- m_State = State_Paused;
- }
- else
- {
- if (m_State == State_Stopped)
- {
- // allow a class derived from CTransformFilter
- // to know about starting and stopping streaming
- CAutoLock lck2(&m_csReceive);
- hr = StartStreaming();
- }
- if (SUCCEEDED(hr))
- {
- // Make sure the receive not blocking
- // Make sure the out-sending thread not working
- mMpegController.FlushAllPending();
- hr = CBaseFilter::Pause();
- }
- }
- return hr;
- }
- HRESULT CFilterMpeg2VD::StartStreaming()
- {
- mIsFlushing = FALSE;
- mEOSReceived = FALSE;
- return NOERROR;
- }
- HRESULT CFilterMpeg2VD::StopStreaming()
- {
- mIsFlushing = FALSE;
- mEOSReceived = FALSE;
- return NOERROR;
- }
- HRESULT CFilterMpeg2VD::Receive(IMediaSample *pSample)
- {
- // Check for other streams and pass them on
- AM_SAMPLE2_PROPERTIES * const pProps = mMpegInputPin->SampleProps();
- if (pProps->dwStreamId != AM_STREAM_MEDIA)
- {
- return m_paStreams[0]->Deliver(pSample);
- }
- // Receive mpeg2 data to buffer
- ASSERT(pSample);
- long lSourceSize = pSample->GetActualDataLength();
- BYTE * pSourceBuffer;
- pSample->GetPointer(&pSourceBuffer);
- mMpegController.ReceiveMpeg(pSourceBuffer, lSourceSize);
- return NOERROR;
- }
- HRESULT CFilterMpeg2VD::EndOfStream(void)
- {
- // Ignoring the more than twice EOS
- if (!mEOSReceived)
- {
- mEOSReceived = TRUE;
- mMpegController.BeginEndOfStream();
- // Wait for all caching data having been fetched out
- // while (!mMpegController.IsCacheOutputWaiting() &&
- // !mMpegController.IsCacheEmpty())
- // {
- // Sleep(10);
- // }
- // mMpegController.EndEndOfStream();
- // mEOSDelivered = TRUE;
- // return m_paStreams[0]->DeliverEndOfStream();
- }
- return NOERROR;
- }
- HRESULT CFilterMpeg2VD::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
- {
- return m_paStreams[0]->DeliverNewSegment(tStart, tStop, dRate);
- }
- HRESULT CFilterMpeg2VD::BeginFlush(void)
- {
- HRESULT hr = m_paStreams[0]->DeliverBeginFlush(); // Call downstreamly
- mIsFlushing = TRUE;
- OutputPin()->BeginFlush();
- return hr;
- }
- HRESULT CFilterMpeg2VD::EndFlush(void)
- {
- mEOSReceived = FALSE;
- OutputPin()->EndFlush();
- mIsFlushing = FALSE;
- return m_paStreams[0]->DeliverEndFlush();
- }
- HRESULT CFilterMpeg2VD::CompleteConnect(PIN_DIRECTION inDirection, IPin * inReceivePin)
- {
- if (inDirection == PINDIR_INPUT)
- {
- CMediaType mtIn = mMpegInputPin->CurrentMediaType();
- if (mtIn.formattype == FORMAT_MPEG2Video)
- {
- MPEG2VIDEOINFO * pFormat = (MPEG2VIDEOINFO *) mtIn.pbFormat;
- mSampleDuration = pFormat->hdr.AvgTimePerFrame;
- mImageWidth = pFormat->hdr.bmiHeader.biWidth;
- mImageHeight = pFormat->hdr.bmiHeader.biHeight;
- // Init the mpeg decoder system
- mMpegController.Uninitialize();
- mMpegController.Initialize();
- return S_OK;
- }
- }
- else
- {
- CMediaType mtOut = OutputPin()->CurrentMediaType();
- int bitcount = 2;
- if (mtOut.subtype == MEDIASUBTYPE_YUY2)
- {
- bitcount = 2;
- mMpegController.SetOutputType(2);
- }
- else if (mtOut.subtype == MEDIASUBTYPE_RGB24)
- {
- bitcount = 3;
- mMpegController.SetOutputType(1);
- }
- mOutputImageSize = mImageWidth * mImageHeight * bitcount;
- mMpegController.SetOutputImageSize(mOutputImageSize);
- return S_OK;
- }
- return E_FAIL;
- }
- /*
- //
- STDMETHODIMP CFilterMpeg2VD::GetPages(CAUUID *pPages)
- {
- pPages->cElems = 1;
- pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID));
- if (pPages->pElems == NULL)
- {
- return E_OUTOFMEMORY;
- }
- *(pPages->pElems) = CLSID_FilterMpeg2VDProp;
- return NOERROR;
- }
- */
- /******************************Public Routine******************************
- * exported entry points for registration and
- * unregistration (in this case they only call
- * through to default implmentations).
- *
- *
- *
- * History:
- *
- **************************************************************************/
- STDAPI DllRegisterServer()
- {
- return AMovieDllRegisterServer2( TRUE );
- }
- STDAPI DllUnregisterServer()
- {
- return AMovieDllRegisterServer2( FALSE );
- }
- // Microsoft C Compiler will give hundreds of warnings about
- // unused inline functions in header files. Try to disable them.
- #pragma warning( disable:4514)