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

 

 

目录
相关文章
|
6月前
|
编解码 5G Linux
FFmpeg开发笔记(二十一)Windows环境给FFmpeg集成AVS3解码器
AVS3是中国首个8K及5G视频编码标准,相比AVS2和HEVC性能提升约30%。解码器libuavs3d支持8K/60P视频实时解码,兼容多种平台。《FFmpeg开发实战》书中介绍了在Windows环境下如何集成libuavs3d到FFmpeg。集成步骤包括下载源码、使用Visual Studio 2022编译、调整配置、安装库文件和头文件,以及重新配置和编译FFmpeg以启用libuavs3d。
104 0
FFmpeg开发笔记(二十一)Windows环境给FFmpeg集成AVS3解码器
|
6月前
|
安全 编译器 C语言
MISRA C++ 、Google C++ 、AUTOSAR Adaptive Platform编码 C++ 规范总结
MISRA C++ 、Google C++ 、AUTOSAR Adaptive Platform编码 C++ 规范总结
197 1
|
存储 缓存 安全
为什么你的Opus编码出来的数据有杂音(解决Android平台架构问题)
Gradle插件分为脚本插件和对象插件,脚本插件就是在普通的gradle中写一系列task,然后在别的gradle构建脚本中通过 apply from: 'xx.gradle' 引用这个脚本插件,下面主要介绍一下对象插件对象插件是指实现了org.gradle.api.Plugin接口的类。并且需要实现void apply(T target)这个方法,该方法中的泛型指的是此Plugin可以应用到的对象,而我们通常是将其应用到Project对象上。 编写对象插件常见创建方式
491 0
|
编译器 开发工具 C语言
QT应用编程:基于VLC开发音视频播放器(句柄方式)
QT应用编程:基于VLC开发音视频播放器(句柄方式)
453 0
QT应用编程:基于VLC开发音视频播放器(句柄方式)
|
编译器 开发工具 C语言
QT应用编程:基于VLC开发音视频播放器(回调方式)
QT应用编程:基于VLC开发音视频播放器(回调方式)
597 0
QT应用编程:基于VLC开发音视频播放器(回调方式)
|
编译器 C语言
QT应用编程: 使用QTAV得到解码视频每帧图像
QT应用编程: 使用QTAV得到解码视频每帧图像
434 0
QT应用编程: 使用QTAV得到解码视频每帧图像
|
Shell C# Windows
Directshow开发的基本技巧
你也可以在graph没有设置时钟的情况下运行graph。当SetSyncSource 函数的参数为NULL的时候就给graph设置了一个空的参考时钟。如果graph没有时钟,graph将运行的快许多。因为renderer 不用再按照sample的presentation 时间了,只要sample到达了renderer filter,就可以立即被提交。
1135 0
|
Web App开发 监控
基于DirectShow和FFmpeg的USB摄像头监控软件-转
第一个版本   ### 软件版本及实现功能 0.0.1 1. USB摄像头枚举和设备信息获取2. 实时视频观看3. 24小时不间断录像,录像文件支持暴风影音播放### 软件说明:软件基于 DirectShow 和 FFMpeg开发### 软件使用说明:1.
1786 0