Ogg
文件格式封装好压缩编码
媒体流可用于存储(
磁盘文件)或直接传输(TCP或管道),这是因为Ogg比特流格式提供了封装/同步、差错同步
捕获、寻找
标记以及其它足够的
信息使得这种分散开的数据能够完全地还原为封装之前的具有包边界“packet”形式的压缩编码媒体流,恢复到这种原来媒体流就具有的包边界形式不需要依赖于针对压缩编码的解码器。也就是说Ogg
映射与逆映射和媒体流的压缩编码、解码具有相对独立性。
映射到Ogg格式的媒体(如vorbis
音频,Theora
视频)有相关详细定义,这些定义使得这些媒体之间有更具体的约束关系。Ogg本身并没详细说明多个并发媒体流之间的时间关系,这需要并发媒体流在映射到Ogg格式的时刻来指定,通常他们之间的交错关系是按他们产生的时间先后顺序来排列。
封装
Ogg
文件需要解封装的情况有两种:(1)
播放器要对媒体流解码之前;(2)对媒体流进行RTP/UDP传输之前。解封装的过程就是ogg逆映射过程,即还原为具有包边界“packet”形式的媒体流,同时以预先填充好了的RTP首部字段与相应一段媒体数据捆绑,形成RTP
封包。此过程便是媒体流从Ogg格式到RTP格式的转换过程。
将以packet为单元的媒体流映射为以page为单元的Ogg格式比特流,其中间经过了
segment的划分和重组环节,但方便了对媒体流的存储与传输(TCP)。对源
缓冲区媒体数据(packet)的操作,需建立几个中间环节的数据结构,只需将切割的媒体数据在
内存移动一次,操作指向媒体数据的
指针便能达到媒体
数据迁移到
目的缓冲区(page)的意图,其过程可用两个函数转换来表述。
Ogg 文件结构
:ogg_stream_packetin()àogg_stream_pageout()。将Ogg格式比特流逆映射还原为packets媒体流,以备
播放解码或以RTP封装进行
UDP传输。其中间环节是把page中的segment单元数据按顺序重组为packet,同样媒体数据在内存中的复制只有一次,其过程可用三个
函数转换来表述:ogg_sync_pageout()àogg_stream_pagein()àogg_stream_packetout(),媒体数据复制发生在第一个函数ogg_sync_pageout()。Ogg
映射与
逆映射的功能都体现在ogg函数库中。
Ogg格式是在吸收其它
流媒体文件格式优点的基础上针对具有“packet”包边界形式的媒体流而制定的利于其存储和传输的开源流媒体文件格式,在icecast流
服务器的传输中得到了很好的应用;根据icecast官方
网站公布其测试结果,在GB
主干网的条件下对Oggvorbis
音频传输的
客户端并发流可达14000个。
OGG
文件每个页之间相互独立,都包含了各自应有的
信息,页的大小是可变的,通常为4K-8KB,最大值不能超过65307bytes(27+255+255*255=65307)。
模式捕获域
capture_pattern:模式捕获域,4个字节,表示页的开始,其作用是分离Ogg封装格式还原媒体编码时识别新页的作用,它包含了四个幻数(
ASCII字符集):
0x4f'O'0x67'g'0x67'g'0x53'S'
stream_structure_version:1个字节,表示当前Ogg
文件格式的
版本,为0。
header_type_flag:头部类型
标识,1个字节。标识当前页具体类型。其设置分三种情况:
bit0x01若已设置,页包含的媒体编码数据于前一页同属于一个逻辑流的同一packet。若未设置,本页是一个新的packet。
bit0x02设置,表示逻辑流的第一个页
bos。未设,不是第一个页。
bit0x04设置,表示逻辑流的最后一页eos。未设,不是最后一页。
granule_position:8个字节(字节6-字节13),包含了媒体编码相关参数
信息。对于
音频流,包含了到页为止逻辑流在PCM中采样编码的总次数。对于
视频流,包含了逻辑流到本页为止视频
帧编码的总次数。其值若为-1,则说明到此页为止,逻辑流的packet还未结束。
bitstream_serial_number:流序列号,4字节,表示本页所属逻辑流与其他逻辑流相区别的序号。
page_sequence_number:表明了本页在逻辑流中的序列号,Ogg解码器能据此识别有无页丢失。
CRC_checksum:循环冗余
校验码校验和,4字节域,包含页的32bitCRC校验和(包括页头部零CRC校验和页
数据校验),它的产生多项式为:0x04c11db7。
number_page_segments:1字节,给定了在本页的segment_tabale域中所出现的segement个数,其最大值为255segments(每片255个字节),即页头部第26个字节的取值范围为:0x00-0xff(0-255)。页最大物理尺寸为65307bytes,小于64KB。
segment_table:逻辑流中的每个packet每个segment
长度的取值(lacingvalues,除了每个packet的最后一个segment小于255外,其它segment都为255),这些值以segment出现的先后顺序依次排列。此域的
字节数为number_page_segments域所表示的数字(即在0-255之间)。
bytevalue
270xff(255)
[.................]
n-10xff(255)
n0x00-0xfe(0-254,n=num_segments+26)
页头部长度的字节数:
header_size=27+number_page_segments[Byte]
即页头部长度为上述9个域名所表述占据的字节数之和。
页的总长度:
page_size=header_size+sum(lacing_values:1...number_page_segments)[Byte]
即页的总长度为页头部长度加上紧随其后的若干segments长度之和(净载荷长度)。
Ogg封装处理过程
文件结构在音视频编码在提供给Ogg封装之前是以具有包边界的“Packets”形式呈现的,包边界依赖于具体的编码格式将逻辑流的各个包进行分片segmentation,每片大小固定为255Byte,但包的最后一个
segment通常小于255字节。因为packet的大小可以是任意长度,由具体的媒体
编码器来决定。
进行页封装,每页都被加上页头,每页的长度可不等,由具体情况而确定。页头部segment_table域告知了“lacing_value”值的大小,即页中最后一个segment的长度(可以为0,或小于255)。一次处理一个packet,此packet被封装成一个或多个page页(page的长度设定了上限,一般为4kB);下一个packet必须用新的page开始封装,由首部字段域header_type_flag的设置规定来表示。