⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 samplecgb.cpp

📁 通用摄像头驱动的应用程序部分
💻 CPP
📖 第 1 页 / 共 3 页
字号:

HRESULT 
ISampleCaptureGraphBuilder::GetMedium( 
                        CComPtr<IPin> pPin, 
                        REGPINMEDIUM& regPinMedium )
{
    if( !pPin )
    {
        return E_POINTER;
    }

    CComPtr<IKsPin> pKsPin;
    HRESULT hr = pPin.QueryInterface( &pKsPin );
    if( FAILED( hr ) )
    {
        return hr;
    }

    PKSMULTIPLE_ITEM pmi;
    hr = pKsPin->KsQueryMediums( &pmi );
    if( FAILED( hr ) )
    {
        return hr;
    }
    
    REGPINMEDIUM *pMedium = (REGPINMEDIUM *)(pmi + 1);
    for( ULONG i  = 0; i < pmi->Count; i++ )
    {
        if( !::IsEqualGUID( pMedium->clsMedium, GUID_NULL ) &&
            !::IsEqualGUID( pMedium->clsMedium, KSMEDIUMSETID_Standard )
        )
        {
            regPinMedium.clsMedium = pMedium->clsMedium;
            regPinMedium.dw1 = pMedium->dw1;
            regPinMedium.dw2 = pMedium->dw2;
            CoTaskMemFree( pmi );
            return S_OK;
        }
    }

    regPinMedium.clsMedium = GUID_NULL;
    regPinMedium.dw1 = 0;
    regPinMedium.dw2 = 0;
    CoTaskMemFree( pmi );
    return S_OK;
}



//
//  Adds the MPEG2 demux and renders 
//  the audio and video pin until the end (until the renderers)
//

HRESULT ISampleCaptureGraphBuilder::AddMPEG2Demux( )
{
    if( pMPEG2Demux_ )
    {
        //
        //  Instead of a MPEG2 demux there is a 
        //  dump filter in which the file will be dumped
        //
        return S_OK;
    }

    HRESULT hr = pMPEG2Demux_.CoCreateInstance(CLSID_MPEG2Demultiplexer);
    if( FAILED( hr ) )
    {
        return hr;
    }
    return graph_->AddFilter( static_cast<IBaseFilter *>( pMPEG2Demux_ ), L"MPEG2 Demux" );
}



HRESULT 
ISampleCaptureGraphBuilder::FindVideoPin( 
                                CComPtr<IBaseFilter> pFilter, 
                                CComPtr<IPin>& pPin  )
{
    if( !pFilter )
    {
        return E_POINTER;
    }

    CComPtr<IEnumPins> pEnumPins;
    HRESULT hr = pFilter->EnumPins( &pEnumPins );
    if( FAILED( hr ) )
    {
        return hr;
    }

    CComPtr<IPin>   pTempPin;
    ULONG           fetched;
    hr = pEnumPins->Reset( );

    while( pTempPin.Release(), S_OK == pEnumPins->Next( 1, &pTempPin, &fetched ) )
    {
        if( IsVideoPin( pTempPin ) )
        {
#ifdef DEBUG
            USES_CONVERSION;
            PIN_INFO info;
            pTempPin->QueryPinInfo( &info );
            info.pFilter->Release( );
#endif
            pPin = pTempPin;
            return S_OK;
        }
    }
    return E_FAIL;
}

BOOL ISampleCaptureGraphBuilder::IsAudioPin( CComPtr<IPin> pPin )
{
    if( !pPin )
    {
        return FALSE;   // NULL pointer
    }

    return HasMediaType( pPin, MEDIATYPE_Audio) ;
}


