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

📄 samplecgb.cpp

📁 通用摄像头驱动的应用程序部分
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//------------------------------------------------------------------------------
// File: SampleCGB.cpp
//
// Desc: DirectShow sample code - Sample capture graph builder class
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------------------------


#include <streams.h>
#include "ks.h"
#include "ksproxy.h"
#include <atlbase.h>

#include  "SampleCGB.h"


//
//  ISampleCaptureGraphBuilder is trying to connect the video pin to the MPEG2 demux.
//  The possible configurations are:
//
//
//
// 1. capture filter- > audio / video encoder & multiplexer -> MPEG2 demux
//
// ----------------------         ---------------------------------------    ---------------
// |                   v|   --->  |                                     |    |             |
// | Capture Filter     |         | Audio / video encoder & Multiplexer |  ->| MPEG2 demux |
// |                   a|   --->  |                                     |    |             |
// ----------------------         ---------------------------------------    ---------------    
//
//
//
//
//
//                        -> audio encoder -> 
//  2. capture filter                           multiplexer -> MPEG2 demux
//                        -> video encoder ->   
//
//  -----------------------     -----------------    ----------------     ---------------   
//  |                    a|  -> | audio encoder | -> |              |     |             |
//  |                     |     -----------------    |              |     |             |
//  | capture filter      |                          |  multiplexer |  -> | MPEG2 demux |
//  |                     |     -----------------    |              |     |             |
//  |                    v|  -> | video encoder | -> |              |     |             |
//  -----------------------     -----------------    ----------------     ---------------
//
//
//
//
//
//                      a
//  3.  capture filter      - audio & video encoder -> multiplexer -> MPEG2 demux
//                      v
//
//  -----------------------     -----------------    ----------------     ---------------   
//  |                    a|  -> | audio encoder | -> |              |     |             |
//  |                     |     |               |    |              |     |             |
//  | capture filter      |     |               |    |  multiplexer |  -> | MPEG2 demux |
//  |                     |     |               |    |              |     |             |
//  |                    v|  -> | video encoder | -> |              |     |             |
//  -----------------------     -----------------    ----------------     ---------------
//
//
//
//
//  4. capture filter -> MPEG2 demux
//
// ------------------------------       ----------------
// |                   MPEG2 PS | --->  |              |
// | Capture Filter             |       | MPEG2 demux  |
// |                            |       |              |
// ------------------------------       ----------------    
//
//


//
//  How the algorithm works: 
//      1. the video pin doesn't stream MPEG2    
//          1. tries to connect the pin to an encoder   
//          2. tries to connect the encoder directly to the MPEG2 demux
//          3. if not possible, tries to find a multiplexor that can be connected to the 
//             encoder and MPEG2 demux
//          4. connect audio pin to the MPEG2 demux using the same algorithm as in 
//             video pin case
//           
//      2. if pin streams MPEG2 PS, then connect it to the MPEG2 demux
//      3. program the MPEG2 demux
//      4. render the video and the audio pin from the MPEG2 demux      
//      


static 
BYTE
Mpeg2ProgramVideo [] = {
    0x00, 0x00, 0x00, 0x00,                         //  .hdr.rcSource.left              = 0x00000000
    0x00, 0x00, 0x00, 0x00,                         //  .hdr.rcSource.top               = 0x00000000
    0xD0, 0x02, 0x00, 0x00,                         //  .hdr.rcSource.right             = 0x000002d0
    0xE0, 0x01, 0x00, 0x00,                         //  .hdr.rcSource.bottom            = 0x000001e0
    0x00, 0x00, 0x00, 0x00,                         //  .hdr.rcTarget.left              = 0x00000000
    0x00, 0x00, 0x00, 0x00,                         //  .hdr.rcTarget.top               = 0x00000000
    0x00, 0x00, 0x00, 0x00,                         //  .hdr.rcTarget.right             = 0x00000000
    0x00, 0x00, 0x00, 0x00,                         //  .hdr.rcTarget.bottom            = 0x00000000
    0x00, 0x09, 0x3D, 0x00,                         //  .hdr.dwBitRate                  = 0x003d0900
    0x00, 0x00, 0x00, 0x00,                         //  .hdr.dwBitErrorRate             = 0x00000000
    0x63, 0x17, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, //  .hdr.AvgTimePerFrame            = 0x0000000000051763
    0x00, 0x00, 0x00, 0x00,                         //  .hdr.dwInterlaceFlags           = 0x00000000
    0x00, 0x00, 0x00, 0x00,                         //  .hdr.dwCopyProtectFlags         = 0x00000000
    0x04, 0x00, 0x00, 0x00,                         //  .hdr.dwPictAspectRatioX         = 0x00000004
    0x03, 0x00, 0x00, 0x00,                         //  .hdr.dwPictAspectRatioY         = 0x00000003
    0x00, 0x00, 0x00, 0x00,                         //  .hdr.dwReserved1                = 0x00000000
    0x00, 0x00, 0x00, 0x00,                         //  .hdr.dwReserved2                = 0x00000000
    0x28, 0x00, 0x00, 0x00,                         //  .hdr.bmiHeader.biSize           = 0x00000028
    0xD0, 0x02, 0x00, 0x00,                         //  .hdr.bmiHeader.biWidth          = 0x000002d0
    0xE0, 0x01, 0x00, 0x00,                         //  .hdr.bmiHeader.biHeight         = 0x00000000
    0x00, 0x00,                                     //  .hdr.bmiHeader.biPlanes         = 0x0000
    0x00, 0x00,                                     //  .hdr.bmiHeader.biBitCount       = 0x0000
    0x00, 0x00, 0x00, 0x00,                         //  .hdr.bmiHeader.biCompression    = 0x00000000
    0x00, 0x00, 0x00, 0x00,                         //  .hdr.bmiHeader.biSizeImage      = 0x00000000
    0xD0, 0x07, 0x00, 0x00,                         //  .hdr.bmiHeader.biXPelsPerMeter  = 0x000007d0
    0x27, 0xCF, 0x00, 0x00,                         //  .hdr.bmiHeader.biYPelsPerMeter  = 0x0000cf27
    0x00, 0x00, 0x00, 0x00,                         //  .hdr.bmiHeader.biClrUsed        = 0x00000000
    0x00, 0x00, 0x00, 0x00,                         //  .hdr.bmiHeader.biClrImportant   = 0x00000000
    0x98, 0xF4, 0x06, 0x00,                         //  .dwStartTimeCode                = 0x0006f498
    0x56, 0x00, 0x00, 0x00,                         //  .cbSequenceHeader               = 0x00000056
    0x02, 0x00, 0x00, 0x00,                         //  .dwProfile                      = 0x00000002
    0x02, 0x00, 0x00, 0x00,                         //  .dwLevel                        = 0x00000002
    0x00, 0x00, 0x00, 0x00,                         //  .Flags                          = 0x00000000
                                                    //  .dwSequenceHeader [1]
    0x00, 0x00, 0x01, 0xB3, 0x2D, 0x01, 0xE0, 0x24,
    0x09, 0xC4, 0x23, 0x81, 0x10, 0x11, 0x11, 0x12, 
    0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14, 
    0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x15, 
    0x15, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 
    0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 
    0x18, 0x18, 0x18, 0x19, 0x18, 0x18, 0x18, 0x19, 
    0x1A, 0x1A, 0x1A, 0x1A, 0x19, 0x1B, 0x1B, 0x1B, 
    0x1B, 0x1B, 0x1C, 0x1C, 0x1C, 0x1C, 0x1E, 0x1E, 
    0x1E, 0x1F, 0x1F, 0x21, 0x00, 0x00, 0x01, 0xB5, 
    0x14, 0x82, 0x00, 0x01, 0x00, 0x00
} ;


static
BYTE
MPEG1AudioFormat [] = {
    0x50, 0x00, 0x02, 0x00, 0x80, 0xBB, 0x00, 0x00,
    0x00, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
    0x16, 0x00, 0x02, 0x00, 0x00, 0xE8, 0x03, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x1C, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
} ;



HRESULT 
ISampleCaptureGraphBuilder::AllocCapFile( LPCOLESTR lpwstr, DWORDLONG dwlSize )
{
    return graphBuilder2_->AllocCapFile( lpwstr, dwlSize );
}


HRESULT 
ISampleCaptureGraphBuilder::ControlStream( const GUID *pCategory,
                                          const GUID *pType,
                                          IBaseFilter *pFilter,
                                          REFERENCE_TIME *pstart,
                                          REFERENCE_TIME *pstop,
                                          WORD wStartCookie,
                                          WORD wStopCookie )
{
    return graphBuilder2_->ControlStream( pCategory, pType, pFilter, 
                                          pstart, pstop, wStartCookie, wStopCookie );
}


