CD，DVD，VCD -- MPlayer -- Linux下的电影播放器

## 4.1 CD/DVD光驱

Linux文件摘录：

现代的CD-ROM光驱能达到十分高的头速度，还有一些CD-ROM光驱能运行在被正常情况低的速度上。你考虑改变CD-ROM光驱的速度可能有若干原因：

- 在告诉情况下发生读取错误，尤其对于压制不好的CD-ROM。降低速度能防止这种情况下的数据丢失。
- 很多CD-ROM光驱的声音吵的讨厌，低的速度可以降低噪音。

你能使用hdparm或一个叫setcd的程序来降低光驱的速度。它是这样工作的：

`hdparm -E [speed] [cdrom device]`

`setcd -x [speed] [cdrom device]`

你也可以试试

`echo current_speed:4 > /proc/ide/[cdrom device]/settings`

但这样你需要root权限。下面这个命令也有用处：

`echo file_readahead:2000000 > /proc/ide/[cdrom device]/settings`

这把文件预读取设置为2MB，对于刮伤的CD-ROM有好处。如果你把这个值设置的太大，你的光驱会不停的转， 显著的降低效率。建议你同时也用hdparm调整你的CD-ROM光驱：

`hdparm -d1 -a8 -u1 (cdrom device)`

这开启DMA存取，预读取，和IRQ unmasking(细节解释请阅读hdparm的man page)。

为了优化你的CD-ROM请参考"`/proc/ide/[cdrom device]/settings`"。

SCSI驱动器没有一个统一的设置参数的方法(你知道这样一种方法？告诉我们！) 有一种工具可以用于Plextor的SCSI驱动器。

FreeBSD:

Speed: `cdcontrol [-f device] speed [speed]`

DMA: `sysctl hw.ata.atapi_dma=1`

## 4.2 DVD播放

可用选项的完整列表参见man page。播放标准的数字多功能碟片(DVD)的语法如下：

`mplayer dvd://<track> [-dvd-device <device>]`

示例：`mplayer dvd://1 -dvd-device /dev/hdc`

默认的DVD设备是`/dev/dvd`。如果你的设置不同，作一个符号链接，或者在命令行中用`-dvd-device`选项 指定一个正确的设备。

#### 新式的DVD支持(mpdvdkit2)

MPlayer使用`libdvdread`和`libdvdcss`进行DVD解密和回放。这两个库包含在MPlayer源码树的`libmpdvdkit/` 子目录中，你不需要单独安装他们。我们选择这种解决方案是因为我们必须修正一个libdvdread的bug，并且给libdvdcss添加一个cracked CSS keys caching support的补丁。 这带来极大的速度提升，因为不用在每次播放之前都破解密钥。

MPlayer也能使用系统的`libdvdread`和`libdvdcss`库，但这种解决方法不推荐，因为它会导致bug，库的不兼容，并且降低速度。

#### DVD导航菜单支持(dvdnav)

通过`dvdnav`支持DVD导航菜单的工作已经开始，但它可能永远不会完成而且现在无人维护。谁知道，它可能还能编译过去。

#### 老式DVD支持 -- 可选

如果你想从硬盘上播放编码的VOB是有用。为此要编译并安装libcss0.0.1(不要更新的)(如果MPlayer检测不到它，使用`-csslib /path/to/libcss.so`选项)。为了使用它你必须是root，使用一个suid root了的MPlayer二进制程序或者让MPlayer调用suid-root了的fibmap_mplayer外壳程序。

#### DVD结构

DVD盘每个扇区有2048字节附带ECC/CRC。它们经常在一个音轨上使用一个UDF文件结构，包含各种文件(小的.IFO和.BUK文件和大的 (1GB) .VOB文件)。它们是真正的文件，可以在一个mount了的未加密的DVD的文件系统上被复制/播放。

.IFO文件包含电影的导航信息(chapter/title/angle map, 语言表等等)需要它来读取和解释.VOB文件的内容(电影)。.BUK文件是它们的备份。 它们到处使用扇区，所以你需要使用碟片上扇区的未经处理的地址类实现DVD导航菜单和内容解密。

整个的老式DVD支持使用`libcss`所以需要一个mount了的DVD文件系统和直接的基于扇区的设备访问。不幸的是(在Linux下)你必须 是root才能得到一个文件的扇区地址。你有以下几种选择：

- 成为root或者使用一个suid-root的mplayer二进制程序。
- 让MPlayer调用suid-root的fibmap_mplayer外壳程序来访问DVD(使用通过`libcss`的老式DVD播放方式)。
- 根本不使用内核的文件系统驱动而是在用户空间重新实现它。`libdvdread` 0.9.x和`libmpdvdkit` 就是这么做的(新式DVD支持)。内核的UDF文件系统驱动是不需要的因为它们有自己内建的UDF文件系统驱动。同样DVD不需要mount 因为只需要使用直接的基于扇区的访问。

有时`/dev/dvd`用户不能读取，所以`libdvdread`的作者设计了一个模拟层把扇区地址变换为文件名 +偏移量，用来在一个mount了的文件系统甚至硬盘上模拟直接访问。

`libdvdread`甚至可以通过mountpoint而不是设备名，通过访问`/proc/mounts`查找设备名来进行直接访问， 这是为Solaris设计的，那里设备名是动态分配的。

默认的DVD设备是`/dev/dvd`。如果你的设置不同，作一个符号链接，或者在命令行中用`-dvd-device`选项 指定一个正确的设备。

#### DVD认证

新式DVD支持的认证和解密的方法是通过一个打了补丁的`libdvdcss`(见上面)来完成的。可以通过指定环境 变量`DVDCSS_METHOD`来设置解密方法，可以设置的值为`key`, `disk`或者`title`。

如果什么都没有指定它将会尝试下列方法(默认: key, title request)：

1. bus key: 这个密钥在认证(一长串的ioctls和各种密钥的交换，加密的东西的混合)的过程中确定，然后在通过没有保护的 总线之前用它加密title和disk keys(防止窃听)。需要bus key来获得加密的disk key并对其进行预解密.
2. cached key: MPlayer寻找已经破解的title keys，存放在`~/.mplayer/DVDKeys`目录下(很快;).
3. key: 如果没有可用的cached key，MPlayer尝试使用播放器密钥来对disk key进行解密。
4. disk: 如果密钥方法失败(比如：没有自带的播放器密钥)，MPlayer将会使用一种暴力算法来破解disk key。 这个过程非常消耗CPU而且需要64 MB内存(16M的32Bit的整个hash表)来存储临时数据。这种方法总能起作用(很慢)。
5. title request: 有了disk key以后MPlayer需要加密的title keys，它被用`ioctl()`储存在隐藏扇区里。 RPC-2驱动器的地区保护在这一步实现，所以在这样的驱动器上可能会失败。如果成功的话，将使用bus和disk key对title keys进行解密。
6. title: 这个方法在title request方法失败时使用，不依赖于与DVD驱动器的任何密钥交换。它使用一种加密破解的方法 直接猜测title key(通过寻找已解密的VOB内容中的一种重复格式然后猜测加密部分的前几个字节是这种格式的延续)。 这种方法也被成为"已知明文攻击"或者"DeCSSPlus"。很少的情况下，因为碟片上没有足够的加密数据来进行统计攻击或者因为密钥交换 发生在一个title的中间，这种方法会失败。这种方法是解密一个储存在硬盘上的DVD或者在一个RPC2驱动器上读取一个地区错误的DVD 的唯一方法(很慢)。

RPC-1 DVD驱动器只保护软件设定的区域。RPC-2驱动器有一个硬件保护，只允许5个改变。如果你有一个RPC-2 DVD驱动器， 可能需要/推荐将固件升级到RPC-1。固件升级可以在这里firmware page找到。 如果没有可用于你的设备的固件升级，使用区域设定工具来设置你的 DVD驱动器的地区(在Linux下)。警告： 你只有5次设置地区的机会。

## 4.3 VCD回放

可用选项的完整列表请阅读man page。播放一个标准的Video CD(VCD)的语法如下：

播放标准的Video CDs：

`mplayer vcd://<track> [-cdrom-device <device>]`

示例：`mplayer vcd://2 -cdrom-device /dev/hdc`

默认的VCD设备是`/dev/cdrom`。如果你的设置不同，作一个符号链接，或者在命令行中用`-cdrom-device`选项 指定一个正确的设备。

注意：至少对于Plextor和一些Toshiba的SCSI CD-ROM驱动器在读取VCD的时候慢的恐怖。这是因为CDROMREADRAW ioctl在这些 驱动器上没有完全实现。如果你有SCSI编程方面的支持，请帮助我们实现普遍的SCSI设备的VCD支持。

此外你还可以使用readvcd提取VCD中的数据，并用 MPlayer播放获得的文件。

#### VCD结构

VCD碟片由一个或多个音轨组成：

- 第一个轨道是一个小的2048字节/扇区的数据轨，有一个iso9660文件系统，通常包含Windows VCD播放程序可能还有其他信息 (图像，文字等等)。
- 第二和之后的轨道是未处理的2324字节/扇区的MPEG(电影)轨，每个扇区包含一个MPEG PS数据包而没有文件系统。音频CD的轨道也类似。 这些轨道是无法被mount的(你曾经mount一个音频CD然后播放过吗？)。大部分电影都在这个轨道，所以你应该先试试 `vcd://2`。
- 有些VCD碟片没有第一个轨道(单轨道而根本没有文件系统)。它们也可以播放，但是不能mount。

#### 关于.DAT文件：

在mount了的VCD的第一轨上看到的~600 MB的文件不是一个真正的文件！这是所谓的ISO通道，用来使Windows能够处理这样的 轨道(Windows根本不允许程序直接访问未处理的设备)。在Linux下你不能复制或者播放这些文件(它们里面是些垃圾)。在Windows下 这是可以的，因为它的iso9660驱动能模拟在这个文件中读取未处理的音轨。要播放一个.DAT文件你需要Linux版的PowerDVD中的 内核驱动。它有一个经过修改的iso9660文件系统(`vcdfs/isofs-2.4.X.o`)驱动，可以通过这个.DAT影子文件模拟 读取未处理音轨。如果你用它们的驱动来mount，你可以复制甚至用mplayer直接播放.DAT文件。但如果用Linux内核的标准的 iso9660驱动是不会有用的！应该使用`-vcd`选项。另一种复制VCD的方法是新的cdfs内核驱动(不是官方内核的一部分)，它能够把CD的sessions 显示成镜像文件，或者cdrdao，一个bit-by-bit的CD抓取/复制程序。