【音视频 | opus】opus编码的Ogg封装文件详解

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍 opus 编码的 Ogg 封装文件🍭
😎金句分享😎:🍭🍭

本文未经允许,不得转发!!!

目录

  • 🎄一、概述
  • 🎄二、ID头部数据(ID Header)
    • ✨2.1、ID 头部数据的介绍
    • ✨2.2、.opus 文件 ID头部数据 分析
  • 🎄三、注释头部数据(Comment Header)
    • ✨3.1、注释头部数据的介绍
    • ✨3.2、.opus 文件 注释头部数据 分析
    • 在这里插入图片描述
  • 🎄四
  • 🎄五
  • 🎄六、


在这里插入图片描述

🎄一、概述

前面的文章 Ogg封装格式详解 介绍了Ogg格式的封装,介绍了封装过程、Ogg的页结构、Ogg的段,但没涉及到每个段的内容,因为这跟编码有关系。本文就介绍 opus 编码在 Ogg 封装文件中是怎样存储的,同样地,从一个 opus 编码的Ogg文件去查看十六进制,最终了解 opus 编码 Ogg 封装文件的整个结构,这样就可以轻易将这类文件解码为PCM了。

opus 编码的Ogg文件结构如下图:

  • 逻辑Ogg比特流中的第一个数据包必须包含ID头部数据(ID Header),该头部数据将流唯一标识为Opus音频。
  • 逻辑Ogg比特流中的第二个数据包必须包含注释头部数据(Comment Header),其中包含用户提供的元数据。
  • 之后的所有页面(page)都是音频数据页面。
    在这里插入图片描述
    下文分析的Ogg封装文件为 48000Hz-s16le-1ch-ChengDu.opus,下载链接:https://download.csdn.net/download/wkd_007/88492683

在这里插入图片描述

🎄二、ID头部数据(ID Header)

✨2.1、ID 头部数据的介绍

opus编码的逻辑Ogg比特流中,第一页必须包含ID头部数据,其结构如下图,包括8个字段,各个字段代表的含义如下:

在这里插入图片描述

  • 1、Magic Signature(8字节):

    这是一个8位字节(64位)字段,允许编解码器识别,并且是人类可读的。它按顺序包含以下的字母:

    0x4F 'O'
    0x70 'p'
    0x75 'u'
    0x73 's'
    0x48 'H'
    0x65 'e'
    0x61 'a'
    0x64 'd'
    

    从“Op”开始有助于将其与音频数据包区分开来,因为这是一个无效的TOC序列。

  • 2、Version (1字节, unsigned):
    对于此版本的封装规范,版本号必须始终为“1”。实现应该将版本号的前四位与已识别规范的版本号匹配的流视为与该规范向后兼容。也就是说,版本号可以分为“主要”和“次要”版本子字段,次要子字段的变化(在较低的四位中)表示兼容的变化。例如,本规范的实现应该接受版本号为“15”或更低的任何流,并且应该假设版本号为”16“或更高的任何流不兼容。选择初始版本“1”是为了防止实现依赖此八位字节作为“OpusHead”字符串的null终止符。

  • 3、Output Channel Count ‘C’ (1字节, unsigned)
    这是输出通道的数量。这可能与编码信道的数量不同,编码信道的数目可以在逐包的基础上改变。此值不得为零。最大允许值取决于通道映射族,可能大到255。详见[RFC7845]文档的第5.1.1节。

  • 4、Pre-skip (2字节, unsigned, little endian):

    这是开始播放时要从解码器输出中丢弃的采样数(48 kHz),也是要从页面的颗粒位置中减去以计算其PCM采样位置的数量。当裁剪现有Ogg Opus流的开头时,建议预跳过至少3840个样本(80ms),以确保解码器完全收敛。

  • 5、Input Sample Rate (4字节, unsigned, little endian):

    这是原始输入(编码前)的采样率,单位为Hz。该字段不是用于播放编码数据的采样率。

    Opus可以在4、6、8、12和20kHz的内部音频带宽之间切换。流中的每个数据包可以具有不同的音频带宽。不管音频带宽如何,参考解码器都支持以8、12、16、24或48kHz的采样率对任何流进行解码。传递到编码器的音频的原始采样率不被有损压缩所保留。

    Ogg Opus播放器应根据以下程序选择播放采样率:

    1.如果硬件支持48 kHz播放,则以48 kHz进行解码。

    2.否则,如果硬件的最高可用采样率是支持的速率,则以该采样率进行解码。

    3.否则,如果硬件的最高可用采样率小于48kHz,则以高于最高可用硬件速率的下一个更高的Opus支持速率进行解码并重新采样。

    4.否则,以48 kHz解码并重新采样。

    然而,“输入采样率”字段允许复用器将原始输入流的采样率作为元数据传递。当用户需要输出采样率来匹配输入采样率时,这是有用的。例如,当不播放输出时,将PCM格式样本写入磁盘的实现可能会选择将音频重新采样回原始输入采样率,以减少用户的意外,因为用户可能会合理地期望以相同的采样率返回文件。

    零值表示“未指定”。复用器应该写入实际输入采样率或零,但使用该字段执行某些操作的实现应该注意,如果给定疯狂的值(例如,如果请求,不要实际将输出上采样到10MHz),则行为要理智。实现应支持 8kHz 和 192kHz(包括8kHz)之间的输入采样率。此范围之外的速率可以通过回落到默认速率 48kHz 来忽略。

  • 6、Output Gain (2字节, signed, little endian):

    这是解码时要应用的增益。它是对解码器输出进行缩放以获得所需播放量的因子的20*log10,存储在具有8个小数比特的16比特、带符号的2的补码定点值中(即Q7.8[Q-NOTATION])。

    为了应用增益,实现可以使用以下内容:

    sample *= pow(10, output_gain/(20.0*256))
    

    其中“output_gain”是来自标头的原始16位值。

    玩家和媒体框架应该默认应用它。如果播放器选择应用任何音量调整或增益修改,如R128_TRACK_AIN(见第5.2节),则除了此输出增益外,还必须应用该调整,以实现标准化音量的播放。

    复用器应该将该字段设置为零,而不是在编码之前应用任何增益,只要这是可能的,并且不会与用户的愿望相冲突。非零输出增益表示在编码之后调整了增益,或者用户希望在保持恢复原始信号幅度的能力的同时调整增益以进行回放。

    尽管输出增益具有巨大的范围(+/-128 dB,足以将听不见的声音放大到身体疼痛的阈值),但大多数应用程序只能合理地使用零附近这个范围的一小部分。大范围的部分作用是确保增益始终可以在OpusHead和R128增益标签之间无损传输(见下文)而不会饱和。

  • 7、Channel Mapping Family (1字节, unsigned):

    这个八位字节表示输出通道的顺序和语义。

    该八位位组的每个当前指定值都指示一个映射族,该映射族定义了一组允许的通道计数,以及每个允许的通道数的有序通道名称集。详见[RFC7845]文档的第5.1.1节。

  • 8、Channel Mapping Table:

    此表定义了从编码流到输出通道的映射。其内容见[RFC7845]文档的第5.1.1节。ID标头中的所有字段都是必需的,但“通道映射表”除外,当通道映射族为0时,必须省略该字段,否则为必需字段。如果流包含的ID标头没有足够的数据用于这些字段,即使它包含有效的“魔术签名”,实现也应该将其视为无效。该规范的未来版本,甚至是向后兼容的版本,可能会在ID头中包含额外的字段。如果ID标头具有兼容的主版本,但具有较大的次版本,则实现不得将其视为无效,因为它包含此处未指定的其他数据,前提是它仍然在第一页上完成。

✨2.2、.opus 文件 ID头部数据 分析

现在按照上面的字段,分析opus编码的Ogg文件,用Notepad打开 48000Hz-s16le-1ch-ChengDu.opus 并查看十六进制模式:

在这里插入图片描述

  • 前面蓝色背景的部分(包括0x13)是Ogg页头部数据,不清楚的看 [上篇文章] 的 4.2 节;
  • 紫色框开始是opus编码的ID头部数据,内容是8个字符:OpuaHead
  • 接下去的蓝色框是版本号,目前的版本,该值为 1
  • 紧接着的蓝色框是声道数量,这里值为 1 ,表示单声道;
  • 后面的橙色框表示 “开始播放时要从解码器输出中丢弃的采样数”,值为0x0138
  • 接着的绿色框表示 “原始输入(编码前)的采样率”,值为0xbb80,对应十进制 48000
  • 后面的蓝色框表示 “解码时要应用的增益”;
  • 后面的黑色框表示 “表示输出通道的顺序和语义”,值为 0 ,代表使用映射族0,允许的通道数:1或2,且省略通道映射表(Channel Mapping Table);

在这里插入图片描述

🎄三、注释头部数据(Comment Header)

✨3.1、注释头部数据的介绍

opus编码的逻辑Ogg比特流中,第二页必须包含注释头部数据。它可能跨越多个页面(page),从逻辑流的第二页开始。无论它跨越多少页,注释头数据包都必须结束在一个完整的页面,其结构如下图,包括6个字段,各个字段代表的含义如下:
在这里插入图片描述

  • 1、Magic Signature(8个字节):

    这是一个8位字节(64位)字段,允许编解码器识别,并且是人类可读的。它按顺序包含以下神奇数字:

    0x4F 'O'
    0x70 'p'
    0x75 'u'
    0x73 's'
    0x54 'T'
    0x61 'a'
    0x67 'g'
    0x73 's'
    

    从“Op”开始有助于将其与音频数据包区分开来,因为这是一个无效的TOC序列。

  • 2、Vendor String Length (4个字节, unsigned, little endian):

    此字段给出下个字段Vendor String的长度,单位为八位字节。它不得指示供应商字符串比数据包的其余部分长。

  • 3、Vendor String (variable length, UTF-8 vector):

    这是一个用于供应商信息的简单可读标签,编码为UTF-8字符串[RFC3629]。不需要终止空八位字节。

    此标签旨在识别编解码器编码器和封装实现,以跟踪技术行为的差异。面向用户的应用程序可以使用“ENCODER”用户注释标记来标识自己。

  • 4、User Comment List Length (4个字节, unsigned, little endian):

    此字段指示用户提供的注释个数。它可能表示用户提供的注释为零,在这种情况下,数据包中没有其他字段。它不能表明有太多的注释,以至于注释字符串长度需要比数据包其余部分更多的数据。

  • 5、User Comment #i String Length (4个字节, unsigned, little endian):

    此字段给出下个字段User Comment #i String的长度,单位为八位字节。“用户评论列表长度”字段指示的每个用户评论都有一个。它不能指示字符串比数据包的其余部分长。

  • 6、User Comment #i String (variable length, UTF-8 vector):

    此字段包含编码为UTF-8字符串的单个用户注释[RFC3629]。“用户评论列表长度”字段指示的每个用户评论都有一个。

✨3.2、.opus 文件 注释头部数据 分析

在这里插入图片描述

在这里插入图片描述

🎄四

在这里插入图片描述

🎄五

在这里插入图片描述

🎄六、

在这里插入图片描述
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/130750.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

汇编语言(举个栗子)

汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。在汇编语言中,用助记符代替机器指令的操作码,用地址符号或标号代替指令或操作数的地址。在不同…

基于51单片机土壤湿度检测及自动浇花系统仿真(带时间显示)

wx供重浩:创享日记 对话框发送:单片机浇花 获取完整源码源文件仿真源文件原理图源文件论文报告等 单片机土壤湿度检测及自动浇花系统仿真(带时间显示) 具体功能: (1)液晶第一行显示实际湿度&am…

信道编码译码及MATLAB仿真

文章目录 前言一、什么是信道编码?二、信道编码的基本逻辑—冗余数据1、奇偶检验码2、重复码 三、编码率四、4G 和 5G 的信道编码1、卷积码2、维特比译码(Viterbi)—— 概率译码3、LTE 的咬尾卷积码4、LTE 的 turbo 码 五、MATLAB 仿真1、plo…

0008Java安卓程序设计-ssm基于Android平台的健康管理系统

文章目录 **摘要**目录系统实现开发环境 编程技术交流、源码分享、模板分享、网课教程 🐧裙:776871563 摘要 首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,…

Git 的基本操作 ——命令行

Git 的工作流程 详解如下: 本地仓库:是在开发人员自己电脑上的Git仓库,存放我们的代码(.git 隐藏文件夹就是我们的本地仓库) 远程仓库:是在远程服务器上的Git仓库,存放代码(可以是github.com或者gitee.com 上的仓库,或者自己该公司的服务器…

【ElasticSearch系列-05】SpringBoot整合elasticSearch

ElasticSearch系列整体栏目 内容链接地址【一】ElasticSearch下载和安装https://zhenghuisheng.blog.csdn.net/article/details/129260827【二】ElasticSearch概念和基本操作https://blog.csdn.net/zhenghuishengq/article/details/134121631【三】ElasticSearch的高级查询Quer…

PTA:前序序列创建二叉树

前序序列创建二叉树 题目输入格式输出格式输入样例(及其对应的二叉树)输出样例 代码 题目 编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以二叉链表存储)。 例如如下的先序遍…

SpringCloudAlibaba - 项目完整搭建(Nacos + OpenFeign + Getway + Sentinel)

目录 一、SpringCloudAlibaba 项目完整搭建 1.1、初始化项目 1.1.1、创建工程 1.1.2、配置父工程的 pom.xml 1.1.3、创建子模块 1.2、user 微服务 1.2.1、配置 pom.xml 1.2.2、创建 application.yml 配置文件 1.2.3、创建启动类 1.2.4、测试 1.3、product 微服务 1…

如何使用CodeceptJS、Playwright和GitHub Actions构建端到端测试流水线

介绍 端到端测试是软件开发的一个重要方面,因为它确保系统的所有组件都能正确运行。CodeceptJS是一个高效且强大的端到端自动化框架,与Playwright 结合使用时,它成为自动化Web、移动甚至桌面 (Electron.js) 应用程序比较好用的工具。 在本文中…

代码随想录算法训练营第23期day38|动态规划理论基础、509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯

目录 一、动态规划理论基础 1.动态规划的解题步骤 2.动态规划应该如何debug 二、(leetcode 509)斐波那契数 1.递归解法 2.动态规划 1)确定dp数组以及下标的含义 2)确定递推公式 3)dp数组如何初始化 4&#x…

C++虚表与虚表指针详解

类的虚表 每个包含了虚函数的类都包含一个虚表。 当一个类(B)继承另一个类(A)时,类B会继承类A的函数的调用权。所以如果一个基类包含了虚函数,那么其继承类也可调用这些虚函数,换句话说&…

基于ASP.NET MVC + Bootstrap的仓库管理系统

基于ASP.NET MVC Bootstrap的仓库管理系统。源码亲测可用,含有简单的说明文档。 适合单仓库,基本的仓库入库管理,出库管理,盘点,报损,移库,库位等管理,有着可视化图表。 系统采用Bo…

MySQL导入数据库报错Error Code: 2006

Error Code: 2006 - MySQL server has gone away 因为导入的某张表数据过大导致导入中途失败 , 修改max_allowed_packet 即可解决。 SET GLOBAL max_allowed_packet 1024*1024*200;

【数据结构】数组和字符串(十五):字符串匹配2:KMP算法(Knuth-Morris-Pratt)

文章目录 4.3 字符串4.3.1 字符串的定义与存储4.3.2 字符串的基本操作4.3.3 模式匹配算法0. 朴素模式匹配算法1. ADL语言2. KMP算法分析3. 手动求失败函数定义例1例2例3 4. 自动求失败函数(C语言)5. KMP算法(C语言)6. 失败函数答案…

STM32F103C8T6第二天:按键点灯轮询法和中断法、RCC、电动车报警器(振动传感器、继电器、喇叭、433M无线接收发射模块)

1. 点亮LED灯详解(307.11) 标号一样的导线在物理上是连接在一起的。 将 PB8 或 PB9 拉低,就可以实现将对应的 LED 灯点亮。常用的GPIO HAL库函数: void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init);//I/…

产品经理入门学习(二):产品经理问题思考维度

参考引用 黑马-产品经理入门基础课程 1. 抓住核心用户 1.1 为什么要抓住核心用户 什么是用户? 所有和产品有关系的群体就是用户,他们是一群既有共性,又有差异的群体组合 做产品为什么要了解用户? 了解用户的付费点、更好的优化产…

【软考中级】软件设计师-下午题

下午题 试题一 黑洞:加工有输入无输出 白洞(奇迹):加工有输出无输入 灰洞:数据流输入的加工不足以产生输出 结构化语言: IF *** THEN ELSE IF *** THEN ******* END IF END IF 数据流的父子图平衡,如果父子图平衡就不…

【CIO人物展】黄淮学院副CIO周鹏:构建数智化平台赋能学校高质量发展

周鹏 本文由黄淮学院副CIO周鹏投递并参与《2023中国数智化转型升级优秀CIO》榜单/奖项评选。丨推荐企业—锐捷网络 大数据产业创新服务媒体 ——聚焦数据 改变商业 黄淮学院是2004年经教育部批准成立的一所省属全日制普通本科高校。学校位于素有“豫州之腹地、天下之最中”之美…

地理信息系统原理-空间数据结构(7)

​四叉树编码 1.四叉树编码定义 四叉树数据结构是一种对栅格数据的压缩编码方法,其基本思想是将一幅栅格数据层或图像等分为四部分,逐块检查其格网属性值(或灰度);如果某个子区的所有格网值都具有相同的值&#xff0…

Linux----------------Shell重定向输入输出

(一) 标准输入 以键盘读取用户输入的数据,然后再把数据拿到 Shel程序中使用。 标准输出 Shell 程序产生的数据,这些数据一般都是呈现到显示器上供用户浏览查看 输入输出重定向 输入方向就是数据从哪里流向程序。数据默认从键…