HRESULT 
ISampleCaptureGraphBuilder::CopyCaptureFile(  LPOLESTR lpwstrOld,
                                              LPOLESTR lpwstrNew,
                                              int fAllowEscAbort,
                                              IAMCopyCaptureFileProgress *pCallback)
{
    return graphBuilder2_->CopyCaptureFile( lpwstrOld, lpwstrNew, 
                                            fAllowEscAbort, pCallback );
}

HRESULT ISampleCaptureGraphBuilder::FindInterface(const GUID *pCategory,
                                                  const GUID *pType,
                                                  IBaseFilter *pf,
                                                  REFIID riid,
                                                  void **ppint
                                                  )
{
    return graphBuilder2_->FindInterface( pCategory, pType, pf, riid, ppint );
}

HRESULT 
ISampleCaptureGraphBuilder::FindPin( IUnknown *pSource,
                                      PIN_DIRECTION pindir,
                                      const GUID *pCategory,
                                      const GUID *pType,
                                      BOOL fUnconnected,
                                      int num,
                                      IPin **ppPin)
{
    return graphBuilder2_->FindPin( pSource, pindir, pCategory, pType, 
                                    fUnconnected, num, ppPin ); 
}


HRESULT ISampleCaptureGraphBuilder::GetFiltergraph( IGraphBuilder **ppfg )
{
    return graphBuilder2_->GetFiltergraph( ppfg );
}

HRESULT 
ISampleCaptureGraphBuilder::RenderStream( const GUID *pCategory,
                                          const GUID *pType,
                                          IUnknown *pSource,
                                          IBaseFilter *pIntermediate,
                                          IBaseFilter *pSink)
{
    if( !pType ||  !::IsEqualGUID( MEDIATYPE_Stream, *pType ) )
    {
        return graphBuilder2_->RenderStream( pCategory, pType, pSource, 
                                             pIntermediate, pSink );
    }

    
    HRESULT hr;
    if( !graph_ )
    {
        hr = GetFiltergraph( &graph_ );
        if( FAILED( hr ) )
        {
            return hr;
        }
    }

    //
    //  try to build MPEG2 graph
    //
    CComPtr< IBaseFilter > captureFilter;

    hr = pSource->QueryInterface( & captureFilter );
    if( FAILED( hr ) )
    {
        return E_INVALIDARG;
    }

    hr = BuildMPEG2Segment( captureFilter);
    if( pSink || FAILED( hr ) )
    {
        return hr;
    }

    hr = ConfigureMPEG2Demux( pMPEG2Demux_ );
    if( FAILED( hr ) )
    {
        return hr;
    }

    hr = RenderStream(NULL, &MEDIATYPE_Video, pMPEG2Demux_, NULL, NULL );
    if( FAILED( hr ) )
    {
        return hr;
    }

    hr = RenderStream(NULL, &MEDIATYPE_Audio, pMPEG2Demux_, NULL, NULL );
    if( FAILED( hr ) )
    {
        return hr;
    }

    return S_OK;
}


HRESULT 
ISampleCaptureGraphBuilder::SetFiltergraph( IGraphBuilder *pfg )
{
    return graphBuilder2_->SetFiltergraph( pfg );
}


HRESULT 
ISampleCaptureGraphBuilder::SetOutputFileName(  const GUID *pType,
                                                LPCOLESTR lpwstrFile,
                                                IBaseFilter **ppf,
                                                IFileSinkFilter **pSink )
{
    if( ! pType || ! lpwstrFile || !ppf || !pSink )
    {
        return E_INVALIDARG;
    }

    if( !::IsEqualGUID( *pType, MEDIASUBTYPE_Mpeg2 ) )
    {
        return graphBuilder2_->SetOutputFileName(pType, lpwstrFile, ppf, pSink );
    }

    HRESULT hr;
    if( !graph_ )
    {
        hr = GetFiltergraph( &graph_ );
        if( FAILED( hr ) )
        {
            return hr;
        }
    }

    //
    //  Configure the dump filter
    //
    CComPtr< IFileSinkFilter > pDump;
    hr = pDump.CoCreateInstance( CLSID_Dump );
    if( FAILED( hr ) )
    {
        return hr;
    }
    
    hr = pDump->SetFileName( lpwstrFile, NULL );
    if( FAILED( hr ) )
    {
        return hr;
    }

    hr = pDump.QueryInterface( &pMPEG2Demux_ );
    if( FAILED( hr ) )
    {
        return hr;
    }

    hr = graph_->AddFilter( pMPEG2Demux_, L"Dump" );
    if( FAILED( hr ) )
    {
        pMPEG2Demux_ = NULL;
        return hr;
    }

    
    *pSink = pDump;
    return S_OK;
}



