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

简介: (DirectX系列09)DirectShow EDS应用编码分析 DES (DirectShow Editing Services),是一套基于DirectShow核心框架的编程接口。

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 );

 

 

目录
相关文章
|
数据处理 C++
(DirectX系列08)DirectShow WavDest编码分析
     在DirectShow 中有很多Samples,WavDest就是其中一个,这个Fliter主要用于将采集到的视频流写入到指定的文件,文件格式是.WAV。
1068 0
(DirectX系列07)DirectShow MFC下Filter编码分析
    MFC下Filter的编写和Win32下Filter的编写极其相似,但又存在很多不同点,在Win32中需要去实现CreateInstance函数,而在MFC直接用NEW 动态产生,不过这并不代表不需要去维护Filter对象计数,因此在MFC ...
793 0
|
网络架构 开发者 数据格式
(DirectX系列06)DirectShow 字符叠加Filter编码分析
(DirectX系列06)DirectShow 字符叠加Filter编码分析 在很多视频播放的软件当中,字幕的处理是免不了的,有些可能本身已经加载到图像当中未做处理,但大部分都是通过字符叠加来进行处理的。
982 0
|
存储 缓存 安全
为什么你的Opus编码出来的数据有杂音(解决Android平台架构问题)
Gradle插件分为脚本插件和对象插件,脚本插件就是在普通的gradle中写一系列task,然后在别的gradle构建脚本中通过 apply from: 'xx.gradle' 引用这个脚本插件,下面主要介绍一下对象插件对象插件是指实现了org.gradle.api.Plugin接口的类。并且需要实现void apply(T target)这个方法,该方法中的泛型指的是此Plugin可以应用到的对象,而我们通常是将其应用到Project对象上。 编写对象插件常见创建方式
572 0
|
API Windows
(DirectX系列02)DirectSound 录音编码实现
      前面已经发布了一篇音频特效播放相关的文章,今天开始学习DirectSound录音编码实现,这是DirectSound中另一个重要的地方。学会之后受益无穷啊!不过DirectSound设备录音编码其实不难,只要是调用Windows API按照一定的顺序和方法都不难。
989 0
WINCE声音驱动模型概述(2)--WINCE WAVE接口模型详解
WINCE WAVE接口模型详解 1、标准的WAVE流式驱动程序接口 WAVE的驱动程序提供标准的流式接口给高层,但真正产生关键作用的是 WAV_IOControl这个函数。
868 0
|
编解码 API Windows
(DirectX系列05)DirectShow 视频采集
    前几小节陆续介绍了Directsound、Directshow音频处理方面的技术,还没有介绍视频方面的技术,从这节开始介绍视频采集方面的技术。今日刚好就介绍Directshow视频采集技术,其实DirectShow视频采集并不复杂,复杂的部分微软已经帮做好了,只需按照顺序将API连接起来即可,如下所叙述; 系统设备枚举     系统设备枚举器为我们按类型枚举已注册在系统中的Fitler提供了统一的方法。
1153 0
借助DirectX 9 播放AVI文件
首先在winfrom工程里引入 using Microsoft.DirectX.AudioVideoPlayback; 再申明一个:  Video _video; 然后添加如下代码(省去其他控件申明) void OpenVideo() 2        .
857 0
|
编解码 C语言
Mac下使用XLD转换无损音乐Ape
最近想要给音乐库增加一些音乐,下载了一些Ape格式的无损音乐,但是无法直接导入到iTunes中,必须经过其他工具转换成苹果的无损格式,XLD就是这样一款工具。XLD的下载和安装非常方便,直接将APP拖入到/Application文件夹下就可以。
1716 0

热门文章

最新文章