?? amfilter.cpp
字號:
if (i == (int)m_bTryMyTypesFirst) {
hr = pReceivePin->EnumMediaTypes(&pEnumMediaTypes);
} else {
hr = EnumMediaTypes(&pEnumMediaTypes);
}
if (SUCCEEDED(hr)) {
ASSERT(pEnumMediaTypes);
hr = TryMediaTypes(pReceivePin,pmt,pEnumMediaTypes);
pEnumMediaTypes->Release();
if (SUCCEEDED(hr)) {
return NOERROR;
} else {
// try to remember specific error codes if there are any
if ((hr != E_FAIL) &&
(hr != E_INVALIDARG) &&
(hr != VFW_E_TYPE_NOT_ACCEPTED)) {
hrFailure = hr;
}
}
}
}
return hrFailure;
}
/* Called when we want to complete a connection to another filter. Failing
this will also fail the connection and disconnect the other pin as well */
HRESULT
CBasePin::CompleteConnect(IPin *pReceivePin)
{
UNREFERENCED_PARAMETER(pReceivePin);
return NOERROR;
}
/* This is called to set the format for a pin connection - CheckMediaType
will have been called to check the connection format and if it didn't
return an error code then this (virtual) function will be invoked */
HRESULT
CBasePin::SetMediaType(const CMediaType *pmt)
{
HRESULT hr = m_mt.Set(*pmt);
if (FAILED(hr)) {
return hr;
}
return NOERROR;
}
/* This is called during Connect() to provide a virtual method that can do
any specific check needed for connection such as QueryInterface. This
base class method just checks that the pin directions don't match */
HRESULT
CBasePin::CheckConnect(IPin * pPin)
{
/* Check that pin directions DONT match */
PIN_DIRECTION pd;
pPin->QueryDirection(&pd);
ASSERT((pd == PINDIR_OUTPUT) || (pd == PINDIR_INPUT));
ASSERT((m_dir == PINDIR_OUTPUT) || (m_dir == PINDIR_INPUT));
// we should allow for non-input and non-output connections?
if (pd == m_dir) {
return VFW_E_INVALID_DIRECTION;
}
return NOERROR;
}
/* This is called when we realise we can't make a connection to the pin and
must undo anything we did in CheckConnect - override to release QIs done */
HRESULT
CBasePin::BreakConnect()
{
return NOERROR;
}
/* Called normally by an output pin on an input pin to try and establish a
connection.
*/
STDMETHODIMP
CBasePin::ReceiveConnection(
IPin * pConnector, // this is the pin who we will connect to
const AM_MEDIA_TYPE *pmt // this is the media type we will exchange
)
{
CheckPointer(pConnector,E_POINTER);
CheckPointer(pmt,E_POINTER);
ValidateReadPtr(pConnector,sizeof(IPin));
ValidateReadPtr(pmt,sizeof(AM_MEDIA_TYPE));
CAutoLock cObjectLock(m_pLock);
/* Are we already connected */
if (m_Connected) {
return VFW_E_ALREADY_CONNECTED;
}
/* See if the filter is active */
if (!IsStopped() && !m_bCanReconnectWhenActive) {
return VFW_E_NOT_STOPPED;
}
HRESULT hr = CheckConnect(pConnector);
if (FAILED(hr)) {
// Since the procedure is already returning an error code, there
// is nothing else this function can do to report the error.
EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) );
return hr;
}
/* Ask derived class if this media type is ok */
CMediaType * pcmt = (CMediaType*) pmt;
hr = CheckMediaType(pcmt);
if (hr != NOERROR) {
// no -we don't support this media type
// Since the procedure is already returning an error code, there
// is nothing else this function can do to report the error.
EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) );
// return a specific media type error if there is one
// or map a general failure code to something more helpful
// (in particular S_FALSE gets changed to an error code)
if (SUCCEEDED(hr) ||
(hr == E_FAIL) ||
(hr == E_INVALIDARG)) {
hr = VFW_E_TYPE_NOT_ACCEPTED;
}
return hr;
}
/* Complete the connection */
m_Connected = pConnector;
m_Connected->AddRef();
hr = SetMediaType(pcmt);
if (SUCCEEDED(hr)) {
hr = CompleteConnect(pConnector);
if (SUCCEEDED(hr)) {
return NOERROR;
}
}
DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Failed to set the media type or failed to complete the connection.")));
m_Connected->Release();
m_Connected = NULL;
// Since the procedure is already returning an error code, there
// is nothing else this function can do to report the error.
EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) );
return hr;
}
/* Called when we want to terminate a pin connection */
STDMETHODIMP
CBasePin::Disconnect()
{
CAutoLock cObjectLock(m_pLock);
/* See if the filter is active */
if (!IsStopped()) {
return VFW_E_NOT_STOPPED;
}
return DisconnectInternal();
}
STDMETHODIMP
CBasePin::DisconnectInternal()
{
ASSERT(CritCheckIn(m_pLock));
if (m_Connected) {
HRESULT hr = BreakConnect();
if( FAILED( hr ) ) {
// There is usually a bug in the program if BreakConnect() fails.
DbgBreak( "WARNING: BreakConnect() failed in CBasePin::Disconnect()." );
return hr;
}
m_Connected->Release();
m_Connected = NULL;
return S_OK;
} else {
// no connection - not an error
return S_FALSE;
}
}
/* Return an AddRef()'d pointer to the connected pin if there is one */
STDMETHODIMP
CBasePin::ConnectedTo(
IPin **ppPin
)
{
CheckPointer(ppPin,E_POINTER);
ValidateReadWritePtr(ppPin,sizeof(IPin *));
//
// It's pointless to lock here.
// The caller should ensure integrity.
//
IPin *pPin = m_Connected;
*ppPin = pPin;
if (pPin != NULL) {
pPin->AddRef();
return S_OK;
} else {
ASSERT(*ppPin == NULL);
return VFW_E_NOT_CONNECTED;
}
}
/* Return the media type of the connection */
STDMETHODIMP
CBasePin::ConnectionMediaType(
AM_MEDIA_TYPE *pmt
)
{
CheckPointer(pmt,E_POINTER);
ValidateReadWritePtr(pmt,sizeof(AM_MEDIA_TYPE));
CAutoLock cObjectLock(m_pLock);
/* Copy constructor of m_mt allocates the memory */
if (IsConnected()) {
CopyMediaType( pmt, &m_mt );
return S_OK;
} else {
((CMediaType *)pmt)->InitMediaType();
return VFW_E_NOT_CONNECTED;
}
}
/* Return information about the filter we are connect to */
STDMETHODIMP
CBasePin::QueryPinInfo(
PIN_INFO * pInfo
)
{
CheckPointer(pInfo,E_POINTER);
ValidateReadWritePtr(pInfo,sizeof(PIN_INFO));
pInfo->pFilter = m_pFilter;
if (m_pFilter) {
m_pFilter->AddRef();
}
if (m_pName) {
lstrcpynW(pInfo->achName, m_pName, sizeof(pInfo->achName)/sizeof(WCHAR));
} else {
pInfo->achName[0] = L'\0';
}
pInfo->dir = m_dir;
return NOERROR;
}
STDMETHODIMP
CBasePin::QueryDirection(
PIN_DIRECTION * pPinDir
)
{
CheckPointer(pPinDir,E_POINTER);
ValidateReadWritePtr(pPinDir,sizeof(PIN_DIRECTION));
*pPinDir = m_dir;
return NOERROR;
}
// Default QueryId to return the pin's name
STDMETHODIMP
CBasePin::QueryId(
LPWSTR * Id
)
{
// We're not going away because someone's got a pointer to us
// so there's no need to lock
return AMGetWideString(Name(), Id);
}
/* Does this pin support this media type WARNING this interface function does
not lock the main object as it is meant to be asynchronous by nature - if
the media types you support depend on some internal state that is updated
dynamically then you will need to implement locking in a derived class */
STDMETHODIMP
CBasePin::QueryAccept(
const AM_MEDIA_TYPE *pmt
)
{
CheckPointer(pmt,E_POINTER);
ValidateReadPtr(pmt,sizeof(AM_MEDIA_TYPE));
/* The CheckMediaType method is valid to return error codes if the media
type is horrible, an example might be E_INVALIDARG. What we do here
is map all the error codes into either S_OK or S_FALSE regardless */
HRESULT hr = CheckMediaType((CMediaType*)pmt);
if (FAILED(hr)) {
return S_FALSE;
}
// note that the only defined success codes should be S_OK and S_FALSE...
return hr;
}
/* This can be called to return an enumerator for the pin's list of preferred
media types. An input pin is not obliged to have any preferred formats
although it can do. For example, the window renderer has a preferred type
which describes a video image that matches the current window size. All
output pins should expose at least one preferred format otherwise it is
possible that neither pin has any types and so no connection is possible */
STDMETHODIMP
CBasePin::EnumMediaTypes(
IEnumMediaTypes **ppEnum
)
{
CheckPointer(ppEnum,E_POINTER);
ValidateReadWritePtr(ppEnum,sizeof(IEnumMediaTypes *));
/* Create a new ref counted enumerator */
*ppEnum = new CEnumMediaTypes(this,
NULL);
if (*ppEnum == NULL) {
return E_OUTOFMEMORY;
}
return NOERROR;
}
/* This is a virtual function that returns a media type corresponding with
place iPosition in the list. This base class simply returns an error as
we support no media types by default but derived classes should override */
HRESULT CBasePin::GetMediaType(int iPosition, CMediaType *pMediaType)
{
UNREFERENCED_PARAMETER(iPosition);
UNREFERENCED_PARAMETER(pMediaType);
return E_UNEXPECTED;
}
/* This is a virtual function that returns the current media type version.
The base class initialises the media type enumerators with the value 1
By default we always returns that same value. A Derived class may change
the list of media types available and after doing so it should increment
the version either in a method derived from this, or more simply by just
incrementing the m_TypeVersion base pin variable. The type enumerators
call this when they want to see if their enumerations are out of date */
LONG CBasePin::GetMediaTypeVersion()
{
return m_TypeVersion;
}
/* Increment the cookie representing the current media type version */
void CBasePin::IncrementTypeVersion()
{
InterlockedIncrement(&m_TypeVersion);
}
/* Called by IMediaFilter implementation when the state changes from Stopped
to either paused or running and in derived classes could do things like
commit memory and grab hardware resource (the default is to do nothing) */
HRESULT
CBasePin::Active(void)
{
return NOERROR;
}
/* Called by IMediaFilter implementation when the state changes from
to either paused to running and in derived classes could do things like
commit memory and grab hardware resource (the default is to do nothing) */
HRESULT
CBasePin::Run(REFERENCE_TIME tStart)
{
UNREFERENCED_PARAMETER(tStart);
return NOERROR;
}
/* Also called by the IMediaFilter implementation when the state changes to
Stopped at which point you should decommit allocators and free hardware
resources you grabbed in the Active call (default is also to do nothing) */
HRESULT
CBasePin::Inactive(void)
{
m_bRunTimeError = FALSE;
return NOERROR;
}
// Called when no more data will arrive
STDMETHODIMP
CBasePin::EndOfStream(void)
{
return S_OK;
}
STDMETHODIMP
CBasePin::SetSink(IQualityControl * piqc)
{
CAutoLock cObjectLock(m_pLock);
if (piqc) ValidateReadPtr(piqc,sizeof(IQualityControl));
m_pQSink = piqc;
return NOERROR;
} // SetSink
STDMETHODIMP
CBasePin::Notify(IBaseFilter * pSender, Quality q)
{
UNREFERENCED_PARAMETER(q);
UNREFERENCED_PARAMETER(pSender);
DbgBreak("IQualityControl::Notify not over-ridden from CBasePin. (IGNORE is OK)");
return E_NOTIMPL;
} //Notify
// NewSegment notifies of the start/stop/rate applying to the data
// about to be received. Default implementation records data and
// returns S_OK.
// Override this to pass downstream.
STDMETHODIMP
CBasePin::NewSegment(
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -