📄 grabber.cpp.svn-base
字号:
//------------------------------------------------------------------------------
// File: Grabber.cpp
//
// Desc: DirectShow sample code - Implementation file for the SampleGrabber
// example filter
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
#include <streams.h> // Active Movie (includes windows.h)
#include <initguid.h> // declares DEFINE_GUID to declare an EXTERN_C const.
#include "grabber.h"
//#pragma warning(disable: 4800)
const AMOVIESETUP_PIN psudSampleGrabberPins[] =
{ { L"Input" // strName
, FALSE // bRendered
, FALSE // bOutput
, FALSE // bZero
, FALSE // bMany
, &CLSID_NULL // clsConnectsToFilter
, L"" // strConnectsToPin
, 0 // nTypes
, NULL // lpTypes
}
, { L"Output" // strName
, FALSE // bRendered
, TRUE // bOutput
, FALSE // bZero
, FALSE // bMany
, &CLSID_NULL // clsConnectsToFilter
, L"" // strConnectsToPin
, 0 // nTypes
, NULL // lpTypes
}
};
const AMOVIESETUP_FILTER sudSampleGrabber =
{ &CLSID_GrabberSample // clsID
, L"SampleGrabber Example" // strName
, MERIT_DO_NOT_USE // dwMerit
, 2 // nPins
, psudSampleGrabberPins }; // lpPin
// Needed for the CreateInstance mechanism
CFactoryTemplate g_Templates[]=
{
{ L"Sample Grabber Example"
, &CLSID_GrabberSample
, CSampleGrabber::CreateInstance
, NULL
, &sudSampleGrabber }
};
int g_cTemplates = sizeof(g_Templates)/sizeof(g_Templates[0]);
////////////////////////////////////////////////////////////////////////
//
// Exported entry points for registration and unregistration
// (in this case they only call through to default implementations).
//
////////////////////////////////////////////////////////////////////////
STDAPI DllRegisterServer()
{
return AMovieDllRegisterServer2(TRUE);
}
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2(FALSE);
}
//
// DllMain
//
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
BOOL WINAPI DllMain(HANDLE hModule,
DWORD dwReason,
LPVOID lpReserved)
{
return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}
//
// CreateInstance
//
// Provide the way for COM to create a CSampleGrabber object
//
CUnknown * WINAPI CSampleGrabber::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
{
ASSERT(phr);
// assuming we don't want to modify the data
CSampleGrabber *pNewObject = new CSampleGrabber(punk, phr, FALSE);
if(pNewObject == NULL) {
if (phr)
*phr = E_OUTOFMEMORY;
}
return pNewObject;
} // CreateInstance
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
CSampleGrabber::CSampleGrabber( IUnknown * pOuter, HRESULT * phr, BOOL ModifiesData )
: CTransInPlaceFilter( TEXT("SampleGrabber"), (IUnknown*) pOuter,
//CLSID_GrabberSample, phr, (BOOL)ModifiesData )
CLSID_GrabberSample, phr)
, m_callback( NULL )
{
// this is used to override the input pin with our own
m_pInput = (CTransInPlaceInputPin*) new CSampleGrabberInPin( this, phr );
if( !m_pInput )
{
if (phr)
*phr = E_OUTOFMEMORY;
}
// Ensure that the output pin gets created. This is necessary because our
// SetDeliveryBuffer() method assumes that the input/output pins are created, but
// the output pin isn't created until GetPin() is called. The
// CTransInPlaceFilter::GetPin() method will create the output pin, since we
// have not already created one.
IPin *pOutput = GetPin(1);
// The pointer is not AddRef'ed by GetPin(), so don't release it
}
STDMETHODIMP CSampleGrabber::NonDelegatingQueryInterface( REFIID riid, void ** ppv)
{
CheckPointer(ppv,E_POINTER);
if(riid == IID_IGrabberSample) {
return GetInterface((IGrabberSample *) this, ppv);
}
else {
return CTransInPlaceFilter::NonDelegatingQueryInterface(riid, ppv);
}
}
//----------------------------------------------------------------------------
// This is where you force the sample grabber to connect with one type
// or the other. What you do here is crucial to what type of data your
// app will be dealing with in the sample grabber's callback. For instance,
// if you don't enforce right-side-up video in this call, you may not get
// right-side-up video in your callback. It all depends on what you do here.
//----------------------------------------------------------------------------
HRESULT CSampleGrabber::CheckInputType( const CMediaType * pmt )
{
CheckPointer(pmt,E_POINTER);
CAutoLock lock( &m_Lock );
// if the major type is not set, then accept anything
GUID g = *m_mtAccept.Type( );
if( g == GUID_NULL )
{
return NOERROR;
}
// if the major type is set, don't accept anything else
if( g != *pmt->Type( ) )
{
return VFW_E_INVALID_MEDIA_TYPE;
}
// subtypes must match, if set. if not set, accept anything
g = *m_mtAccept.Subtype( );
if( g == GUID_NULL )
{
return NOERROR;
}
if( g != *pmt->Subtype( ) )
{
return VFW_E_INVALID_MEDIA_TYPE;
}
// format types must match, if one is set
g = *m_mtAccept.FormatType( );
if( g == GUID_NULL )
{
return NOERROR;
}
if( g != *pmt->FormatType( ) )
{
return VFW_E_INVALID_MEDIA_TYPE;
}
// at this point, for this sample code, this is good enough,
// but you may want to make it more strict
return NOERROR;
}
//----------------------------------------------------------------------------
// This bit is almost straight out of the base classes.
// We override this so we can handle Transform( )'s error
// result differently.
//----------------------------------------------------------------------------
HRESULT CSampleGrabber::Receive( IMediaSample * pms )
{
CheckPointer(pms,E_POINTER);
HRESULT hr;
AM_SAMPLE2_PROPERTIES * const pProps = m_pInput->SampleProps();
RETAILMSG(1, (TEXT("Grabber: Receive! %x\r\n")));
if (pProps->dwStreamId != AM_STREAM_MEDIA)
{
if( m_pOutput->IsConnected() )
return m_pOutput->Deliver(pms);
else
return NOERROR;
}
/* if (UsingDifferentAllocators())
{
// We have to copy the data.
pms = Copy(pms);
if (pms == NULL)
{
return E_UNEXPECTED;
}
}
*/
// have the derived class transform the data
hr = Transform(pms);
if (FAILED(hr))
{
// DbgLog((LOG_TRACE, 1, TEXT("Error from TransInPlace")));
/* if (UsingDifferentAllocators())
{
pms->Release();
}
*/
return hr;
}
if (hr == NOERROR)
{
hr = m_pOutput->Deliver(pms);
}
// release the output buffer. If the connected pin still needs it,
// it will have addrefed it itself.
/* if (UsingDifferentAllocators())
{
pms->Release();
}
*/
return hr;
}
//----------------------------------------------------------------------------
// Transform
//----------------------------------------------------------------------------
HRESULT CSampleGrabber::Transform ( IMediaSample * pms )
{
CheckPointer(pms,E_POINTER);
CAutoLock lock( &m_Lock );
RETAILMSG(1, (TEXT("Grabber: Transform! %x\r\n")));
if( m_callback )
{
REFERENCE_TIME StartTime, StopTime;
pms->GetTime( &StartTime, &StopTime);
StartTime += m_pInput->CurrentStartTime( );
StopTime += m_pInput->CurrentStartTime( );
BOOL * pTypeChanged = &((CSampleGrabberInPin*) m_pInput)->m_bMediaTypeChanged;
HRESULT hr = m_callback( pms, &StartTime, &StopTime, *pTypeChanged );
*pTypeChanged = FALSE; // now that we notified user, we can clear it
return hr;
}
return NOERROR;
}
//----------------------------------------------------------------------------
// SetAcceptedMediaType
//----------------------------------------------------------------------------
STDMETHODIMP CSampleGrabber::SetAcceptedMediaType( const CMediaType * pmt )
{
CAutoLock lock( &m_Lock );
if( !pmt )
{
m_mtAccept = CMediaType( );
return NOERROR;
}
HRESULT hr = TRUE;
CopyMediaType( &m_mtAccept, pmt );
return hr;
}
//----------------------------------------------------------------------------
// GetAcceptedMediaType
//----------------------------------------------------------------------------
STDMETHODIMP CSampleGrabber::GetConnectedMediaType( CMediaType * pmt )
{
if( !m_pInput || !m_pInput->IsConnected( ) )
{
return VFW_E_NOT_CONNECTED;
}
return m_pInput->ConnectionMediaType( pmt );
}
//----------------------------------------------------------------------------
// SetCallback
//----------------------------------------------------------------------------
STDMETHODIMP CSampleGrabber::SetCallback( SAMPLECALLBACK Callback )
{
CAutoLock lock( &m_Lock );
m_callback = Callback;
return NOERROR;
}
//----------------------------------------------------------------------------
// inform the input pin of the allocator buffer we wish to use. See the
// input pin's SetDeliverBuffer method for comments.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -