概述
随着整个互联网的崛起,数据传递的模式也在一直降级变动,总的风行趋势如下:
纯文本的短信,QQ -> 空间,微博,朋友圈的图片文字联合 -> 微信语音 -> 各大直播软件 -> 抖音快手短视频
音视频的倒退正在向各个行业一直扩大,从教育的近程授课,交通的人脸识别,医疗的近程就医等等,音视频方向曾经占据一个相当重要的地位,而音视频真正入门的文章又少之甚少,一个刚毕业小白可能很难切入了解, 因为音视频中波及大量理论知识, 而代码的书写须要联合这些实践, 所以搞懂音视频, 编解码等理论知识至关重要. 自己也是从实习开始接触音视频我的项目, 看过很多人的文章,在这里总结一个通俗易懂的文章,让更多筹备学习音视频的同学更快入门。
划重点
本文中理论知识来自于各种音视频文章的演绎音视频编码基本原理汇总, 其中也会有一些我本人总结减少的局部. 若有谬误可评论, 查看后会更正.
为了避免大家了解过于空洞, 作者花了三个月工夫将最罕用, 最重要的一些性能的理论知识及实战 Demo 亲自写进去, 配合文章浏览成果更佳. 每一部分的文章能够在上面每章章节开始的深刻学习中点击链接查看, 链接中文章均有 Github 地址, 每个 Demo 都亲测能够通过, 能够下载 Demo 运行.
如果喜爱, 请帮忙点赞并反对转载, 转载请附原文链接.
原理
-
采集
无论是 iOS 平台, 还是安卓平台, 咱们都是须要借助官网的 API 实现一系列相干性能. 首先咱们要明确咱们想要什么, 最开始咱们须要一部手机, 智能手机中摄像头是不可短少的一部分, 所以咱们通过一些零碎 API 获取就要能够获取物理摄像头将采集到的视频数据与麦克风采集到的音频数据.
-
解决
音频和视频原始数据实质都是一大段数据, 零碎将其包装进自定义的构造体中, 通常都以回调函数模式提供给咱们, 拿到音视频数据后, 能够依据各自我的项目需要做一系列非凡解决, 如: 视频的旋转, 缩放, 滤镜, 美颜, 裁剪等等性能, 音频的单声道降噪, 打消回声, 静音等等性能.
-
编码
原始数据做完自定义解决后就能够进行传输, 像直播这样的性能就是把采集好的视频数据发送给服务器, 以在网页端供所有粉丝观看, 而传输因为自身就是基于网络环境, 宏大的原始数据就必须压缩后能力带走, 能够了解为咱们搬家要将物品都打包到行李箱这样了解.
-
传输
编码后的音视频数据通常以 RTMP 协定进行传输, 这是一种专门用于传输音视频的协定, 因为各种各样的视频数据格式无奈对立, 所以须要有一个规范作为传输的规定. 协定就起到这样的作用.
-
解码
服务端接管到咱们送过来的编码数据后, 须要对其解码成原始数据, 因为编码的数据间接送给物理硬件的设施是不能间接播放的, 只有解码为原始数据能力应用.
-
音视频同步
解码后的每帧音视频中都含有最开始录制时候设置的工夫戳, 咱们须要依据工夫戳将它们正确的播放进去, 然而在网络传输中可能会失落一些数据, 或者是延时获取, 这时咱们就须要肯定的策略去实现音视频的同步, 大体分为几种策略: 缓存肯定视频数据, 视频追音频等等.
推流,拉流流程
- 推流: 将手机采集到的视频数据传给后盾播放端进行展现,播放端能够是 windows, linux, web 端,即手机充当采集的性能,将手机摄像头采集到视频和麦克风采集到的音频合成编码后传给对应平台的播放端。
- 拉流: 将播放端传来的视频数据在手机上播放, 推流的逆过程,行将 windows, linux, web 端传来的视频数据进行解码后传给对应音视频硬件,最终将视频渲染在手机界面上播放.
推流如下:
拉流如下:
具体分析
推流,拉流理论为互逆过程,这里依照从采集开始介绍.
1. 采集
采集是推流的第一个环节,是原始的音视频数据的起源. 采集的原始数据类型为音频数据 PCM,视频数据 YUV,RGB…。
1.1. 音频采集
-
深入研究
- iOS Core Audio 简介
- iOS Audio Session 治理音频上下文
- iOS Audio Queue 采集播放音频数据
- iOS Audio Queue 采集音频数据实战
- iOS Audio Unit 采集音频数据
- iOS Audio Unit 采集音频数据实战
-
采集起源
- 内置麦克风
- 外置具备麦克风性能的设施(相机,话筒 …)
- 零碎自带相册
-
音频主要参数
- 采样率(samplerate): 模拟信号数字化的过程, 每秒钟采集的数据量, 采样频率越高, 数据量越大, 音质越好。
- 声道数(channels): 即单声道或双声道 (iPhone 无奈间接采集双声道,但能够模仿, 即复制一份采集到的单声道数据. 安卓局部机型能够)
- 位宽: 每个采样点的大小, 位数越多, 示意越精密, 音质越好, 个别是 8bit 或 16bit.
- 数据格式: iOS 端设施采集的原始数据为线性 PCM 类型音频数据
- 其余: 还能够设置采样值的精度, 每个数据包有几帧数据, 每帧数据占多少字节等等.
-
音频帧
音频与视频不同, 视频每一帧就是一张图片, 音频是流式, 自身没有明确的帧的概念, 理论中为了不便, 取 2.5ms~60ms 为单位的数据为一帧音频.
-
计算
数据量(字节 / 秒)=(采样频率(Hz)* 采样位数(bit)* 声道数)/ 8
单声道的声道数为 1,立体声的声道数为 2. 字节 B,1MB=1024KB = 1024*1024B
1.2. 视频采集
-
深入研究
- iOS AVCaptureSession 采集视频数据
- iOS AVCaptureSession 采集视频数据 Demo)
- 视频原始数据 YUV 介绍
-
采集起源
- 摄像头
- 屏幕录制
- 外置带摄像头采集性能的设施(相机,DJI 无人机,OSMO…)
- 零碎自带相册
留神: 像一些外置摄像头, 如像利用摄像机的摄像头采集, 而后用手机将数据处理编码并收回, 也是能够的, 然而数据的流向须要咱们解析, 即从摄像头的 HDMI 线转成网线口, 网线口再转 USB,USB 转苹果 Lighting 接口, 利用 FFmpeg 能够获取其中的数据.
-
视频主要参数
- 图像格式: YUV, RGB (即红黄蓝三种颜色混合组成各种色彩).
- 分辨率: 以后设施屏幕反对的最大分辨率
- 帧率: 一秒钟采集的帧数
- 其余: 白平衡, 对焦, 曝光, 闪光灯等等
- 计算 (RGB)
1 帧数据量 = 分辨率(width * height) * 每个像素的所占字节数(个别是 3 个字节)
留神下面计算的办法并不是惟一的, 因为视频的数据格式有很多种, 如 YUV420 计算形式为
分辨率(width * height) * 3/2
1.3. 综上所述
咱们假如要上传的视频是 1080P 30fps(分辨率:1920*1080), 声音是 48kHz, 那么每秒钟数据量如下:
video = 1920 * 1080 * 30 * 3 = 186624000B = 186.624 MB
audio = (48000 * 16 * 2) / 8 = 192000B = 0.192 MB
由此咱们可得,如果间接将原始采集的数据进行传输, 那么一部电影就须要 1000 多 G 的视频,如果是这样将如许恐怖,所以就波及到咱们前面的编码环节。
2. 解决
-
深入研究 (待增加)
- 高效裁剪视频
- 依据声音大小实现音量柱性能
从上一步中,咱们能够失去采集到的音频原始数据和视频原始数据,在挪动端,个别是通过各自手机平台官网 API 中拿到, 前文链接中皆有实现的办法.
之后, 咱们能够对原始数据加以解决, 对原始操作解决只能在编码之前, 因为编码后的数据只能用于传输. 比方可 以对图像处理
- 美颜
- 水印
- 滤镜
- 裁剪
- 旋转
- …
对音频解决
- 混音
- 打消回声
- 降噪
- …
目前风行的有很多大型框架专门用来解决视频, 音频, 如 OpenGL, OpenAL, GPUImage… 以上的各种解决网上均有开源的库能够实现, 基本原理就是, 咱们拿到原始的音视频帧数据, 将其送给开源库, 解决完后再拿到解决好的音视频持续咱们本人的流程. 当然很多开源库仍须要依据我的项目需要稍微更改并封装.
3. 编码
-
深入研究
- iOS 视频视频编码
- iOS 音频音频编码
3.1. 为什么要编码
在第 1.
步采集最初曾经讲到, 原始的视频每秒钟就产生 200 多 MB, 如果间接拿原始数据传输, 网络带宽即内存耗费是微小的, 所以视频在传输中是必须通过编码的.
相似的例子就像咱们平时搬家, 如果间接搬家, 货色很零散, 须要跑很多趟拿, 如果将衣服, 物品打包, 咱们仅仅须要几个行李箱就能够一次搞定. 等咱们达到新家, 再将货色取出来, 从新安排, 编解码的原理就是如此.
3.2. 有损压缩 VS 无损压缩
-
有损压缩
- 视频利用人眼的视觉个性, 以肯定的主观失真换取数据的压缩, 比方人眼对亮度辨认的阈值, 视觉阈值, 对亮度和色度的敏感度不同, 以至于能够在编码时引入适量误差, 不会被觉察进去.
- 音频利用了人类对图像或声波中的某些频率成分不敏感的个性,容许压缩过程中损失肯定的信息;去除声音中冗余成分的办法实现。冗余成分指的是音频中不能被人耳朵觉察的信号,它们对声音的音色,音调等信息没有任何帮忙。重构后的数据与原来的数据有所不同,但不影响人对原始材料表白的信息造成误会。
有损压缩实用于重构信号不肯定非要和原始信号完全相同的场合。
-
无损压缩
- 视频的空间冗余, 工夫冗余, 构造冗余, 熵冗余等, 即图像的各个像素间存在很强的关联性, 打消这些冗余不会导致信息失落
- 音频压缩格局则是利用数据的统计冗余进行压缩,可完全恢复原始数据而不引起任何失真,但压缩率是受到数据统计冗余度的实践限度,个别为 2:1 到 5:1。
正因为有着下面的压缩办法, 视频数据量能够极大的压缩, 有利于传输和存储.
3.3. 视频编码
-
原理:编码是如何做到将很大的数据质变小的呢? 次要原理如下
- 空间冗余: 图像相邻像素之间有很强的相关性
- 工夫冗余: 视频序列的相邻图像之间内容类似
- 编码冗余: 不同像素值呈现的概率不同
- 视觉冗余: 人的视觉系统对某些细节不敏感
- 常识冗余: 规律性的构造可由先前常识和背景常识失去
-
压缩编码的办法
-
变换编码 (理解即可,具体请谷歌)
将空间域形容的图像信号变换成频率域,而后对变换后的系数进行编码解决。一般来说,图像在空间上具备较强的相关性,变换频率域能够实现去除相干与能量集中。罕用的正交变换有离散傅里叶变换,离散余弦变换等等。
-
熵编码 (理解即可,具体请谷歌)
熵编码是因编码后的均匀码长靠近信源熵值而得名。熵编码多用可变字长编码(VLC,Variable Length Coding)实现。其基本原理是对信源中呈现概率大的符号赋予短码,对于呈现概率小的符号赋予长码,从而在统计上取得较短的均匀码长。可变字长编码通常有霍夫曼编码、算术编码、游程编码等。
- 静止预计和静止弥补 (重要)
静止预计和静止弥补是打消图像序列工夫方向相关性的无效伎俩。下面介绍的变换编码,熵编码都是在以一帧图像的根底上进行的,通过这些办法能够打消图像外部各像素在空间上的相关性。实际上图像信号除了空间上的相关性外,还有工夫上的相关性。例如对于像新闻联播这种背景静止,画面主体静止较小的数字视频,每一幅画面之间的区别很小,画面之间的相关性很大。对于这种状况咱们没有必要对每一帧图像独自进行编码,而是能够只对相邻视频帧中变动的局部进行编码,从而进一步减小数据量,这方面的工作是由静止预计和静止弥补来实现的。
-
a. 静止预计技术
将以后的输出图像宰割成若干彼此不相重叠的小图像子块,例如一帧图像为 1280*720, 首先将其以网格状模式分成 40*45 个尺寸为 16*16 彼此没有重叠的图像块,而后在前一图像或者后一图像某个搜寻窗口的范畴内为每一个图像块寻找一个与之最为类似的图像块,这个搜查的过程叫做静止预计。
b. 静止弥补
通过计算最类似的图像块与该图像块之间的地位信息,能够失去一个静止矢量。这样在编码的过程中就能够将以后图像中的块与参考图像静止矢量所指向的最类似的图像块相减,失去一个残差图像块,因为每个残差图像块中的每个像素值都很小,所以在压缩编码中能够取得更高的压缩比。
-
压缩数据类型
正因为静止预计与静止弥补,所以编码器将输出的每一帧图像依据参考图像分成了三种类型:I 帧,P 帧,B 帧。
- I 帧: 只应用本帧内的数据进行编码,在编码过程中不须要进行静止预计和静止弥补。
- P 帧: 在编码过程中应用后面的 I 帧或 P 帧作为参考图像的静止弥补,理论是对以后图像与参考图像的差值进行编码。
- B 帧: 在编码过程中应用后面的 I 帧或 P 帧和前面的 I 帧或 P 帧进行预测。由此可见,每个 P 帧利用一帧图像为参考图像。而 B 帧须要两帧图像作为参考。
理论利用中应用混合编码(变换编码 + 静止预计,静止弥补 + 熵编码)
-
编码器
通过数十年的倒退,编码器的性能曾经非常弱小,品种繁多,上面介绍最支流的一些编码器。
- H.264
与旧规范相比,它可能在更低带宽下提供优质视频(换言之,只有 MPEG-2,H.263 或 MPEG-4 第 2 局部的一半带宽或更少),也不减少太多设计复杂度使得无奈实现或实现老本过高。
- H.265/HEVC
高效率视频编码(High Efficiency Video Coding,简称 HEVC)是一种视频压缩规范,被视为是 ITU-T H.264/MPEG-4 AVC 规范的继任者。HEVC 被认为不仅晋升视频品质,同时也能达到 H.264/MPEG-4 AVC 两倍之压缩率(等同于同样画面质量下比特率缩小了 50%).
- VP8
VP8 是一个凋谢的视频压缩格局,最早由 On2 Technologies 开发,随后由 Google 公布。
- VP9
VP9 的开发从 2011 年第三季开始,指标是在同画质下,比 VP8 编码缩小 50% 的文件大小,另一个指标则是要在编码效率上超过 HEVC 编码。
3.4. 音频编码
-
原理
数字音频压缩编码在保障信号在听觉方面不产生失真的前提下,对音频数据信号进行尽可能的压缩。数字音频压缩编码采取去除声音中冗余成分的办法实现。冗余成分指的是音频中不能被人耳朵觉察的信号,它们对声音的音色,音调等信息没有任何帮忙。
冗余信号蕴含人耳听觉范围外的音频信号以及被掩蔽掉的音频信号灯。例如,人耳能觉察的声音频率为 20Hz~20kHz, 出此之外的其余频率人耳无奈觉察,都为冗余信号。此外,依据人耳听觉的生理和心理学景象。当一个强音信号与一个弱音信号同时存在时,弱音信号将被强音信号所掩蔽而听不见,这样弱音信号就能够视为冗余信号不必传送。这就是人耳听觉的掩蔽效应。
-
压缩编码方法
- 频谱掩蔽
一个频率的声音能量小于某个阈值之后,人耳就会听不到,这个阈值称为最小可闻阈。当有另外能量较大的声音呈现的时候,该声音频率左近的阈值会进步很多,即所谓的掩蔽效应
人耳对 2KHz~5KHz 的声音最敏感,而对频率太低或太高的声音信号都很机灵,当有一个频率为 0.2KHz、强度为 60dB 的声音呈现时,其左近的阈值进步了很多。
- 时域掩蔽
当强音信号和弱音信号同时呈现时,还存在时域掩蔽效应,前掩蔽,同时掩蔽,后掩蔽。前掩蔽是指人耳在听到强信号之前的短暂工夫内,曾经存在的弱信号会被掩蔽而听不到。
- 前掩蔽是指人耳在听到强信号之前的短暂工夫内,曾经存在的弱信号会被掩蔽而听不到
- 同时掩蔽是指当强信号与弱信号同时存在时,弱信号会被强信号所掩蔽而听不到。
- 后掩蔽是指当强信号隐没后,需通过较长的一段时间能力从新听见弱信号,称为后掩蔽。这些被掩蔽的弱信号即可视为冗余信号。
4. 封装编码数据
-
深入研究
- iOS 残缺推流过程
- iOS FFmpeg 环境搭建
4.1 定义
封装就是把编码器生成的音频, 视频同步以生成咱们肉眼可见, 耳朵可听并且看到的与听到的是同步的视频文件. 即封装后生成一个容器, 来寄存音频和视频流以及一些其余信息(比方字幕, metadata 等).
4.2 格局
-
AVI(.AVI):
- 长处是图像品质好。因为无损 AVI 能够保留 alpha 通道,常常被咱们应用
- 毛病太多,体积过于宏大,而且更加蹩脚的是压缩规范不对立,
- MOV(.MOV): 美国 Apple 公司开发的一种视频格式,默认的播放器是苹果的 QuickTime。
- MPEG(.MPG,.MPEG,MPE,.DAT,.VOB,.ASF,.3GP,.MP4):
- WMV(.WMV,.ASF)
- Real Video(.RM,.RMBV): 依据不同的网络传输速率制订出不同的压缩比率,从而实现在低速率的网络上进行影像数据实时传送和播放
- Flash Video(.FLV): 由 Adobe Flash 延长进去的的一种风行网络视频封装格局。随着视频网站的丰盛,这个格局曾经十分遍及。
4.3 将编码数据合成流
在挪动端咱们须要借助 FFmpeg 框架, 正如下面介绍的,FFmpeg 不仅能够做编解码, 还能够合成视频流, 像罕用的.flv 流,.asf 流.
最初, 合成好的数据即可用于写文件或者在网络上流传
补充: FFmpeg (必学框架)
FFmpeg 是一个开源框架,能够运行音频和视频多种格局的录影、转换、流性能,蕴含了 libavcodec: 这是一个用于多个我的项目中音频和视频的解码器库,以及 libavformat 一个音频与视频格式转换库。
目前反对 Linux ,Mac OS,Windows 三个支流的平台,也能够本人编译到 Android 或者 iOS 平台。如果是 Mac OS,能够通过 brew 装置 brew install ffmpeg –with-libvpx –with-libvorbis –with-ffplay
4.4. FLV 流简介
-
Overview
FLV 封装格局分析器。FLV 全称是 Flash Video,是互联网上应用极为宽泛的视频封装格局。像 Youtube,优酷这类视频网站,都应用 FLV 封装视频
FLV(Flash Video)是 Adobe 公司设计开发的一种风行的流媒体格式,因为其视频文件体积笨重、封装简略等特点,使其很适宜在互联网上进行利用。此外,FLV 能够应用 Flash Player 进行播放,而 Flash Player 插件曾经装置在全世界绝大部分浏览器上,这使得通过网页播放 FLV 视频非常容易。目前支流的视频网站如优酷网,土豆网,乐视网等网站无一例外地应用了 FLV 格局。FLV 封装格局的文件后缀通常为“.flv”。
-
构造
FLV 包含文件头(File Header)和文件体(File Body)两局部,其中文件体由一系列的 Tag 组成。因而一个 FLV 文件是如图 1 构造。
每个 Tag 后面还蕴含了 Previous Tag Size 字段,示意后面一个 Tag 的大小。Tag 的类型能够是视频、音频和 Script,每个 Tag 只能蕴含以上三种类型的数据中的一种。图 2 展现了 FLV 文件的具体构造。
5. 将数据通过 RTMP 协定传输
-
长处
- CDN 反对良好,支流的 CDN 厂商都反对
- 协定简略,在各平台上实现容易
-
毛病
- 基于 TCP,传输老本高,在弱网环境丢包率高的状况下问题显著
- 不反对浏览器推送
- Adobe 公有协定,Adobe 曾经不再更新
咱们推送进来的流媒体须要传输到观众,整个链路就是传输网络.
5.1. Overview
RTMP 协定是一个互联网 TCP/IP 五层体系结构中应用层的协定。RTMP 协定中根本的数据单元称为音讯(Message)。当 RTMP 协定在互联网中传输数据的时候,音讯会被拆分成更小的单元,称为音讯块(Chunk)。
5.2. 音讯
音讯是 RTMP 协定中根本的数据单元。不同品种的音讯蕴含不同的 Message Type ID,代表不同的性能。RTMP 协定中一共规定了十多种音讯类型,别离施展着不同的作用。
- 1- 7 的音讯用于协定管制,这些音讯个别是 RTMP 协定本身治理要应用的音讯,用户个别状况下无需操作其中的数据
- Message Type ID 为 8,9 的音讯别离用于传输音频和视频数据
- Message Type ID 为 15-20 的音讯用于发送 AMF 编码的命令,负责用户与服务器之间的交互,比方播放,暂停等等
- 音讯首部(Message Header)有四局部组成:标记音讯类型的 Message Type ID,标记音讯长度的 Payload Length,标识工夫戳的 Timestamp,标识音讯所属媒体流的 Stream ID
2. 音讯块
在网络上传输数据时,音讯须要被拆分成较小的数据块,才适宜在相应的网络环境上传输。RTMP 协定中规定,音讯在网络上传输时被拆分成音讯块(Chunk)。
音讯块首部(Chunk Header)有三局部组成:
- 用于标识本块的 Chunk Basic Header
- 用于标识本块负载所属音讯的 Chunk Message Header
- 以及当工夫戳溢出时才呈现的 Extended Timestamp
3. 音讯分块
在音讯被宰割成几个音讯块的过程中,音讯负载局部(Message Body)被宰割成大小固定的数据块(默认是 128 字节,最初一个数据块能够小于该固定长度),并在其首部加上音讯块首部(Chunk Header),就组成了相应的音讯块。音讯分块过程如图 5 所示,一个大小为 307 字节的音讯被宰割成 128 字节的音讯块(除了最初一个)。
RTMP 传输媒体数据的过程中,发送端首先把媒体数据封装成音讯,而后把音讯宰割成音讯块,最初将宰割后的音讯块通过 TCP 协定发送进来。接收端在通过 TCP 协定收到数据后,首先把音讯块重新组合成音讯,而后通过对音讯进行解封装解决就能够复原出媒体数据。
4.RTMP 中的逻辑构造
RTMP 协定规定,播放一个流媒体有两个前提步骤
- 第一步,建设一个网络连接(NetConnection)
- 第二步,建设一个网络流(NetStream)。
其中,网络连接代表服务器端应用程序和客户端之间根底的连通关系。网络流代表了发送多媒体数据的通道。服务器和客户端之间只能建设一个网络连接,然而基于该连贯能够创立很多网络流。他们的关系如图所示:
5. 连贯流程
播放一个 RTMP 协定的流媒体须要通过以下几个步骤:
- 握手
- 建设连贯
- 建设流
- 播放
RTMP 连贯都是以握手作为开始的。建设连贯阶段用于建设客户端与服务器之间的“网络连接”;建设流阶段用于建设客户端与服务器之间的“网络流”;播放阶段用于传输视音频数据。
6. 解析并解码视频流
-
深入研究
- iOS 残缺文件拉流解析解码同步渲染音视频流
- FFmpeg 解析视频数据
- iOS 利用 FFmpeg 实现视频硬解码
- iOS 利用 VideoToolbox 实现视频硬解码
- iOS 利用 FFmpeg 实现音频硬解码
- iOS 利用原生音频解码
到这里为止, 残缺的推流过程曾经介绍实现, 上面的过程即为逆向过程 - 拉流.
因为接收端拿到编码的视频流最终还是想将视频渲染到屏幕上, 将音频通过扬声器等输出设备播出, 所以接着下面的步骤, 接收端能够通过 RTMP 协定拿到视频流数据, 而后须要利用 FFmpeg parse 数据, 因为咱们须要将数据中的音频跟视频离开, 拆散出音视频数据后须要别离对它们做解码操作. 解码的视频即为 YUV/RGB 等格局, 解码后的音频即为线性 PCM 数据.
须要留神的是, 咱们解码进去的数据并不可能间接应用, 因为, 手机端如果想要播放解码进去的数据是须要将其放入特定的数据结构中, 在 iOS 中, 视频数据须要放入 CMSampleBufferRef 中, 而该数据结构又由 CMTime,CMVideoFormatDes,CMBlockBuffer 组成, 所以咱们须要提供它所须要的信息能力组成零碎可能播放的格局.
7. 音视频同步并播放
-
深入研究
- iOS 视频渲染
- AudioQueue 实现音频流实时播放实战
当咱们拿到解码后的音视频帧时, 首先要思考的问题就是如何同步音视频, 在网络失常的状况下是不须要做音视频同步操作, 因为咱们 parse 到的音视频数据里自身带着它们在采集时的工夫戳, 只有咱们在正当工夫内拿到音视频帧, 将它们别离送给屏幕与扬声器即可实现同步播放. 然而思考到网络稳定, 所以可能失落一些帧或提早后能力获取, 当这种状况呈现时就会造成声音视频不同步, 因而须要对音视频做同步解决.
咱们能够这样了解: 有一把尺子 一只蚂蚁(视频)跟着一个标杆(音频)走,标杆是匀速的 蚂蚁或快或慢,慢了你就抽它 让它跑起来,快了就拽它。这样音视频就能同步了。这里最大的问题就是音频是匀速的,视频是非线性的。
别离取得音视频的 PTS 后,咱们有三个抉择:视频同步音频(计算音视频 PTS 之差,来断定视频是否有提早)、音频同步视频(依据音视频 PTS 差值调整音频取的样值,即扭转音频缓冲区的大小)和音频视频同步内部时钟(同前一个),因为调整音频范畴过大,会造成令用户不适的尖利声,所以通常咱们抉择第一种。
咱们的策略是通过比拟前一个 PTS 和以后的 PTS 来预测下一帧的 PTS。与此同时,咱们须要同步视频到音频。咱们将创立一个 audio clock 作为外部变量来跟踪音频当初播放的工夫点,video thread 将用这个值来计算和判断视频是播快了还是播慢了。
当初假如咱们有一个 get\_audio\_clock 函数来返回咱们 audio clock,那当咱们拿到这个值,咱们怎么去解决音视频不同步的状况呢?如果只是简略的尝试跳到正确的 packet 来解决并不是一个很好的计划。咱们要做的是调整下一次刷新的机会:如果视频播慢了咱们就放慢刷新,如果视频播快了咱们就减慢刷新。既然咱们调整好了刷新工夫,接下来用 frame\_timer 跟设施的时钟做一下比拟。frame\_timer 会始终累加在播放过程中咱们计算的延时。换而言之,这个 frame\_timer 就是播放下一帧的应该对上的工夫点。咱们简略的在 frame\_timer 上累加新计算的 delay,而后和零碎工夫比拟,并用失去的值来作为工夫距离去刷新。
参考文章
- 雷神
- 阿里七牛云
本文转自 https://juejin.cn/post/6844903889007820813,如有侵权,请分割删除。
相干视频:
【2021 最新版】Android studio 装置教程 +Android(安卓)零基础教程视频(适宜 Android 0 根底,Android 初学入门)含音视频_哔哩哔哩_bilibili
Android 音视频学习——穿插编译与 CameraX 预览_哔哩哔哩_bilibili