📄 samplegrabber.cpp
字号:
// SampleGrabber.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include "SampleGrabber.h"
#include <windows.h>
#include <commctrl.h>
#pragma warning(disable: 4800)
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
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]);
//
// 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)
, 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 ) // xiaqz:>
{
return CTransInPlaceFilter::Receive(pms);
}
//{
// CheckPointer(pms,E_POINTER);
//
// HRESULT hr;
// AM_SAMPLE2_PROPERTIES * const pProps = m_pInput->SampleProps();
//
// 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 );
ATLASSERT(FALSE);
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;
}
CopyMediaType( &m_mtAccept, pmt );
return S_OK;
}
//----------------------------------------------------------------------------
// 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.
//----------------------------------------------------------------------------
STDMETHODIMP CSampleGrabber::SetDeliveryBuffer( ALLOCATOR_PROPERTIES props, BYTE * m_pBuffer )
{
// have the input/output pins been created?
if( !InputPin( ) || !OutputPin( ) )
{
return E_POINTER;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -