?? cfiltermpeg2dec.cpp
字號:
//
// CFilterMpeg2Dec.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 "CFilterMpeg2Dec.h"
#include "CFilterMpeg2DecInputPin.h"
#include "CDecodedStream.h"
// {151CFBD1-4626-49b8-9D22-C8A8132DA494}
DEFINE_GUID(CLSID_MyFilterMpeg2Dec,
0x151cfbd1, 0x4626, 0x49b8, 0x9d, 0x22, 0xc8, 0xa8, 0x13, 0x2d, 0xa4, 0x94);
//
// setup data
//
const AMOVIESETUP_MEDIATYPE sudPinTypes0 =
{
&MEDIATYPE_Stream, // Major type
&MEDIASUBTYPE_MPEG2_PROGRAM // Minor type
};
const AMOVIESETUP_MEDIATYPE sudPinTypes1 =
{
&MEDIATYPE_Video, // Major type
&MEDIASUBTYPE_NULL // Minor type
};
const AMOVIESETUP_MEDIATYPE sudPinTypes2 =
{
&MEDIATYPE_Audio, // 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
&sudPinTypes0 }, // The pin details
{ L"VOutput", // 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
&sudPinTypes1 // The pin details
},
{ L"AOutput", // 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
&sudPinTypes2 // The pin details
}
};
const AMOVIESETUP_FILTER sudFilter =
{
&CLSID_MyFilterMpeg2Dec, // Filter CLSID
L"My Mpeg2Dec Filter", // Filter name
MERIT_PREFERRED, // Its merit
3, // 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"My Mpeg2Dec Filter",
&CLSID_MyFilterMpeg2Dec,
CFilterMpeg2Dec::CreateInstance,
NULL,
&sudFilter
}
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
static int decoderInstances = 0;
// ----------------------------------------------------------------------------
// Filter implementation
// ----------------------------------------------------------------------------
CFilterMpeg2Dec::CFilterMpeg2Dec(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr) :
CSource(tszName, punk, CLSID_MyFilterMpeg2Dec)
{
decoderInstances++;
mSampleDuration = 0;
mImageWidth = 0;
mImageHeight = 0;
mOutputImageSize = 0;
mIsFlushing = FALSE;
mEOSDelivered = FALSE;
mEOSReceived = FALSE;
*phr = NOERROR;
mMpegInputPin = NULL;
CDecodedStream * outStream = new CDecodedStream(NAME("VOutput"), phr, this);
if (outStream == NULL)
{
*phr = E_OUTOFMEMORY;
}
else
{
outStream->SetController(&mMpeg2Controller);
// 添加處理類構(gòu)造函數(shù)
}
}
CFilterMpeg2Dec::~CFilterMpeg2Dec()
{
if (mMpegInputPin)
{
delete mMpegInputPin;
mMpegInputPin = NULL;
}
decoderInstances--;
}
//
// CreateInstance
//
// Override CClassFactory method.
// Provide the way for COM to create a CNullInPlace object
//
CUnknown * WINAPI CFilterMpeg2Dec::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;
}
CFilterMpeg2Dec *pNewObject = new CFilterMpeg2Dec(NAME("My Mpeg2Dec Filter"), punk, phr);
if (pNewObject == NULL)
{
*phr = E_OUTOFMEMORY;
}
return pNewObject;
}
//
// Basic COM - used here to reveal our own interfaces
STDMETHODIMP CFilterMpeg2Dec::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 CFilterMpeg2Dec::GetPinCount()
{
return 2;
}
CBasePin * CFilterMpeg2Dec::GetPin(int n)
{
if (mMpegInputPin == NULL)
{
HRESULT hr = NOERROR;
mMpegInputPin = new CFilterMpeg2DecInputPin(NAME("TS Input"), this, &hr);
ASSERT(mMpegInputPin);
}
switch (n)
{
case 0:
return mMpegInputPin;
case 1:
return m_paStreams[0];
default:
return NULL;
}
}
STDMETHODIMP CFilterMpeg2Dec::FindPin(LPCWSTR Id, IPin ** ppPin)
{
return CBaseFilter::FindPin(Id, ppPin);
}
STDMETHODIMP CFilterMpeg2Dec::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
mMpeg2Controller.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 CFilterMpeg2Dec::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
mMpeg2Controller.FlushAllPending();
hr = CBaseFilter::Pause();
}
}
return hr;
}
HRESULT CFilterMpeg2Dec::StartStreaming()
{
mIsFlushing = FALSE;
mEOSReceived = FALSE;
return NOERROR;
}
HRESULT CFilterMpeg2Dec::StopStreaming()
{
mIsFlushing = FALSE;
mEOSReceived = FALSE;
return NOERROR;
}
HRESULT CFilterMpeg2Dec::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);
mMpeg2Controller.ReceiveMpeg(pSourceBuffer, lSourceSize);
return NOERROR;
}
HRESULT CFilterMpeg2Dec::EndOfStream(void)
{
// Ignoring the more than twice EOS
if (!mEOSReceived)
{
mEOSReceived = TRUE;
mMpeg2Controller.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 CFilterMpeg2Dec::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
{
return m_paStreams[0]->DeliverNewSegment(tStart, tStop, dRate);
}
HRESULT CFilterMpeg2Dec::BeginFlush(void)
{
HRESULT hr = m_paStreams[0]->DeliverBeginFlush(); // Call downstreamly
mIsFlushing = TRUE;
OutputPin()->BeginFlush();
return hr;
}
HRESULT CFilterMpeg2Dec::EndFlush(void)
{
mEOSReceived = FALSE;
OutputPin()->EndFlush();
mIsFlushing = FALSE;
return m_paStreams[0]->DeliverEndFlush();
}
HRESULT CFilterMpeg2Dec::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
mMpeg2Controller.Uninitialize();
mMpeg2Controller.Initialize();
return S_OK;
}
}
else
{
CMediaType mtOut = OutputPin()->CurrentMediaType();
int bitcount = 2;
if (mtOut.subtype == MEDIASUBTYPE_YUY2)
{
bitcount = 2;
mMpeg2Controller.SetOutputType(2);
}
else if (mtOut.subtype == MEDIASUBTYPE_RGB24)
{
bitcount = 3;
mMpeg2Controller.SetOutputType(1);
}
mOutputImageSize = mImageWidth * mImageHeight * bitcount;
mMpeg2Controller.SetOutputImageSize(mOutputImageSize);
return S_OK;
}
return E_FAIL;
}
/*
//
STDMETHODIMP CFilterMpeg2Dec::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)
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -