音频编码实战

随着5G时代的到来,音视频领域将会大放异彩。

5G让所有人兴奋,用户期待,因为5G网络更快更稳定延迟更低。运营商和上下游产业也期待,大家都想在5G时代分一杯羹。

近几年抖音快手B站等App的火热,已经说明问题了。随着WiFi设施的全面普及,流量费用的进一步下降,使得我们随时随地刷视频成为了可能。回想起我大学时代,那个时候流量很贵,贵到什么程度呢?1M流量要10块钱!大家想一想,1M流量10块钱,1G流量1万块钱,你还敢用4G刷视频么?4G时代,大家刷短视频,5G时代,大家刷长视频。基于这个判断,音视频相关技术是未来几年的热点,除了抖音快手,新的现象级客户端有可能会出现。

作为移动开发人员,如何跟上热点学习音视频技术呢?

FFmpeg流程 

从本地文件读取PCM数据进行AAC格式编码,然后将编码后的AAC数据存储到本地文件。

示例的流程如下所示。

关键函数说明:

avcodec_find_encoder:根据指定的AVCodecID查找注册的编码器。

avcodec_alloc_context3:为AVCodecContext分配内存。

avcodec_open2:打开编码器。

avcodec_send_frame:将AVFrame非压缩数据给编码器。

avcodec_receive_packet:获取到编码后的AVPacket数据,收到的packet需要自己释放内存。

av_frame_get_buffer: 为音频或视频帧分配新的buffer。在调用这个函数之前,必须在AVFame上设

置好以下属性:format(视频为像素格式,音频为样本格式)、nb_samples(样本个数,针对音频)、

channel_layout(通道类型,针对音频)、width/height(宽高,针对视频)。

av_frame_make_writable:确保AVFrame是可写的,使用av_frame_make_writable()的问题是,在

最坏的情况下,它会在您使用encode再次更改整个输入frame之前复制它. 如果frame不可写,

av_frame_make_writable()将分配新的缓冲区,并复制这个输入input frame数据,避免和编码器需

要缓存该帧时造成冲突。

av_samples_fill_arrays 填充音频帧


对于 flush encoder的操作:

编码器通常的冲洗方法:调用一次 avcodec_send_frame(NULL)(返回成功),然后不停调用

avcodec_receive_packet() 直到其返回 AVERROR_EOF,取出所有缓存帧,

2avcodec_receive_packet() 返回 AVERROR_EOF 这一次是没有有效数据的,仅仅获取到一

个结束标志

PCM样本格式

PCM(Pulse Code Modulation,脉冲编码调制)音频数据是未经压缩的音频采样数据裸流,它是由模拟信

号经过采样、量化、编码转换成的标准数字音频数据。

描述PCM数据的6个参数:

1. Sample Rate : 采样频率。8kHz(电话)、44.1kHz(CD)、48kHz(DVD)。

2. Sample Size : 量化位数。通常该值为16-bit。

3. Number of Channels : 通道个数。常用的音频有立体声(stereo)和单声道(mono)两种类型,立体声包

含左声道和右声道。另外还有环绕立体声等其它不太常用的类型。

4. Sign : 表示样本数据是否是有符号位,比如用一字节表示的样本数据,有符号的话表示范围为-128 ~

127,无符号是0 ~ 255。有符号位16bits数据取值范围为-32768~32767。

5. Byte Ordering : 字节序。字节序是little-endian还是big-endian。通常均为little-endian。字节序说

明见第4节。

6. Integer Or Floating Point : 整形或浮点型。大多数格式的PCM样本数据使用整形表示,而在一些对

精度要求高的应用方面,使用浮点类型表示PCM样本数据(浮点数 float值域为 [-1.0, 1.0])。

推荐的PCM数据播放工具:

ffplay, 使用示例如下:

1 //播放格式为f32le,双声道,采样频率48000Hz的PCM数据

2 ffplay -f f32le -ac 2 -ar 48000 pcm_audio

Audacity:一款免费开源的跨平台音频处理软件。

Adobe Auditon。导入原始数据,打开的时候需要选择采样率、格式和字节序。

FFmpeg支持的PCM数据格式

使⽤ffmpeg -formats命令,获取ffmpeg支持的音视频格式,其中我们可以找到支持的PCM格式。

1 DE alaw PCM A-law

2 DE f32be PCM 32-bit floating-point big-endian

3 DE f32le PCM 32-bit floating-point little-endian

4 DE f64be PCM 64-bit floating-point big-endian

5 DE f64le PCM 64-bit floating-point little-endian

6 DE mulaw PCM mu-law

37 DE s16be PCM signed 16-bit big-endian

8 DE s16le PCM signed 16-bit little-endian

9 DE s24be PCM signed 24-bit big-endian

10 DE s24le PCM signed 24-bit little-endian

11 DE s32be PCM signed 32-bit big-endian

12 DE s32le PCM signed 32-bit little-endian

13 DE s8 PCM signed 8-bit

14 DE u16be PCM unsigned 16-bit big-endian

15 DE u16le PCM unsigned 16-bit little-endian

16 DE u24be PCM unsigned 24-bit big-endian

17 DE u24le PCM unsigned 24-bit little-endian

18 DE u32be PCM unsigned 32-bit big-endian

