(DirectX系列09)DirectShow EDS应用编码分析

DirectX系列09DirectShow EDS应用编码分析

DES (DirectShow Editing Services),是一套基于DirectShow核心框架的编程接口。DES的出现,简化了视频编辑任务,弥补了DirectShow对于媒体文件非线性编辑支持的先天性不足。但是,就技术本身而言,DES并没有超越DirectShow Filter架构,而只是DirectShow Filter的一种增强应用。

本章通过DirectX timelinetest为例子详细介绍Eds应用编码实现,其中主要包括创建事件线对象、在轨道上加入音频过度、在轨道上加入视频过度、使用控制引擎等。

创建事件线对象

这是在所有操作之前必须要做的事情,同样也贯穿这个编码过程,如下代码;

hr = CoCreateInstance(

                         CLSID_AMTimeline,

                         NULL,

                         CLSCTX_INPROC_SERVER,

                         IID_IAMTimeline,

                         (void**) &pTimeline

                         );

    if(FAILED( hr )) {

        Err(_T("Could not create timeline"));

        return hr;

    }

创建组,并标记为音频组或视频组

   DirectShow 通过CreateEmptyNode来创建EDS组,并采用SetMediaType函数来标识音视频组,设置为MEDIATYPE_Video标识为视频组,设置为MEDIATYPE_Audio为音频组,如下代码;

    // 创建视频组

hr = pTimeline->CreateEmptyNode( &pVideoGroupObj, TIMELINE_MAJOR_TYPE_GROUP );

    CComQIPtr< IAMTimelineGroup, &IID_IAMTimelineGroup > pVideoGroup( pVideoGroupObj );

    CMediaType VideoGroupType;

    // all we set is the major type. The group will automatically use other defaults

    VideoGroupType.SetType( &MEDIATYPE_Video );

hr = pVideoGroup->SetMediaType( &VideoGroupType );

// 创建音频组

hr = pTimeline->CreateEmptyNode( &pAudioGroupObj, TIMELINE_MAJOR_TYPE_GROUP );

    CComQIPtr< IAMTimelineGroup, &IID_IAMTimelineGroup > pAudioGroup( pAudioGroupObj );

    CMediaType AudioGroupType;

    // all we set is the major type. The group will automatically use other defaults

    AudioGroupType.SetType( &MEDIATYPE_Audio );

hr = pAudioGroup->SetMediaType( &AudioGroupType );

在轨道上加入视频过渡处理,并实现过渡子对象的设置

    CComPtr< IAMTimelineObj > pTrack2Obj;

    hr = pTimeline->CreateEmptyNode( &pTrack2Obj, TIMELINE_MAJOR_TYPE_TRACK );

    if(FAILED( hr ))

    {

        Err(_T("Could not create second track"));

        return hr;

    }

    hr = pRootComp->VTrackInsBefore( pTrack2Obj, -1 );

    if(FAILED( hr ))

    {

        Err(_T("Could not insert second track"));

        return hr;

    }

    TLStart = 0 * UNITS;

    TLStop = 8 * UNITS;

    MediaStart = 0 * UNITS;

    MediaStop = 8 * UNITS;

    (void)StringCchCopyW( pClipname, NUMELMS(pClipname), T2W( tBasePath ) );

    (void)StringCchCatW( pClipname, NUMELMS(pClipname), L"///0" );

    (void)StringCchCatW( pClipname, NUMELMS(pClipname),wszVideo2Name );

    // create the timeline source

    //

    CComPtr<IAMTimelineObj> pSource2Obj;

    hr = pTimeline->CreateEmptyNode( &pSource2Obj, TIMELINE_MAJOR_TYPE_SOURCE );

    if(FAILED( hr ))

    {

        Err(_T("Could not create the second timeline source"));

        return hr;

    }

    // set up source right

    //

    hr = pSource2Obj->SetStartStop( TLStart, TLStop );

    CComQIPtr< IAMTimelineSrc, &IID_IAMTimelineSrc > pSource2Src( pSource2Obj );

    hr |= pSource2Src->SetMediaTimes( MediaStart, MediaStop );

    hr |= pSource2Src->SetMediaName( pClipname );

    if(FAILED( hr ))

    {

        Err(_T("Could not configure second media source"));

        return E_FAIL;

    }

    //--------------------------------------------

    // tell the track about the source

    //--------------------------------------------

    CComQIPtr< IAMTimelineTrack, &IID_IAMTimelineTrack > pTrack2( pTrack2Obj );

    hr = pTrack2->SrcAdd( pSource2Obj );

    if(FAILED( hr ))

    {

        Err(_T("Could not add second track"));

        return hr;

    }

    CComQIPtr< IAMTimelineTransable, &IID_IAMTimelineTransable > pTransable( pTrack2 );

#ifdef DO_TRANSITION

    REFERENCE_TIME TransStart = 0 * UNITS;

    REFERENCE_TIME TransStop = 4 * UNITS;

    // create the timeline effect

    //

    CComPtr<IAMTimelineObj> pTrackTransObj;

    hr = pTimeline->CreateEmptyNode(&pTrackTransObj,

                                    TIMELINE_MAJOR_TYPE_TRANSITION );

    if(FAILED( hr ))

    {

        Err(_T("Could not create transition effect"));

        return hr;

    }

    //--------------------------------------------

    // set up filter right

    //--------------------------------------------

    // we set the CLSID of the DXT to use instead of a pointer to the

    // actual object. We let the DXT have it's default properties.

    //

    hr = pTrackTransObj->SetSubObjectGUID( CLSID_DxtJpeg );

    hr |= pTrackTransObj->SetStartStop( TransStart, TransStop );

    CComQIPtr< IAMTimelineTrans, &IID_IAMTimelineTrans > pTrackTrans( pTrackTransObj );

    hr |= pTransable->TransAdd( pTrackTransObj );

    if(FAILED( hr ))

    {

        Err(_T("Could not configure transition object"));

        return E_FAIL;

    }

#ifdef CUTS_ONLY

    //---------------------------------------------

    // turn the transition into a cut by doing this

    //---------------------------------------------

    hr = pTrackTrans->SetCutsOnly( TRUE );

    if(FAILED( hr ))

    {

        Err(_T("Could not SetCutsOnly to TRUE"));

        return hr;

    }

#endif  // CUTS_ONLY

    //---------------------------------------------

    // create an transition on the track from B 2 A

    //---------------------------------------------

    TransStart = 4 * UNITS;

    TransStop = 8 * UNITS;

    // create the timeline effect

    //

    pTrackTransObj.Release( );

    hr = pTimeline->CreateEmptyNode(&pTrackTransObj,

                                    TIMELINE_MAJOR_TYPE_TRANSITION );

    ASSERT( !FAILED( hr ) );

    // set up filter right

    //

    hr = pTrackTransObj->SetSubObjectGUID( CLSID_DxtJpeg );           

    hr |= pTrackTransObj->SetStartStop( TransStart, TransStop );

    pTrackTrans = pTrackTransObj;

    hr |= pTrackTrans->SetSwapInputs( TRUE );

    hr |= pTransable->TransAdd( pTrackTransObj );

ASSERT( !FAILED( hr ) );

在轨道中加入声音效果

    CComPtr< IAMTimelineObj > pTrack4FxObj;

    hr = pTimeline->CreateEmptyNode( &pTrack4FxObj, TIMELINE_MAJOR_TYPE_EFFECT );

    ASSERT( !FAILED( hr ) );

 

    // set up effect riht

    //

    hr = pTrack4FxObj->SetStartStop( TLStart, TLStop );

    hr |= pTrack4FxObj->SetSubObjectGUID( CLSID_AudMixer );

    ASSERT( !FAILED( hr ) );

 

    // add the effect

    //

    CComQIPtr< IAMTimelineEffectable , &IID_IAMTimelineEffectable > pTrack4Fable( pTrack4 );

    hr = pTrack4Fable->EffectInsBefore( pTrack4FxObj, -1 );

ASSERT( !FAILED( hr ) );

控制引擎的使用

hr = CoCreateInstance(

                         CLSID_RenderEngine,

                         NULL,

                         CLSCTX_INPROC_SERVER,

                         IID_IRenderEngine,

                         (void**) &pRenderEngine );

    ASSERT( !FAILED( hr ) );

 

    // tell the render engine about the timeline it should look at

    //

    hr = pRenderEngine->SetTimelineObject( pTimeline );

    ASSERT( !FAILED( hr ) );

 

    //--------------------------------------------

    // connect up the front end, then the back end

    //--------------------------------------------

 

    hr = pRenderEngine->ConnectFrontEnd( );

    hr |= pRenderEngine->RenderOutputPins( );

    ASSERT( !FAILED( hr ) );

 

    //--------------------------------------------

    // get a bunch of pointers, then run the graph

    //--------------------------------------------

 

    hr = pRenderEngine->GetFilterGraph( &pGraph );

    hr |= pGraph->QueryInterface( IID_IMediaEvent, (void**) &pEvent );

    hr |= pGraph->QueryInterface( IID_IMediaControl, (void**) &pControl );

    hr |= pGraph->QueryInterface( IID_IMediaSeeking, (void**) &pSeeking );

    hr |= pGraph->QueryInterface( IID_IVideoWindow, (void**) &pVidWindow );

    ASSERT( !FAILED( hr ) );

 

    //--------------------------------------------

    // give the main window a meaningful title

    //--------------------------------------------

 

    BSTR bstrCaption;

    WriteBSTR(&bstrCaption, wszTitle);

 

    hr = pVidWindow->put_Caption(bstrCaption);

    FreeBSTR(&bstrCaption);

 

    //--------------------------------------------

    // since no user interaction is allowed, remove

    // system menu and maximize/minimize buttons

    //--------------------------------------------

    long lStyle=0;

    hr = pVidWindow->get_WindowStyle(&lStyle);

 

    lStyle &= ~(WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU);

    hr = pVidWindow->put_WindowStyle(lStyle);

 

    //--------------------------------------------

    // run it

    //--------------------------------------------

 

    hr = pControl->Run( );

    ASSERT( !FAILED( hr ) );

 

    //--------------------------------------------

    // wait for it

    //--------------------------------------------

 

    long EventCode = 0;

    hr = pEvent->WaitForCompletion( -1, &EventCode );

    ASSERT( !FAILED( hr ) );

 

    REFERENCE_TIME Start = 0;

 

#ifdef DO_RENDERRANGE

 

    // seek the timeline back to 0

    //

    hr = pSeeking->SetPositions( &Start, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning );

    ASSERT( !FAILED( hr ) );

 

    hr = pRenderEngine->SetRenderRange2( 2.0, 6.0 );

    ASSERT( !FAILED( hr ) );

 

    //------------------------------------------------------

    // connect up the front end, then the back end if needed

    //------------------------------------------------------

 

    hr = pRenderEngine->ConnectFrontEnd( );

    ASSERT( !FAILED( hr ) );

    if(hr == (HRESULT) S_WARN_OUTPUTRESET) {

        hr |= pRenderEngine->RenderOutputPins( );

    }

    ASSERT( !FAILED( hr ) );

 

    //--------------------------------------------

    // run it

    //--------------------------------------------

 

    hr = pControl->Run( );

    ASSERT( !FAILED( hr ) );

 

    //--------------------------------------------

    // wait for it

    //--------------------------------------------

 

    hr = pEvent->WaitForCompletion( -1, &EventCode );

    ASSERT( !FAILED( hr ) );

#endif  // DO_RENDERRANGE

 

#ifdef DO_RECONNECT

 

    //---------------------------------------------

    // make a change to the timeline, however small

    //---------------------------------------------

 

    CComPtr< IAMTimelineObj > pTransObj;

    REFERENCE_TIME InOut = -1;

 

    pTransable->GetNextTrans( &pTransObj, &InOut );

    CComQIPtr< IAMTimelineTrans, &IID_IAMTimelineTrans > pTrans( pTransObj );

 

    pTrans->SetCutsOnly( TRUE );

    pTransObj.Release( );

    pTrans.Release( );

 

    hr = pTransable->GetNextTrans( &pTransObj, &InOut );

    pTrans = pTransObj;

 

    hr |= pTrans->SetCutsOnly( TRUE );

    ASSERT( !FAILED( hr ) );

 

    // seek the timeline back to 0

    //

    hr = pSeeking->SetPositions( &Start, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning );

    ASSERT( !FAILED( hr ) );

 

    //------------------------------------------------------

    // connect up the front end, then the back end if needed

    //------------------------------------------------------

 

    hr = pRenderEngine->ConnectFrontEnd( );

    if(hr == (HRESULT) S_WARN_OUTPUTRESET) {

        hr |= pRenderEngine->RenderOutputPins( );

    }

    ASSERT( !FAILED( hr ) );

 

    //--------------------------------------------

    // run it

    //--------------------------------------------

 

    hr = pControl->Run( );

    ASSERT( !FAILED( hr ) );

 

    //--------------------------------------------

    // wait for it

    //--------------------------------------------

 

    hr = pEvent->WaitForCompletion( -1, &EventCode );

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值