为了说明简单,下面统称OGG。
1、OGG/OGV文件结构
首先介绍一下几个相关的概念:
(1)Packet:Packet一个解码单元,或者是一帧数据。
(2)Segment:Segment是由Packet分割而成,一个Segment最多只包含255格式bytes。Segment没有Header。
(3)Page:Page是OGG/OGV文件格式的基本组成单元,是对Segment的封装。给一个或者几个连续的Segments添加一个Page Header就构成了一个Page。
下面看一下OGG/OGV的文件格式,如下图所示:
OGG/OGV文件就是由一个个的Page组成的。在解析的时候,通过Page的Header标记(“OggS”)将Page解析出来。下面看一些Page的Header结构,如下图所示。
(1)需要详细说明一下Header Type这个field。这个变量用来标识一个Page的类型。可以设置3种数值。
0x01:设置,说明该page和前面的一个page属于同一个packet;如果不设置,说明该page属于一个新的packet。
0x02:设置,说明该page是该stream的第一个page,如果不设置,说明不是。
0x04:设置,说明该page是该stream的最后一个page,如果不设置,说明不是。
(2)一个Page Header占用的字节数是不固定的,主要是因为Segment Table的长度不固定。因此,Page Header占用的字节数为:27 + Seg Numbers。
(3)Granule Position的值如果为-1,说明,该page不是当前packet的最后一个page。
OGG/OGV的封装格式比较简单。不过到这里,会有一个疑问,解码的时候是以packet为单位的,那么解析出pages之后,该如何获得packets呢?了解了OGG/OGV文件格式的封装过程之后,这个问题就比较简单了。
2、OGG/OGV文件封装过程
OGG/OGV文件格式的封装主要分为四个过程:
第一、从编码器获得Packets;
第二:将Packets分割成Segments;
第三:将Segments打包成Pages;
第四:将不同stream的pages组合在一起从而获得OGG/OGV文件。对于只含有一个stream的文件,这个过程可以没有。
封装过程如下图所示。
Packets分割成Segments之后,由于Segment的最大长度只能为255,而且一个Segment不能包含两个Packet中的数据,因此,如果某个Segment的长度小于255,这个Segment就是Packet的最后一个Segment。有一种特殊的情况,那就是Segment的长度为0。如果一个Packet的长度正好是255的整数倍,那么就会用一个长度为0的Segment作为与下一个Packet的分界。以图中的seg_5为例,它是packet_1和packet_2的分界,它的长度必须小于255,包括0。
图中只是给出了一个比较简单的情况。在真正深入到OGG/OGV文件中去之后才发现,Packets和Pages的关系还是比较复杂的。图中的情况是一个Packet包含在一个或者多个Pages中,而一个Page只涉及到一个Packet的数据。实际的情况是,一个Page可能涉及到多个Packets的数据,而且还有可能不是整个Packet的数据。举个例子,还是上图中的Packets和Segments,只是Pages重新打包。例如:
page_1:packet_1的seg_1、seg_2、seg_3、seg_4
page_2:packet_1的seg_5和packet_2的seg_1
page_3:packet_2的seg_2、seg_3和packet_3的seg_1、seg_2
因此,在解析OGG/OGV文件的时候,就需要做相应的处理。
3、OGG/OGV文件Header信息
OGG/OGV文件是由Pages组成的,因此,与文件、stream有关的信息,也是保存在Pages中的,这些Pages一般放在文件的开始位置。那么,如何判断Pages中放的Header信息呢?这个其实比较简单,可以通过Page的Header之后的几个字节来判断。这几个字节不仅可以判断Page中的数据是否为Header信息,还可以判断Header信息的类型。这几个字节是以ASCII的形式存在的,比如:“\001virbis、“\200theora”、“fishead”等等。OGG/OGV文件包含的Header的信息类型比较多,关于各个Header的类型、结构、解析方法等,可以去参考一下ffmpeg。
对于只包含vorbis音频格式的OGG文件,包含的Header一般比较少。而在OGV文件中,就比较多了。