BOOL ISampleCaptureGraphBuilder::HasMediaType(CComPtr<IPin> pPin,  REFGUID majorType )
{
    if( !pPin )
    {
        return FALSE;
    }

    CComPtr<IEnumMediaTypes> pMediaTypes;
    HRESULT hr = pPin->EnumMediaTypes( &pMediaTypes );
    if( FAILED( hr ) )
    {
        return FALSE;
    }

    hr = pMediaTypes->Reset();
    if( FAILED( hr ) )
    {
        return FALSE;
    }

    ULONG           fetched;
    AM_MEDIA_TYPE   *mediaType;

    while( S_OK == pMediaTypes->Next( 1, &mediaType, &fetched ) )
    {
        if( ::IsEqualGUID( mediaType->majortype, majorType ) )
        {
            DeleteMediaType( mediaType );
            return TRUE;
        }
        DeleteMediaType( mediaType );
    }

    return FALSE;

}


HRESULT 
ISampleCaptureGraphBuilder::FindAudioPin( 
                                CComPtr<IBaseFilter> pFilter, 
                                CComPtr<IPin>& pPin  )
{
    if( !pFilter )
    {
        return E_POINTER;
    }

    CComPtr<IEnumPins> pEnumPins;
    HRESULT hr = pFilter->EnumPins( &pEnumPins );
    if( FAILED( hr ) )
    {
        return hr;
    }

    CComPtr<IPin>   pTempPin;
    ULONG           fetched;
    hr = pEnumPins->Reset( );

    while( pTempPin.Release(), S_OK == pEnumPins->Next( 1, &pTempPin, &fetched ) )
    {
        if( IsAudioPin( pTempPin ) )
        {
#ifdef DEBUG
            USES_CONVERSION;
            PIN_INFO info;
            pTempPin->QueryPinInfo( &info );
            info.pFilter->Release( );
#endif
            pPin = pTempPin;
            return S_OK;
        }
    }
    return E_FAIL;
}



HRESULT ISampleCaptureGraphBuilder::FindEncoder( 
                CComPtr<IEnumMoniker> pEncoders, 
                REGPINMEDIUM pinMedium, 
                CComPtr<IBaseFilter>& pEncoder  )
{
    if( ! pEncoders )
    {
        return E_INVALIDARG;
    }

    if( IsEqualGUID( pinMedium.clsMedium, GUID_NULL ) ||
        IsEqualGUID( pinMedium.clsMedium, KSMEDIUMSETID_Standard ) )
    {
        return E_INVALIDARG;
    }

    HRESULT                 hr;
    CComPtr<IBaseFilter>    pFilter;
    CComPtr<IMoniker>       pMoniker;
    ULONG                   fetched;
    CComPtr<IPin>           pPin;

    while( pFilter.Release(), pMoniker.Release(), 
           S_OK == pEncoders->Next( 1, &pMoniker, &fetched ) )
    {
        hr = pMoniker->BindToObject(
            0, 0, IID_IBaseFilter, reinterpret_cast<void **>( &pFilter ) );
        if( FAILED( hr ) )
        {
            continue;
        }

        hr = FindPin( pFilter, pinMedium, PINDIR_INPUT, TRUE, pPin );
        if( SUCCEEDED( hr ) )
        {
            pEncoder = pFilter;
            return hr;
        }
    }

    return E_FAIL;
}



HRESULT 
ISampleCaptureGraphBuilder::RenderToMPEG2Demux( 
                            CComPtr<IPin> pPin, 
                            CComPtr<IEnumMoniker> pEncoders)
{
    if( !pPin || !pEncoders )
    {
        return E_INVALIDARG;
    }

    REGPINMEDIUM pinMedium ;
    pinMedium.clsMedium = GUID_NULL;
    pinMedium.dw1 = 0;
    pinMedium.dw2 = 0;

    CComPtr<IBaseFilter> pFilter;
    CComPtr<IMoniker>    pMoniker;
    ULONG                fetched;
    HRESULT              hr;

    while( pFilter.Release(), pMoniker.Release(), S_OK == pEncoders->Next( 1, &pMoniker, &fetched ) )
    {
        hr = pMoniker->BindToObject(
            0, 0, IID_IBaseFilter, reinterpret_cast<void **>( &pFilter ) );
        if( FAILED( hr ) )
        {
            continue;
        }

        hr = graph_->AddFilter( pFilter, L"Encoder" );
        if( FAILED( hr ) )
        {
            continue;
        }

        hr = ConnectPin( pPin, pFilter );
        if( FAILED( hr ) )
        {
            graph_->RemoveFilter( pFilter );
            continue;
        }

        hr = ConnectEncoderToMPEG2Demux( pFilter, pinMedium );
        if( SUCCEEDED( hr ) )
        {
            pEncoder_ = pFilter;
            return S_OK;
        }
        graph_->RemoveFilter( pFilter );
    }

    return E_FAIL;
}


