amfilter.cpp.svn-base

来自「ffshow源码」· SVN-BASE 代码 · 共 2,432 行 · 第 1/5 页

SVN-BASE
2,432
字号
    m_bCanReconnectWhenActive(false),    m_bTryMyTypesFirst(false),    m_dRate(1.0){    /*  WARNING - pFilter is often not a properly constituted object at        this state (in particular QueryInterface may not work) - this        is because its owner is often its containing object and we        have been called from the containing object's constructor so        the filter's owner has not yet had its CUnknown constructor        called    */    ASSERT(pFilter != NULL);    ASSERT(pLock != NULL);    if (pName) {        DWORD nameLen = lstrlenW(pName)+1;        m_pName = new WCHAR[nameLen];        if (m_pName) {            CopyMemory(m_pName, pName, nameLen*sizeof(WCHAR));        }    }#ifdef DEBUG    m_cRef = 0;#endif}#ifdef UNICODECBasePin::CBasePin(const CHAR *pObjectName,           CBaseFilter *pFilter,           CCritSec *pLock,           HRESULT *phr,           LPCWSTR pName,           PIN_DIRECTION dir) :    CUnknown( pObjectName, NULL ),    m_pFilter(pFilter),    m_pLock(pLock),    m_pName(NULL),    m_Connected(NULL),    m_dir(dir),    m_bRunTimeError(FALSE),    m_pQSink(NULL),    m_TypeVersion(1),    m_tStart(),    m_tStop(MAX_TIME),    m_bCanReconnectWhenActive(false),    m_bTryMyTypesFirst(false),    m_dRate(1.0){    /*  WARNING - pFilter is often not a properly constituted object at        this state (in particular QueryInterface may not work) - this        is because its owner is often its containing object and we        have been called from the containing object's constructor so        the filter's owner has not yet had its CUnknown constructor        called    */    ASSERT(pFilter != NULL);    ASSERT(pLock != NULL);    if (pName) {        DWORD nameLen = lstrlenW(pName)+1;        m_pName = new WCHAR[nameLen];        if (m_pName) {            CopyMemory(m_pName, pName, nameLen*sizeof(WCHAR));        }    }#ifdef DEBUG    m_cRef = 0;#endif}#endif/* Destructor since a connected pin holds a reference count on us there is   no way that we can be deleted unless we are not currently connected */CBasePin::~CBasePin(){    //  We don't call disconnect because if the filter is going away    //  all the pins must have a reference count of zero so they must    //  have been disconnected anyway - (but check the assumption)    ASSERT(m_Connected == FALSE);    delete[] m_pName;    // check the internal reference count is consistent    ASSERT(m_cRef == 0);}/* Override this to say what interfaces we support and where */STDMETHODIMPCBasePin::NonDelegatingQueryInterface(REFIID riid, void ** ppv){    /* Do we have this interface */    if (riid == IID_IPin) {        return GetInterface((IPin *) this, ppv);    } else if (riid == IID_IQualityControl) {        return GetInterface((IQualityControl *) this, ppv);    } else {        return CUnknown::NonDelegatingQueryInterface(riid, ppv);    }}/* Override to increment the owning filter's reference count */STDMETHODIMP_(ULONG)CBasePin::NonDelegatingAddRef(){    ASSERT(InterlockedIncrement(&m_cRef) > 0);    return m_pFilter->AddRef();}/* Override to decrement the owning filter's reference count */STDMETHODIMP_(ULONG)CBasePin::NonDelegatingRelease(){    ASSERT(InterlockedDecrement(&m_cRef) >= 0);    return m_pFilter->Release();}/* Displays pin connection information */#ifdef DEBUGvoidCBasePin::DisplayPinInfo(IPin *pReceivePin){    if (DbgCheckModuleLevel(LOG_TRACE, CONNECT_TRACE_LEVEL)) {        PIN_INFO ConnectPinInfo;        PIN_INFO ReceivePinInfo;        if (FAILED(QueryPinInfo(&ConnectPinInfo))) {            lstrcpyW(ConnectPinInfo.achName, L"Bad Pin");        } else {            QueryPinInfoReleaseFilter(ConnectPinInfo);        }        if (FAILED(pReceivePin->QueryPinInfo(&ReceivePinInfo))) {            lstrcpyW(ReceivePinInfo.achName, L"Bad Pin");        } else {            QueryPinInfoReleaseFilter(ReceivePinInfo);        }        DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Trying to connect Pins :")));        DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("    <%ls>"), ConnectPinInfo.achName));        DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("    <%ls>"), ReceivePinInfo.achName));    }}#endif/* Displays general information on the pin media type */#ifdef DEBUGvoid CBasePin::DisplayTypeInfo(IPin *pPin, const CMediaType *pmt){    UNREFERENCED_PARAMETER(pPin);    if (DbgCheckModuleLevel(LOG_TRACE, CONNECT_TRACE_LEVEL)) {        DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Trying media type:")));        //DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("    major type:  %hs"),        //       GuidNames[*pmt->Type()]));        //DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("    sub type  :  %hs"),        //       GuidNames[*pmt->Subtype()]));    }}#endif/* Asked to connect to a pin. A pin is always attached to an owning filter   object so we always delegate our locking to that object. We first of all   retrieve a media type enumerator for the input pin and see if we accept   any of the formats that it would ideally like, failing that we retrieve   our enumerator and see if it will accept any of our preferred types */STDMETHODIMPCBasePin::Connect(    IPin * pReceivePin,    const AM_MEDIA_TYPE *pmt   // optional media type){    CheckPointer(pReceivePin,E_POINTER);    ValidateReadPtr(pReceivePin,sizeof(IPin));    CAutoLock cObjectLock(m_pLock);    DisplayPinInfo(pReceivePin);    /* See if we are already connected */    if (m_Connected) {        DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Already connected")));        return VFW_E_ALREADY_CONNECTED;    }    /* See if the filter is active */    if (!IsStopped() && !m_bCanReconnectWhenActive) {        return VFW_E_NOT_STOPPED;    }    // Find a mutually agreeable media type -    // Pass in the template media type. If this is partially specified,    // each of the enumerated media types will need to be checked against    // it. If it is non-null and fully specified, we will just try to connect    // with this.    const CMediaType * ptype = (CMediaType*)pmt;    HRESULT hr = AgreeMediaType(pReceivePin, ptype);    if (FAILED(hr)) {        DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Failed to agree 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 hr;    }    // Check downstream filter    // Does Video Renderer support multithreading?    // "Video Renderer" includes VMR7 and old Video Renderer that does not support multithreading.    PIN_INFO pPinInfo;    FILTER_INFO pFilterInfo;    IVMRFilterConfig* pvObject;    HRESULT hr1;    m_IsOldVideoRenderer=false;    pReceivePin->QueryPinInfo(&pPinInfo);    if(pPinInfo.pFilter){        pPinInfo.pFilter->QueryFilterInfo(&pFilterInfo);	if(pFilterInfo.pGraph){	    if(wcscmp(pFilterInfo.achName,L"Video Renderer")==0){		if(pPinInfo.pFilter->QueryInterface(IID_IVMRFilterConfig,(void**)(&pvObject))!=S_OK){ // Query if it is VMR7.                    // Video Renderer should not be called from child thread.		    m_IsOldVideoRenderer=true;                }		else{		    pvObject->Release();                }            }	    pFilterInfo.pGraph->Release();        }	pPinInfo.pFilter->Release();    }    DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Connection succeeded")));    return NOERROR;}// given a specific media type, attempt a connection (includes// checking that the type is acceptable to this pin)HRESULTCBasePin::AttemptConnection(    IPin* pReceivePin,      // connect to this pin    const CMediaType* pmt   // using this type){    // The caller should hold the filter lock becasue this function    // uses m_Connected.  The caller should also hold the filter lock    // because this function calls SetMediaType(), IsStopped() and    // CompleteConnect().    ASSERT(CritCheckIn(m_pLock));    // Check that the connection is valid  -- need to do this for every    // connect attempt since BreakConnect will undo it.    HRESULT hr = CheckConnect(pReceivePin);    if (FAILED(hr)) {        DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("CheckConnect failed")));        // 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;    }    DisplayTypeInfo(pReceivePin, pmt);    /* Check we will accept this media type */    hr = CheckMediaType(pmt);    if (hr == NOERROR) {        /*  Make ourselves look connected otherwise ReceiveConnection            may not be able to complete the connection        */        m_Connected = pReceivePin;        m_Connected->AddRef();        hr = SetMediaType(pmt);        if (SUCCEEDED(hr)) {            /* See if the other pin will accept this type */            hr = pReceivePin->ReceiveConnection((IPin *)this, pmt);            if (SUCCEEDED(hr)) {                /* Complete the connection */                hr = CompleteConnect(pReceivePin);                if (SUCCEEDED(hr)) {                    return hr;                } else {                    DbgLog((LOG_TRACE,                            CONNECT_TRACE_LEVEL,                            TEXT("Failed to complete connection")));                    pReceivePin->Disconnect();                }            }        }    } else {        // we cannot use this media type        // 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;        }    }    // BreakConnect and release any connection here in case CheckMediaType    // failed, or if we set anything up during a call back during    // ReceiveConnection.    // 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() ) );    /*  If failed then undo our state */    if (m_Connected) {        m_Connected->Release();        m_Connected = NULL;    }    return hr;}/* Given an enumerator we cycle through all the media types it proposes and   firstly suggest them to our derived pin class and if that succeeds try   them with the pin in a ReceiveConnection call. This means that if our pin   proposes a media type we still check in here that we can support it. This   is deliberate so that in simple cases the enumerator can hold all of the   media types even if some of them are not really currently available */HRESULT CBasePin::TryMediaTypes(    IPin *pReceivePin,    const CMediaType *pmt,    IEnumMediaTypes *pEnum){    /* Reset the current enumerator position */    HRESULT hr = pEnum->Reset();    if (FAILED(hr)) {        return hr;    }    CMediaType *pMediaType = NULL;    ULONG ulMediaCount = 0;    // attempt to remember a specific error code if there is one    HRESULT hrFailure = S_OK;    for (;;) {        /* Retrieve the next media type NOTE each time round the loop the           enumerator interface will allocate another AM_MEDIA_TYPE structure           If we are successful then we copy it into our output object, if           not then we must delete the memory allocated before returning */        hr = pEnum->Next(1, (AM_MEDIA_TYPE**)&pMediaType,&ulMediaCount);        if (hr != S_OK) {            if (S_OK == hrFailure) {                hrFailure = VFW_E_NO_ACCEPTABLE_TYPES;            }            return hrFailure;        }        ASSERT(ulMediaCount == 1);        ASSERT(pMediaType);        // check that this matches the partial type (if any)        if ((pmt == NULL) ||            pMediaType->MatchesPartial(pmt)) {            hr = AttemptConnection(pReceivePin, pMediaType);            // attempt to remember a specific error code            if (FAILED(hr) &&            SUCCEEDED(hrFailure) &&            (hr != E_FAIL) &&            (hr != E_INVALIDARG) &&            (hr != VFW_E_TYPE_NOT_ACCEPTED)) {                hrFailure = hr;            }        } else {            hr = VFW_E_NO_ACCEPTABLE_TYPES;        }        DeleteMediaType(pMediaType);        if (S_OK == hr) {            return hr;        }    }}/* This is called to make the connection, including the taask of finding   a media type for the pin connection. pmt is the proposed media type   from the Connect call: if this is fully specified, we will try that.   Otherwise we enumerate and try all the input pin's types first and   if that fails we then enumerate and try all our preferred media types.   For each media type we check it against pmt (if non-null and partially   specified) as well as checking that both pins will accept it. */HRESULT CBasePin::AgreeMediaType(    IPin *pReceivePin,    const CMediaType *pmt){    ASSERT(pReceivePin);    IEnumMediaTypes *pEnumMediaTypes = NULL;    // if the media type is fully specified then use that    if ( (pmt != NULL) && (!pmt->IsPartiallySpecified())) {        // if this media type fails, then we must fail the connection        // since if pmt is nonnull we are only allowed to connect        // using a type that matches it.        return AttemptConnection(pReceivePin, pmt);    }    /* Try the other pin's enumerator */    HRESULT hrFailure = VFW_E_NO_ACCEPTABLE_TYPES;    for (int i = 0; i < 2; i++) {        HRESULT hr;        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 */HRESULTCBasePin::CompleteConnect(IPin *pReceivePin){    UNREFERENCED_PARAMETER(pReceivePin);    return NOERROR;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?