Sample Description Atoms保存了解码Samples时的有用信息。保存在sample description varies中的媒体数据依赖于媒体类型,比如VIdeo Media、Sound Media、Timecode Media、3D Media等等。Sample Description Atoms的布局如图1所示。
图1 Sample Description Atoms的布局
从图中可以看出,Sample Description Atoms包含了一个关于sample description的table,sample description的个数由Number of entries指定。
Sample Description的结构如下所示:
Sample description size:4个字节,指定该Sample Description的字节数;
Data format:4个字节,指定保存的数据格式;
Reserved:6个字节,设置为0;
Data reference index:2个字节。
这也可以看成是一个atom,Sample description size表示atom的大小,Data format表示atom的类型,比如“XVID”、“avc1”、“DIVX”等等,好多。其他数据都是该atom的内容,当然还可能包含其他的atoms。
虽然对于不同的媒体类型,Sample description是不一样的,变化的,但是这16个字节,对于所有的媒体类型都是一样的。在这16个字节的后面,还有一些额外的数据,这些数据会根据不同的媒体类型和数据格式的不同而不同。这里,我们主要介绍一下Sound Media类型的Sample Description。
Sound Sample Descriptions包含了用于解释audio数据的信息,支持的格式非常的多,可以参考qtff的spec。目前Sound Sample Descriptions有三种version,分别为version 0、version 1和version 2。
1、Sound Sample Descriptions of Version 0
Version 0仅仅支持非压缩的raw数据或者twos-complement格式,对应的fourcc分别为“raw ”和“twos”。Version 0的格式如下所示:
Version:2个字节。
Revision level:2个字节,设置为0。
Vendor:4个字节,设置为0。
Number of channels:2个字节,标识channel数量,monaural sounds设置为1,stereo sounds设置为2,不支持更高的channel数量。
Sample size:2个字节,标识非压缩的sample的比特数,允许的值为8或16。需要注意的是,如果sample的比特数超过16,那么该变量设置为16,而且使用version 1。
Compression ID:2个字节,对于version 0,该变量设置为0。对于一些version 2,该变量的值为-2,当为-2是,就需要考虑重新定义Sample Table了。
Packet size:2个字节,设置为0.
Sample rate:4个字节的无符号定点值(16.16),标识了sample的比特率。这个数值的整数部分应该匹配time scale。
2、Sound Sample Descriptions of Version 1
Version 1是在QuickTime 3中引进的,在version 0的基础上扩展出了4个fields,每个field占四个字节,也就是总共16个字节。
在介绍这四个fields之前先说一下两个名词:packet和frame。
packet:对于非压缩audio,一个packet是一个来自于单个channel的sample;对于压缩audio,没什么意义,通常情况下被看作为1/number-of-channels。
frame:对于非压缩audio,一个frame是一个来自于每个channel的sample;对于压缩audio,一个frame是一组压缩的samples。
介绍完packet和frame了,下面该介绍一下这四个fields了。对于压缩的audio和非压缩的audio,这些fields都有不同的含义,而且这些含义不是field的名字就能简单的推论出来的。
(1)Samples per packet:通过压缩的frame产生的非压缩的frame的个数(一个非压缩frame是一个来自于每个channel的sample)。这个值也是frame的duration,通过媒体的timescale来表达,而且timescale等价于sample rate。对于非压缩的audio,这个值设置为1。
(2)Bytes per packet:对于非压缩的audio,这个值标识了一个sample的字节数。这个值替代了之前的sampleSize的值,将被设置为16。这个值可以通过frameSize / channelNum来获得。对于压缩的audio,可以用同样的方式来计算,但是没什么意义。
(3)Bytes per frame:对于非压缩的audio,是一个非压缩的frame的字节数;对于压缩的audio,是一个压缩的frame的字节数。该值可以通过Bytes per packet * channelNum来获得。
(4)Bytes per sample:非压缩sample的字节数。对于8比特的audio,该值设置为1,对于其他的所有情况,该值设置为2,即使sample size的值大于2个字节。
3、Sound Sample Description of Version 2
Version 2是QuickTime 7引进的一个新的version。
4、Redefined Sample Tables
最后,我们说一下这个Redefined Sample Tables。在version 1的情况下,如果compression ID设置为-2,那就说明需要使用Redefined Sample Tables,对压缩audio的一些优化。
不像video media,之前的QuickTime sound media的数据结构是为非压缩的sample设计的。而扩展的version 1则提供了很多对压缩audio的支持,但是并不直接处理sample table atoms。普通的Sample Tables并不指向压缩的frames,也就是压缩媒体数据的基本单元。而是指向非压缩的samples,一个sample只有一个字节。因此,通过使用之前的Sample Table来解析samples,显然是比较复杂的。
QuickTime 4.1引进了对VBR audio的支持,一些field 的内容被重新定义了,因此,一个压缩的audio frame可以看成是一个单独的sample。sample-to-chunk和chunk offset atoms指向压缩的frames,sample size table记载了frame的大小。这个大小,对于CBR来说是定值,对于VBR则是可变的。
time-to-sample table记载了frames的duration。如果time scale设置为sampling rate,那么frame的duration等价于frame中非压缩的sample的个数,这通常是一个定值,即使是VBR的audio。如果使用了一个不同的timescale,那么就有必要将timescale单元转化成sampling rate单元,以此来计算sample的个数。
Sample Tables意义的改变,可以让开发者利用这些tables来精确的定位压缩的frames。为了标明是使用Sample Tables的这些含义,通常将version设置为1,也就是使用Sound Sample Descriptions of Version 1,并将compression ID设置为-2。samplesPerPacket 和 bytesPerSample对于VBR的audio,不一定有意义,但是也应该被正确的设置。bytesPerPacket和bytesPerFrame被保留的且设置为0。
如果compression ID设置为0,Sample Tables则被用来描述非压缩的samples,不能直接用来查找和操作压缩的frames。但是QuickTime提供一些支持,可以让程序员感觉到,这些sample tables是指向了非压缩的samples,每个sample只有一个字节。
以上这些介绍可能比较乏味,可以分析一些相关的代码,比如FFmpeg、Android的Stagefrihgt等等。
为了研究QuickTime文件格式,最近就实现了一个解析MOV文件格式的工具,但这也仅仅只是为了研究,不过这样可以达到更深刻学习的目的,比研究spec、分析代码效果要好好多。