从零开始精通RTSP之传输AAC音频流

概述

        AAC,英文全称为Advanced Audio Coding,是一种高效的有损音频压缩格式,由MPEG-4标准定义。相比传统的MP3,AAC在相同比特率下能提供更好的音质,尤其在低比特率场景下优势明显。AAC支持多种采样率、声道数和编码工具,比如:LC(Low Complexity)、HE-AAC(High-Efficiency AAC)、HE-AAC v2(增强型高效率AAC)等,可适应不同应用场景的需求。

AAC ADTS

        AAC ADTS是指AAC数据在传输或存储时,采用的封装格式。ADTS为AAC编码的音频数据提供了一个标准化的容器,使得非实时流媒体环境(比如:文件系统、HTTP下载等)也能方便地处理和识别AAC数据。ADTS头部结构详细描述了封装AAC音频数据的ADTS帧的前导部分,它包含了必要的信息以供解码器正确识别、解析和解码AAC音频数据。在实际应用中,ADTS头部通常为7个字节,不包含CRC校验。当需要增加数据完整性检查时,可以选择添加2个字节的CRC校验,此时头部总长度为9个字节。ADTS头部包含以下字段。

        syncword:同步字,固定为0xFFF,占12位,用于识别ADTS帧的起始位置。

        ID:固定为0,占1位,表明是MPEG-4格式的音频数据。

        layer:固定为0,占2位,无特定含义,在MPEG-1/2 Layer III中用于区分层信息,但在AAC中未使用。

        protection absent:占1位,表示是否包含CRC校验。1表示没有CRC校验(通常情况),0表示存在CRC校验。

        profile:占2位,表示AAC编码的Profile,如0表示AAC Main Profile,1表示AAC Low Complexity (LC),2表示AAC Scalable Sample Rate (SSR),3保留。

        sampling freq:占4位,采样率索引,指示音频的采样频率。比如:0表示96 kHz,1表示88.2 kHz,2表示64 kHz,3表示48 kHz,4表示44.1 kHz,5表示32 kHz,6表示24 kHz,7表示22.05 kHz,8表示16 kHz,9表示12 kHz,10表示11.025 kHz,11表示8 kHz,12至15保留。

        private bit:占1位,保留位,通常为0。

        channel config:占3位,表示声道数配置。比如:0表示单声道,1表示立体声,2至7表示多声道模式。

        original/copy:占1位,原版/复制标志,通常为0,表示原版。

        home:占1位,保留位,通常为0。

        emphasis:占2位,强调模式,通常为0,表示无强调。

        frame length:占13位,表示当前ADTS帧的总长度(不包括syncword和CRC,如果有),单位为字节。

        adts buffer fullness:占11位,解码器缓冲区状态信息,用于解码器的缓冲管理。

        number of raw data blocks:占2位,原始数据块数量,通常为00,表示只有一个数据块。

        optional CRC:可选,占16位。如果protection absent字段为0,则ADTS头后会跟随一个16-bit的CRC校验码,用于检测ADTS头的完整性。

封装方法

        RTP封装AAC音频数据时,需要遵循一定的规则和步骤,以确保音频数据能够被正确地传输和解码。与H264、H265的封装方法相比,AAC的封装方法相对比较简单。AAC音频帧一般比较小,只用一个RTP包便可以承载。因此,可以直接将AAC音频数据放入一个RTP包的Payload中。注意:AAC音频数据不包括ADTS头。此时,RTP包的结构如下。

+-----------------------------+
| RTP Header (12 Byte)        |
| AAC Header (4 Byte)         |
| AAC Data ...                |
+-----------------------------+

        可以看到,在12字节的RTP Header后,还有4字节的AAC Header,最后才是AAC音频数据。AAC Header的第一个字节固定为0x00,第二个字节固定为0x10。第三、四个字节保存AAC Data的大小,最多只能保存13位。第三个字节保存数据大小的高8位,第四个字节的高5位保存数据大小的低5位。如果用C/C++实现,可以参考下面的示例代码。

rtpPacket->payload[0] = 0x00;
rtpPacket->payload[1] = 0x10;
// 取aacDataLen的高8位
rtpPacket->payload[2] = (aacDataLen & 0x1FE0) >> 5;
// 取aacDataLen的低5位
rtpPacket->payload[3] = (aacDataLen & 0x1F) << 3;

AAC的SDP

        在使用裸AAC(Raw AAC)格式时,SDP媒体描述应反映这种封装方式,以便接收端能够正确识别、配置解码器并处理音频流。下面,给出了一个针对裸AAC格式的典型SDP媒体描述。

v=0
o=- 1595963774959070000 1 IN IP4 192.0.2.1
s=Example Session
t=0 0
m=audio 49250 RTP/AVP 96
c=IN IP4 192.0.2.1
a=rtpmap:96 MPEG4-GENERIC/44100/2
a=fmtp:96 streamtype=5;profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3;
a=ptime:1024
a=maxptime:6144
a=control:trackID=1

        m=行中,audio表明这是一个音频媒体流;49250是传输此音频流所使用的端口号;RTP/AVP表示使用RTP进行传输,且使用AVP作为默认的RTP特性集;96是RTP负载类型,用于标识封装在RTP包内的AAC数据。这个值必须与接收端协商一致,以便接收端能够识别出AAC音频。

        a=rtpmap行定义了负载类型(PT=96)对应的编码格式和参数。MPEG4-GENERIC表示使用MPEG-4 Generic编码格式封装数据,对于裸AAC而言,这是合适的标识符。44100表示采样率为44.1 kHz,2表示双声道(立体声)。

        a=fmtp行提供了负载类型(PT=96)的附加参数。streamtype=5指定为音频流(MPEG-4 Object Type Indication)。profile-level-id=1用于指定AAC编码的Profile和Level,但实际值需参照AAC标准或具体实现。mode=AAC-hbr表示使用AAC High Bit Rate(HBR)模式。sizelength=13;indexlength=3;indexdeltalength=3为AAC音频配置信息的长度,具体值根据实际AAC配置而定。

        a=ptime行表示建议的解码器缓冲区处理的最短有效载荷时间(取样点数或毫秒),在此例中为1024个采样点。对于44.1 kHz采样率,相当于约23.2毫秒。

        a=maxptime行设置了接收端解码器缓冲区应能处理的最大有效载荷时间(取样点数或毫秒),防止过大的包导致缓冲溢出,在此例中为6144个采样点。对于44.1 kHz采样率,约为143毫秒。

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

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

相关文章

MySQL远程连接错误解决:“Host is not allowed to connect to this MySQL server”详解

目录 一、异常错误二、原因三、解决方法 一、异常错误 通过远程客户端访问MySQL服务器时会遇到“Host is not allowed to connect to this MySQL server”的错误提示。 二、原因 MySQL服务器当前配置不允许来自特定主机的连接尝试。 三、解决方法 允许远程主机访问MySQL服…

link.click()时浏览器报错The file at ‘data:image/png;base64,iVBORw

代码如下&#xff1a; const dataURL canvas.toDataURL({format: "png",width: 400,height: 400, });const link document.createElement("a"); link.download new Date().getTime();link.href dataURL; document.body.appendChild(link); link.click…

IT行业的现状与未来发展趋势

方向一&#xff1a;技术革新与行业应用 随着科技的日新月异&#xff0c;IT行业已成为全球经济增长和社会进步的重要引擎。从云计算、大数据、人工智能到物联网、5G通信和区块链&#xff0c;这些前沿技术正以前所未有的速度重塑我们的生活和工作方式。以下是我对IT行业现状及未来…

高压无源探头能测整流桥电压吗?

高压无源探头是用于测量高电压电路中信号的一种工具&#xff0c;它不需要外部电源供电。然而&#xff0c;对于测量整流桥电压&#xff0c;需要考虑几个因素以确定是否可以使用高压无源探头。 首先&#xff0c;让我们了解一下整流桥的基本原理。整流桥是一种电路&#xff0c;用…

MyBatis的一二级缓存区别

MyBatis的一级缓存和二级缓存之间存在以下主要区别&#xff1a; 缓存级别与作用域&#xff1a; 一级缓存&#xff1a;也称为SqlSession级别的缓存&#xff0c;与数据库会话&#xff08;SqlSession对象&#xff09;绑定&#xff0c;并且默认开启。一级缓存的作用域仅限于同一个…

STM32--HC-SR501 热释电人体红外感应模块

实物引脚图&#xff1a; 模块工作特性&#xff1a; 当人进入感应范围之后输出引脚输出高电平&#xff0c;人离开感应范围自动延时输出低电平 热释电效应&#xff1a; 热释电传感器&#xff0c;也称为人体红外传感器&#xff0c;其工作原理基于热释电效应。这种传感器由几个关…

Rust中使用Rocket框架返回html网页,返回一个基于 Handlebars (HBS) 模板的响应

在Rust中使用Rocket框架返回网页&#xff0c;通常涉及创建一个路由&#xff0c;该路由将返回一个HTML页面。Rocket是一个快速、易用且可扩展的Web框架&#xff0c;它允许你以一种简洁的方式定义路由和处理请求。 一、使用Rocket框架返回一个简单的HTML页面&#xff1a; 添加依…

手机怎么下载别人直播间视频

