科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件DirectShow应用——支持DVD播放

DirectShow应用——支持DVD播放

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

DVD光盘的文件系统典型情况下有两个文件夹:VIDEO_TS和AUDIO_TS

作者:陆其明 来源:hqtech 2007年10月20日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
二. DirectShow对DVD的支持

  DirectShow对DVD播放提供了强力的支持。(DirectShow为支持DVD播放作了大量的工作,除了不提供MPEG2 Video Decoder Filter外。换句话说,必须提供第三方的MPEG2 Decoder,否则我们写的播放程序还是跑不起来的!)编写DVD播放程序,我们无须研究DVD的规格说明书;了解上面的这些基础知识就已经足够了。因为微软提供了一个叫DVD Navigator的Filter,帮我们完成了繁琐的DVD导航的任务;提供一个专门用于建立播放DVD的Filter Graph的COM组件(CLSID_DvdGraphBuilder)。我们所要做的,主要就是使用DVD Navigator的两个接口:IDvdInfo2,获得光盘的属性和导航状态;以及IDvdControl2,设置属性和执行播放操作。典型的播放DVD的Filter Graph如下:



  典型的Filter Graph创建过程如下:

// Create an instance of the DVD Graph Builder object.
HRESULT hr;
hr = CoCreateInstance(CLSID_DvdGraphBuilder,
NULL,
CLSCTX_INPROC_SERVER,
IID_IDvdGraphBuilder,
reinterpret_cast<void**>(&m_pIDvdGB));

// Build the DVD filter graph.
AM_DVD_RENDERSTATUS buildStatus;
hr = m_pIDvdGB->RenderDvdVideoVolume(pszwDiscPath, m_dwRenderFlags, &buildStatus);

// Get the pointers to the DVD Navigator interfaces.
hr = m_pIDvdGB->GetDvdInterface(IID_IDvdInfo2, reinterpret_cast<void**>(&m_pIDvdI2));
hr = m_pIDvdGB->GetDvdInterface(IID_IDvdControl2, reinterpret_cast<void**>(&m_pIDvdC2));
...
// Get a pointer to the filter graph manager.
hr = m_pDvdGB->GetFiltergraph(&m_pGraph);
...
// Use the graph pointer to get a pointer to IMediaControl,
// for controlling the filter graph as a whole.
hr = m_pGraph->QueryInterface(IID_IMediaControl, reinterpret_cast<void**>(&m_pIMC));
...
// Get a pointer to IMediaEventEx,
// used for handling DVD and other filter graph events.
hr = m_pGraph->QueryInterface(IID_IMediaEventEx, reinterpret_cast<void**>(&m_pME));
...
// Use the graph builder pointer again to get the IVideoWindow interface,
// to set the window style and message-handling behavior of the video renderer filter.
hr = m_pIDvdGB->GetDvdInterface(IID_IVideoWindow, reinterpret_cast<void**>(&m_pIVW));
hr = m_pDvdGB->GetDvdInterface(IID_IAMLine21Decoder, reinterpret_cast<void**>(&pL21Dec));

  关于IDvdInfo2和IDvdControl2的各个接口方法的详细说明和用法,请参见DirectShow SDK文档,以及SDK提供的例子代码DVDSample。下面,仅就编写DVD播放程序需要注意的地方,进行一些简单的罗列:

  1. 为了得到DVD Navigator在创建时发出的事件,一般在RenderDvdVideoVolume 调用之前获得ImediaEventEx接口。

  2. 菜单命令实际上有两种,一种是选中(Select),一种是激活(Activate)。前者如IDvdControl2::SelectAtPosition,IDvdControl2::SelectButton,IDvdControl2::SelectRelativeButton等,效果是高亮度显示被选中的菜单;后者如IDvdControl2::ActivateAtPosition,IDvdControl2::ActivateButton等,效果是产生相应的动作。也有选中加激活的命令,如IDvdControl2::SelectAndActivateButton。

  3. DVD最多支持8条音频流、32条子图片流,但在同一时刻,都只能各自选中某一条。

  4. DVD Navigator本身并不强调父母锁功能,而只是把光盘上的PML信息发送给应用程序。因此,父母锁功能需要在应用程序上完成。

  5. 通过IDvdInfo2::GetState调用,可以得到IDvdState对象,用以实现“书签”的功能。具体实现参见DVDSample的CDvdCore::SaveBookmark和CDvdCore::RestoreBookmark两个函数。

  6. 注意DVD播放时候的Filter Graph状态,需要同时考虑DVD Navigator的状态。

  7. 支持卡拉OK的DVD,要求Audio Decoder实现AM_KSPROPSETID_DvdKaraoke属性集(即实现IKsPropertySet接口)。

  8. IDvdControl2关于播放的接口方法,一般都有异步和同步两种调用方式。如果是异步方式,调用这些接口方法后,会立即返回,而并不等到实际的操作完成。有时候,这样操作会引起DVD Navigator的状态混乱。对于这些接口方法,微软推荐了有5种调用方法,下面列出常用的3种:

  (1)异步方式(以PlayTitle调用为例,下同)

HRESULT hr = pDVDControl2->PlayTitle( uTitle,
DVD_CMD_FLAG_None, // = 0
NULL);

  (2)阻塞方式

HRESULT hr = pDVDControl2->PlayTitle( uTitle,
EC_DVD_CMD_FLAG_Block,
NULL);

  (3)使用同步对象

IDvdCmd* pObj;
HRESULT hr = pDVDControl2->PlayTitle(uTitle, 0, &pObj);
if(SUCCEEDED(hr))
{
pObj->WaitToEnd();
pObj->Release();
}

  三. 总结

  总之,DirectShow使我们从DVD的专业知识中解放出来;有了DirectShow的支持,编写一个DVD播放程序还是比较轻松的!再次提醒读者朋友们,必须要提供第三方的Video Decoder和Audio Decoder,否则,我们的DVD播放程序会陷入“万事具备,只欠东风”的窘境!

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章