//
//  A device can stream directly MPEG2 stream,
//  or it can be linked with a video codec and multiplexer
//
//

//
//  Loop through every media type supported by this pin
//  to see if there is one which can be considered MPEG2
//
BOOL ISampleCaptureGraphBuilder::IsMPEG2Pin( CComPtr<IPin> pPin )
{
    if( !pPin )
    {
        return FALSE;   // NULL pointer
    }
    
    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, MEDIATYPE_Video ) ||
                ::IsEqualGUID( mediaType->majortype, MEDIATYPE_Stream ) 
            )
            &&
            (
                ::IsEqualGUID( mediaType->subtype, MEDIASUBTYPE_MPEG2_VIDEO ) ||
                ::IsEqualGUID( mediaType->subtype,  MEDIASUBTYPE_MPEG2_PROGRAM )
            )
        )
        {
            DeleteMediaType( mediaType );
            return TRUE;
        }
        DeleteMediaType( mediaType );
    }

    return FALSE;
}

BOOL ISampleCaptureGraphBuilder::IsVideoPin( CComPtr<IPin> pPin )
{
    return HasMediaType( pPin, MEDIATYPE_Video );
}



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

    return pDeviceEnum->CreateClassEnumerator( KSCATEGORY_ENCODER, &pEncoders, 0 );
}



HRESULT 
ISampleCaptureGraphBuilder::GetEncodersByEnumerating(
                                        CComPtr< IPin > pPin,   
                                        const REGPINMEDIUM& pinMedium,
                                        CComPtr<IEnumMoniker>& pEncoders )
{
    CComPtr<IFilterMapper2> pFilterMapper2;
    HRESULT hr = pFilterMapper2.CoCreateInstance( CLSID_FilterMapper2 );
    if( FAILED( hr ) )
    {
        return hr;
    }

    hr = pFilterMapper2->EnumMatchingFilters( 
                                &pEncoders, 
                                NULL, 
                                FALSE, 
                                0,          //any merit
                                TRUE, 
                                0, 
                                NULL, 
                                &pinMedium, 
                                NULL, 
                                FALSE, 
                                TRUE, 
                                0, 
                                NULL, 
                                NULL, 
                                NULL );


    return hr;
}


//
//  looks for an MPEG2 pin
//
HRESULT 
ISampleCaptureGraphBuilder::FindMPEG2Pin( 
                        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;
    PIN_DIRECTION   dir;

    hr = pEnumPins->Reset( );
    while( pTempPin.Release(), S_OK == pEnumPins->Next( 1, &pTempPin, &fetched ) )
    {
        hr = pTempPin->QueryDirection( &dir );
        if( FAILED( hr ) || PINDIR_INPUT == dir )
        {
            continue;
        }
        if( IsMPEG2Pin( pTempPin ) )
        {
            pPin = pTempPin;
            return S_OK;
        }
    }
    return E_FAIL;
}

//
//  search the encoder that has this special medium
//  video == TRUE -- look for a video pin
//  video == FALSE -- look for a audio pin  
//
HRESULT ISampleCaptureGraphBuilder::FindPin( 
            CComPtr<IBaseFilter> pFilter, 
            const REGPINMEDIUM& regPinMedium, 
            PIN_DIRECTION direction, 
            BOOL video,             
            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;
    REGPINMEDIUM    regPinMediumTemp;
    PIN_DIRECTION   dir;

    hr = pEnumPins->Reset( );
    while( pTempPin.Release(), S_OK == pEnumPins->Next( 1, &pTempPin, &fetched ) )
    {
        ASSERT( pTempPin );

        hr = pTempPin->QueryDirection( &dir );
        if( FAILED( hr ) || dir != direction )
        {
            continue;
        }

        hr = GetMedium( pTempPin, regPinMediumTemp );
        if( FAILED( hr ) )
        {
            continue;
        }

        if( !IsVideoPin( pTempPin ) )
        {
            continue;
        }

        if( ::IsEqualGUID( regPinMediumTemp.clsMedium, regPinMedium.clsMedium  ) &&
            regPinMediumTemp.dw1 == regPinMedium.dw1 )
        {
            pPin = pTempPin;
            return S_OK;
        }
    }

    return E_FAIL;
}

//
//  Get a special medium from this pin.
//  If there is not one, return GUID_NULL.
//  Returns the first one it finds special
//

⌨️ 快捷键说明

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