手机下载直播视频&#xff0c;您需要按照以下步骤进行操作&#xff1a; 1. 打开直播平台&#xff0c;获取正在直播的链接&#xff0c;就是直播间的地址&#xff0c;然后粘贴在直接视频解析工具里&#xff0c;就可以同步下载直播视频画面。 2. 获取直播视频解析工具方法&#…

项目管理-案例重点知识(成本管理)

项目管理&#xff1a;每天进步一点点~ 活到老&#xff0c;学到老 ヾ(◍∇◍)&#xff89;&#xff9e; 何时学习都不晚&#xff0c;加油 三、成本管理 案例重点 成本管理 案例重点内容&#xff1a; &#xff08;1&#xff09;成本管理计划内容 &#xff08;2&#xff09;估算…

pcdn边缘云常见sla有哪些?如何避免被白嫖

PCDN&#xff08;Point-to-Point Content Delivery Network&#xff09;边缘云常见的SLA&#xff08;Service Level Agreement&#xff09;规则包括高峰期离线、服务时间、重传延时、限速等。这些规则是为了保证服务质量和用户体验。下面将详细解释这些规则&#xff0c;并提供一…

ANSYS Maxwell16 引导

Maxwell 使用 下载 https://download.csdn.net/download/wangjun_huster/89313272 安装 https://www.52txr.cn/2022/MaxwellInstall.html 入门

渗透相关面试+流量分析

文章目录 简单自我介绍上一个工作的主要内容Hvv的分组和流程你在hvv/攻防演练中取得了哪些成绩&#xff1f; 二、渗透相关面试题基础端口号以及入侵方式OSI七层协议响应状态码都有哪些&#xff1f;**WAF和IPS的区别**盲注是什么&#xff1f;java内存马类型**内存马有几种类型**…

2024最新大厂C++面试真题合集,大厂面试百日冲刺 bay11

CSIG 腾讯后台 new和malloc区别 "new"是C的一个操作符&#xff0c;它在创建对象时会自动调用构造函数。"malloc"是C语言的函数&#xff0c;仅仅分配内存。"new"返回的是对象类型的指针&#xff0c;类型与对象的类型保持一致&#xff0c;无需类…

谷歌全力反击 OpenAI:Google I/O 2024 揭晓 AI 新篇章,一场激动人心的技术盛宴

&#x1f680; 谷歌全力反击 OpenAI&#xff1a;Google I/O 2024 揭晓 AI 新篇章&#xff0c;一场激动人心的技术盛宴&#xff01; 在这个人工智能的全新时代&#xff0c;只有谷歌能让你眼前一亮&#xff01;来自全球瞩目的 Google I/O 2024 开发者大会&#xff0c;谷歌用一场…

Vue 之 后台管理系统的权限路由的管理

目录 前言实现理解三者的概念以及之间的关联账号&#xff08;用户&#xff09;角色菜单 用户权限授权相关概念实现代码实现登录跳转路由&#xff0c;路由守卫中进行权限验证按钮权限封装指令&#xff1a;调用&#xff08;其中一个页面参考&#xff09; 思路&#xff0c;操作流程…

学习java第七十一天

DI&#xff1a;依赖注入 依赖注入是spring容器中创建对象时给其设置依赖对象的方式&#xff0c;比如给spring一个清单&#xff0c;清单中列出了需要创建B对象以及其他的一些对象&#xff08;可能包含了B类型中需要依赖对象&#xff09;&#xff0c;此时spring在创建B对象的时候…

探索 pinia-plugin-persistedstate:为 Pinia 状态持久化助力

在使用 Pinia 进行状态管理时&#xff0c;我们常常希望某些重要的状态能够持久化保存&#xff0c;以便在应用重新启动或不同会话中保持数据的连续性。这时候&#xff0c;pinia-plugin-persistedstate 就派上了大用场。 首先&#xff0c;我们当然需要安装这个插件&#xff1a; …

数学:矩阵范数的定义、常见的矩阵范数

1 算子范数【从属范数】 1.1 1-算子范数【列和范数】 &#xff1a;即对A的每列的绝对值求和再求其中的最大值 1.2 ∞-算子范数【行和范数】即对 A 的每行的绝对值求和再求其中的最大值 1.3 2-算子范数【谱范数】 学过奇异值分解就知道谱范数是最大奇异值/ 二次型的最大特…

力扣刷题day01

前期准备&#xff1a; 熟练掌握一门编程语言&#xff08;Java&#xff0c;C&#xff0c;python&#xff09;掌握数据结构与算法算法通关手册python 重学C 编程指北C 学C之前要学C语言&#xff0c;重点掌握指针和内存

大数据Spark教程从入门到精通第四篇:Spark快速上手

一&#xff1a;Spark快速上手 1&#xff1a;创建Maven项目 idea安装scala_idea scala插件-CSDN博客 代表了我们安装scala的maven环境已经准备好了&#xff0c;代码可以正常跑了