19 DE u32le PCM unsigned 32-bit little-endian

20 DE u8 PCM unsigned 8-bit

s是有符号,u是无符号,f是浮点数。

be是大端,le是小端。

FFmpeg中Packed和Planar的PCM数据区别

FFmpeg中音视频数据基本上都有Packed和Planar两种存储存式,对于双声道音频来说,

Packed方式为两个声道的数据交错存储;Planar方式为两个声道分开存储。假设一个L/R为⼀

个采样点,数据存储的方式如下所示:

Packed: L R L R L R L R

Planar: L L L L ... R R R R...

packed格式

1 AV_SAMPLE_FMT_U8, ///< unsigned 8 bits

2 AV_SAMPLE_FMT_S16, ///< signed 16 bits

3 AV_SAMPLE_FMT_S32, ///< signed 32 bits

4 AV_SAMPLE_FMT_FLT, ///< float

5 AV_SAMPLE_FMT_DBL, ///< double

只能保存在AVFrame的uint8_t *data[0];

音频保持格式如下:

LRLRLR...

planar为FFmpeg内部存储音频使的采样格式,所有的Planar格式后都有字P标识。

1 AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar

2 AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar

3 AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar

4 AV_SAMPLE_FMT_FLTP, ///< float, planar

5 AV_SAMPLE_FMT_DBLP, ///< double, planar

6 AV_SAMPLE_FMT_S64, ///< signed 64 bits

7 AV_SAMPLE_FMT_S64P, ///< signed 64 bits, planar

plane 0: LLLLLLLLLLLLLLLLLLLLLLLLLL...

plane 1: RRRRRRRRRRRRRRRRRRRR....

plane 0对于uint8_t *data[0];

plane 1对于uint8_t *data[1];

FFmpeg默认的AAC编码器不⽀持AV_SAMPLE_FMT_S16格式的编码,只支持

AV_SAMPLE_FMT_FLTP,这种格式是按平面存储,样点是float类型,所谓平面也就是

每个声道单独存储.如左声道存储到data[0]中,右声道存储到data[1]中。

FFmpeg音频解码后和编码前的数据是存放在AVFrame结构中的。

Packed格式,frame.data[0]或frame.extended_data[0]包含所有的音频数据中。

Planar格式,frame.data[i]或者frame.extended_data[i]表示第i个声道的数据(假设声道0是第一⼀

个), AVFrame.data数组大小固定为8,如果声道数超过8,需要从frame.extended_data获取声道数

据。

补充说明

Planar模式是ffmpeg内部存储模式,我们实际使用 的音频文件都是Packed模式的。

FFmpeg解码不同格式的音频输出的音频采样格式不是一样。测试发现,其中AAC解码输出的数据为浮

点型的 AV_SAMPLE_FMT_FLTP 格式,MP3解码输出的数据为 AV_SAMPLE_FMT_S16P 格式(使

用的mp3文件为16位深)。具体采样格式可以查看解码后的AVFrame中的format成员或编解码器的

AVCodecContext中的sample_fmt成员。

Planar或者Packed模式直接影响到保存文件时写文件的操作,操作数据的时候一定要先检测音频采样

格式。

PCM字节序

谈到字节序的问题,必然牵涉到两大CPU派系。那就是Motorola的PowerPC系列CPU和Intel的x86系列

CPU。PowerPC系列采用big endian方式存储数据,而x86系列则采用little endian方式存储数据。那么

究竟什么是big endian,什么又是little endian?

big endian是指低地址存放最高有效字节(MSB,Most Significant Bit),而little endian则是低地址

存放最低有效字节(LSB,Least Significant Bit)。

下图像加以说明。比如数字0x12345678在两种不同字节序CPU中的存储顺序如下所示:

Big Endian

低地址 ⾼高地址

---------------------------------------------------------------------------

-->

| 12 | 34 | 56 | 78 |

Little Endian

低地址 ⾼高地址

---------------------------------------------------------------------------

-->

| 78 | 56 | 34 | 12 |

所有网络协议都是采用big endian的方式来传输数据的。所以也把big endian方式称之为网络字节序。当

两台采用不同字节序的主机通信时,在发送数据之前都必须经过字节序的转换成为往络字节序后再进行传

输。

更多音视频学习,关注

个人介绍领取 音视频资料

音视频课程学习大纲

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 目录 什么是PCM? PCM数据格式 FFmpeg支持的PCM数据格式 FFmpeg中Packed和Planar的...
    smallest_one阅读 46,423评论 1 32
  • 一.声音的相关概念 声音是介质振动在听觉系统中产生的反应。声音总可以被分解为不同频率不同强度正弦波的叠加(傅里叶变...
    泥孩儿0107阅读 4,282评论 6 9
  • 声波 这里为啥讲到了声波,讲到了我们的中学物理上的知识,因为我想大家能从根本理解后面音频编码的各种参数以及原因。当...
    第八区阅读 8,640评论 0 31
  • //音频编码 JNIEXPORT void JNICALL Java_com_tz_dream_ffmpeg_an...
    Jackey_song阅读 1,471评论 0 1
  • 本篇博客在雷神的结构体介绍基础上按自己的喜好整理的 后面根据自己工作中所需有所增改 AVStream 存储每一个视...
    石丘阅读 2,458评论 1 10