网页功能: 加入收藏 设为首页 网站搜索  
DirectShow应用——支持DVD播放
发表日期:2007-01-18作者:[转贴] 出处:  

目录:
  
一. DVD基础知识
  
二. DirectShow对DVD的支持
  三. 总结

文档内容:

一. DVD基础知识

  首先,我们来增加一点感性认识,看一下DVD光盘的文件系统(采用MicroUDF标准)。我们可以看到,典型情况下光盘上有两个文件夹:VIDEO_TS和AUDIO_TS(通常是空的,这里不作介绍)。VIDEO_TS下面一般包含三种类型的文件:.VOB文件、.IFO文件和.BUP文件。这些文件都是作什么用的呢?其实,.VOB文件是用来保存所有MPEG2格式的音视频数据的,这些数据包括影片内容、供菜单(Menu)和按钮(Button)以及多种语言字幕用的子图片(Sub-picture)流;.IFO文件则是控制.VOB文件播放用的,这个文件中可以找到有关何时以及如何播放.VOB文件数据的控制信息;而.BUP文件则是.IFO文件内容的一个备份(因为.IFO文件对于保证DVD光盘的正确播放起着至关重要的作用)。根据这三种文件的特性,我们也就可以理解它们在光盘介质上的排列顺序了:IFO-VOB-VOB...-BUP。

  我们再来看一下各个具体的文件。VIDEO_TS.IFO文件,保存DVD光盘的视频管理器 (Video Manager,简称VMG)信息,主要是光盘的一些全局信息,比如光盘指定的播放区域、如何显示菜单等。VIDEO_TS.VOB文件,保存显示菜单的数据。类似VTS_xx_y.VOB的文件,保存各个视频节目。(注:这里"xx"是节目编号,从01到99,"y"是从0到9的编号;由于MicroUDF文件系统中一个文件最大只能1 GB,因此大多数影片不得不保存在多个VOB文件中。)VTS_xx_y.IFO文件,保存对应编号的VOB文件的音视频格式信息。

  大致了解了文件系统,我们再来看一下DVD其他方面的基础知识。大家知道,一张DVD光盘主要包括三种媒体数据:视频(Video)、音频(Audio)和子图片。视频一般采用MPEG2压缩算法,视频流支持最多9个视角(Angle),支持Line 21 Closed Caption(模拟电视中的概念,主要是些文字信息);音频最多支持8条不同的流(即8种不同语言的配音),支持最多6声道的声音格式(具体格式可以是AC3、MPEG、LPCM、DTS、SDDS等),支持卡拉OK;子图片流最多可以支持32个(即提供多种语言的字幕)。DVD内容最主要的逻辑分类叫做“标题”(Title)(一个标题通常代表了一部电影,或者一段视频节目,一张DVD光盘最多可以有99个标题),每个标题又可以 最多分成999个“章节”(Chapter)(章节是便于用户随机访问的节点,每播放完一个章节的内容会自动播放下一个章节,或者跳回菜单)。

  用户与DVD的交互,最主要是通过菜单来完成的。菜单有两种:视频管理器菜单(Video Manager Menu,简称VMGM,也叫做Top Menu或Title Menu)和视频标题集菜单(Video Title Set Menu,简称VTSM,也叫做Root Menu,尽管它不是真正意义上的“根”菜单)。VMGM允许用户进入主要的标题或者标题集(包含有一组标题)。如果进入标题集,就显示VTSM子菜单。VTSM菜单可以包含进入当前标题集中各个标题的按钮,还有音频、视角、字幕、章节等选择子菜单。VTSM菜单是可选的,可以不实现;当用户开始播放一张DVD,一般首先看到的就是VMGM菜单,除非这张光盘在制作时被设置成了自动播放第一个标题(此时DVD也可以根本不制作VMGM菜单)。

  DVD还有父母锁功能。DVD中的视频内容可以打上父母管理级别(Parental Management Level,简称PML);级别可以从1到8,其中1是无限制级别,8是最高限制级别。这样,可以禁止孩子在未经父母同意的情况下观看成人电影。注意:父母锁功能需要播放器的支持。

  DVD导航(Navigation)还有一个非常重要的抽象概念,就是域(Domain)。通俗地说,也就是DVD在特定播放状态下的操作许可。比如“选择按钮”命令必须在菜单状态下才有效,“快进”命令在停止或者菜单状态下是无效的。播放器必须使用域的概念,阻止用户向DVD驱动器发送无效的命令。下表列出了五个主要的域以及对应的操作说明:

Domain(域)
DVD导航器的工作内容

First Play(开始播放DVD时第一个播放的一段视频内容)
读取光盘上初始部分

Video Manager Menu(显示VMGM菜单时)
读取光盘的主菜单,菜单相关的指令都是有效的

Video Title Set Menu(显示VTSM菜单时)
读取VTSM菜单,或者设置音频、字幕、视角等的子菜单,菜单相关的指令都是有效的

Title(播放标题内容时)
菜单相关的指令都是无效的

Stop(停止时)
导航器不在工作,此时可以执行播放指令


  另外,DVD的制作者还可以利用“用户操作控制”功能(User Operation Controls,简称UOPs)来限制用户的操作。这需要在光盘上记录这些限制记号。比如,大多数光盘都不允许用户在DVD播放处于First Play域时执行快进或者显示菜单命令。


二. 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播放程序会陷入“万事具备,只欠东风”的窘境!
我来说两句】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 DirectShow应用——支持DVD播放
本类热点文章
  DirectShow应用——支持Windows Media格..
  DirectShow PIN 連接教學
  游戏UI设计1
  PSD格式文件的读取
  将RGB值转换为灰度值的简单算法
  貼圖 filtering 與 MIP map 簡介
  读取万能图片以及DShow的另类用法
  TGA图像文件格式资料
  DirectShow初探
  PNG格式
  DirectShow应用——支持DVD播放
  DirectShow的中文资料之建立一个捕捉程序
最新分类信息我要发布 
最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放  
Copyright ©2003-2024 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00378