本文系微信公众号和知乎专栏《MediaStack》原创文章,欢迎大家关注,随时进行交流。
上一篇我们针对OGG的发展历程,文件结构和关键点等内容做了说明,还单独介绍了MDCT编码,有兴趣的可以翻阅之前的文章。
本文将以FFMPEG代码为范例进行走读,更加全面和深入学习和掌握OGG
ogg_probe()
该函数的工作原理是首先检查输入流的前 5 个字节是否与 Ogg 签名匹配。如果前 5 个字节与 Ogg 签名匹配,则该函数然后检查输入流的第六个字节是否小于或等于 7。如果第六个字节小于或等于 7,则该函数返回 AVPROBE_SCORE_MAX,这表明 输入流是高质量的Ogg流。
ogg_read_header()
该函数的工作原理是读取 Ogg 流的标头:
  • 首先调用 ogg_packet() 函数来读取流中的第一个数据包。如果数据包不是标头数据包,则该函数会重复该过程,直到找到标头数据包。
  • 一旦找到标头数据包,该函数就会解析标头数据包并将信息存储在流格式上下文中。 然后,该函数对文件中的所有流重复该过程。
  • 该函数还为每个流设置 start_capsule 和 lastpts 字段。 start_capsule 字段是流中第一帧的颗粒位置。 Lastpts 字段是流中最后一帧的呈现时间戳。
  • 最后调用ogg_get_length()函数来获取文件的长度。
ogg_packet()
该函数首先在输入流中查找下一个 Ogg 数据包标头。一旦找到标头,该函数就会读取数据包数据的其余部分并相应地设置输出参数。
libavformat 使用该函数从输入流中读取 Ogg 数据包。还被其他需要读取 Ogg 数据包的应用程序使用,例如媒体播放器和解码器。
ogg_read_page()
该函数读取 Ogg 页面的标题。读取标题后将读取页面数据的其余部分并相应地设置输出参数。
这段代码作用进行初始化校验和,用于验证页面数据的完整性。校验和初始化为值 0x4fa9b05f,是字符串“OggS”的 CRC-32 校验和。接下来依次读取页面的标题,标头包含版本、标志、颗粒位置、序列号和序列号。之后检查页面的校验和。如果校验和无效,该函数将返回错误。
ogg_gptopts()
该函数用于将opts位置转换为64 位无符号整数的时间戳。
  • 如果Stream有支持的编解码器,该函数的工作原理是首先调用 os->codec->gptopts() 函数。如果Stream没有支持的编解码器,则该函数仅返回opts位置。
  • 如果呈现时间戳大于 INT64_MAX,该函数会记录一条错误消息并将呈现时间戳设置为 AV_NOPTS_VALUE。
特别说明
ogg_codec类型比较多,如下图所示:

针对所有类型,自己做了一个对比,可以参考一下:

ogg格式的parse相关代码如以上部分,ogg包含各种codec部分后需会逐步展开,类似MDCT这样详细做一下介绍,特别celt,frac,opus,speex,theora等编解码算法。因为这些部分必须要补充必要的背景知识,否则部分同学没有办法一下理解。
我是一枚爱跑步的程序猿,维护公众号和知乎专栏《MediaStack》,有兴趣可以关注,一起学习音视频知识,时不时分享实战经验。
继续阅读
阅读原文