//
//  Loop through every encoder available on system.
//  Look first after the one that has a special medium if
//  there is a special one on pPin.
//  Otherwise, try to render using ICaptureGrapBuilder2
//  and the encoder that matches this will be the chosen one/
//  If the encoder is found, then this will be rendered to the 
//  MPEG2 demux.
//

HRESULT 
    ISampleCaptureGraphBuilder::RenderToMPEG2Demux( 
        CComPtr<IPin> pPin, 
        const REGPINMEDIUM& pinMedium, 
        CComPtr<IEnumMoniker> pEncoders 
)
{
    //
    //  The pin has a special medium, 
    //  there shold be an encoder with the same 
    //  medium
    //
    CComPtr< IBaseFilter > pEncoder; 
    HRESULT hr = FindEncoder( pEncoders, pinMedium, pEncoder );
    if( FAILED( hr ) )
    {
        return hr;
    }

    hr = graph_->AddFilter( pEncoder, L"Encoder" );
    if( FAILED( hr ) )
    {
        return hr;
    }

    hr = ConnectPin( pPin, pEncoder );
    if( FAILED(  hr ) )
    {
        hr = graph_->RemoveFilter( pEncoder );
        return hr;
    }

    //
    //  the video pin was rendered to the same 
    //  ( hardware? ) encoder with the same mediu
    //
    hr = ConnectEncoderToMPEG2Demux( pEncoder, pinMedium );
    if( FAILED( hr ) )
    {
        hr = graph_->RemoveFilter( pEncoder );
        return hr;
    }

    pEncoder_ = pEncoder;
    return S_OK;
}



HRESULT 
ISampleCaptureGraphBuilder::RenderToMPEG2Demux( CComPtr<IPin> pPin )
{
    if( !pPin )
    {
        return E_INVALIDARG;
    }

    REGPINMEDIUM pinMedium;
    HRESULT hr = GetMedium( pPin, pinMedium );
    if( FAILED( hr ) )
    {
        return hr;
    }


    CComPtr< IEnumMoniker > pEncoders;
    if( ::IsEqualGUID( pinMedium.clsMedium, GUID_NULL ) )
    {
        //
        //  Search throgh the codec category 
        //  
        hr = GetEncodersByCategory( pEncoders );
        if( FAILED( hr ) )
        {
                return hr;
        }

        hr = RenderToMPEG2Demux( pPin, pEncoders );
        if( SUCCEEDED( hr ) )
        {
            return S_OK;
        }
    }
    else
    {
        //
        //  search through encoders category; identify
        //  the encoder using the medium
        //
        hr = GetEncodersByCategory( pEncoders );
        if( FAILED( hr ) )
        {
            return hr;
        }

        hr = RenderToMPEG2Demux( pPin, pinMedium, pEncoders  );
        if( SUCCEEDED( hr ) )
        {
            return S_OK;
        }
        
        pEncoders = NULL;
        hr = GetEncodersByEnumerating( pPin, pinMedium, pEncoders );
        if( FAILED( hr ) )
        {
            return hr;
        }

        hr = RenderToMPEG2Demux( pPin, pinMedium, pEncoders );
        if( FAILED( hr ) )
        {
            return hr;
        }
    }
    return S_OK;
}


//
//  pEncoder - the encoder to be connected using a multiplexer
//
//
HRESULT 
ISampleCaptureGraphBuilder::ConnectEncoderToMPEG2Demux( 
                CComPtr< IBaseFilter > pEncoder, 
                const REGPINMEDIUM& pinMedium )
{

    REGPINMEDIUM regPinMedium ;
    regPinMedium.clsMedium = GUID_NULL;
    regPinMedium.dw1 = 0;
    regPinMedium.dw2 = 0;
    //
    //  try a direct connection between 
    //  codec and MPEG2Demux
    //
    HRESULT hr = ConnectFilters( 
                        pEncoder, 
                        pMPEG2Demux_ );
    if( SUCCEEDED( hr ) )
    {
        return S_OK;
    }

    //
    //  no luck
    //  maybe I need a multiplexer 
    //
    CComPtr< IEnumMoniker > pMultiplexers;
    hr = GetMultiplexersByCategory( pMultiplexers );
    if( FAILED( hr ) )
    {
        return hr;
    }
    hr = ConnectMultiplexerToMPEG2Demux( pEncoder, pMultiplexers );
    if( SUCCEEDED( hr ) )
    {
        return S_OK;
    }

    if( FALSE == ::IsEqualGUID( pinMedium.clsMedium, GUID_NULL ) )
    {
        //
        //  get the multiplexers using IFilterMapper2
        //  assuming that the encoder and the multiplexer have the same medium
        //
        pMultiplexers = NULL;
        hr = GetMultiplexersByFilterMapper( pMultiplexers, pinMedium );
        if( FAILED( hr ) )
        {
            return hr;
        }
        hr = ConnectMultiplexerToMPEG2Demux( pEncoder, pMultiplexers );
        if( SUCCEEDED( hr ) )
        {
            return S_OK;
        }
    }
    return E_FAIL;
}


HRESULT 
ISampleCaptureGraphBuilder::GetMultiplexersByCategory( CComPtr<IEnumMoniker>& pMultiplexers )
{
    CComPtr<ICreateDevEnum> pDeviceEnum;
        
    HRESULT hr = pDeviceEnum.CoCreateInstance( CLSID_SystemDeviceEnum );
    if( FAILED( hr ) )
    {
        return hr;
    }

    return pDeviceEnum->CreateClassEnumerator( KSCATEGORY_MULTIPLEXER, &pMultiplexers, 0 );
}

HRESULT 
ISampleCaptureGraphBuilder::GetMultiplexersByFilterMapper( 
                                    CComPtr<IEnumMoniker>& pMultiplexers, 
                                    const REGPINMEDIUM& pinMedium  )
{
    return E_NOTIMPL;
}


HRESULT 
ISampleCaptureGraphBuilder::ConnectMultiplexerToMPEG2Demux( 
                                        CComPtr<IBaseFilter> pEncoder, 
                                        CComPtr< IEnumMoniker > pMultiplexers )
{
    if( !pEncoder || !pMultiplexers )
    {
        return E_INVALIDARG;
    }

    CComPtr<IBaseFilter> pFilter;
    CComPtr<IMoniker>   pMoniker;
    ULONG               fetched;
    HRESULT             hr;

    while( pFilter.Release(), pMoniker.Release(), 
           S_OK == pMultiplexers->Next( 1, &pMoniker, &fetched ) )
    {
        hr = pMoniker->BindToObject(
            0, 0, IID_IBaseFilter, reinterpret_cast<void **>( &pFilter ) );
        if( FAILED( hr ) )
        {
            continue;
        }

        hr = graph_->AddFilter( pFilter, NULL );
        if( FAILED( hr ) )
        {
            continue;
        }

        //
        //  connect the encoder to the multiplexer
        //
        hr = ConnectFilters( pEncoder, pFilter );
        if( FAILED( hr ) )
        {
            graph_->RemoveFilter( pFilter );
            continue;
        }

        //
        //  connect the multiplexer to the encoder
        //
        hr = ConnectFilters( pFilter, pMPEG2Demux_ );
        if( SUCCEEDED( hr ) )
        {
            pMultiplexer_ = pFilter;
            return S_OK;
        }

    }

⌨️ 快捷键说明

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