开发者社区> double2li> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

使用librtmp进行H264与AAC直播

简介: libx264版本是128libfaac版本是1.28 1、帧的划分 1.1 H.264帧 对于H.264而言每帧的界定符为00 00 00 01或者00 00 01。 比如下面的h264文件片断这就包函三帧数据 00 00 00 01 67 42 C0 28 DA 01 E0 08 9F...
+关注继续查看

libx264版本是128
libfaac版本是1.28

1、帧的划分

1.1 H.264帧

对于H.264而言每帧的界定符为00 00 00 01或者00 00 01。

比如下面的h264文件片断这就包函三帧数据

00 00 00 01 67 42 C0 28 DA 01 E0 08 9F 96 10 00
00 03 00 10 00 00 03 01 48 F1 83 2A 00 00 00 01
68 CE 3C 80 00 00 01 06 05 FF FF 5D DC 45 E9 BD
E6 D9 48 B7 96 2C D8 20 D9 23 EE EF …

第一帧是00 00 00 01 67 42 C0 28 DA 01 E0 08 9F 96 10 00 00 03 00 10 00 00 03 01 48 F1 83 2A
第二帧是00 00 00 01 68 CE 3C 80
第三帧是00 00 01 06 05 FF FF 5D DC 45 E9 BD E6 D9 48 B7 96 2C D8 20 D9 23 EE EF ..

帧类型有:
NAL_SLICE = 1
NAL_SLICE_DPA = 2
NAL_SLICE_DPB = 3
NAL_SLICE_DPC = 4
NAL_SLICE_IDR = 5
NAL_SEI = 6
NAL_SPS = 7
NAL_PPS = 8
NAL_AUD = 9
NAL_FILLER = 12,

我们发送RTMP数据时只需要知道四种帧类型,其它类型我都把它规类成非关键帧。
分别是
NAL_SPS(7), sps帧
NAL_PPS(8), pps帧
NAL_SLICE_IDR(5), 关键帧
NAL_SLICE(1) 非关键帧

帧类型的方式判断为界面符后首字节的低四位。
第一帧的帧类型为: 0x67 & 0x1F = 7,这是一个SPS帧
第二帧的帧类型为: 0x68 & 0x1F = 8,这是一个PPS帧
第三帧的帧类型为: 0x06 & 0x1F = 6,这是一个SEI帧

以上是我们利用帧界定符划分帧,并可以判断每一个帧的类型。

注意:如果是压缩图像成H264帧,我们就可不必进行帧界定,因为每一次压缩的输出都明确了该帧的大小(包括界定符),每一次的压缩的结果可能包函多帧。一会具体讨论。

1.2 AAC帧

对于AAC帧它的界定符是FF F1

这里我就不举例了,可通过查看AAC的二进制文件可以看到如下的帧结构。
FF F1 50 80 24 9F FD DE 04 00 00 6C 69 62 66 61 61 63 20 31 2E 32 38 00 00 42 15 95 ..

注意:那么对于AAC而言加上界定符每一帧的前7字节是帧的描述信息,也就是说AAC的祼数据是除去前面的7个字节的,在发送RTMP时,我们要去掉这7个字节。同样,如果我们是一边压缩一边发送RTMP,我们同样不需要界定帧,因为libfaac每次压缩完成的输出就是一个完整的帧数据,我们只需要将该帧打包发送即可。

综合上面的所述,如果我们只是一边压缩一边将压缩结果发送到RTMP服务器,那我们就可以不用对帧进行界定,如果我们是发送H264与AAC文件,那我们就要对帧进行界定。

2.视频与音频的编码信息

如果我们只是简答的将压缩数据打包发送给RTMP服务器,那么RTMP服务器是不可以对数据进行解码和播放的,在这之前我们要将音视频的视频的编码信息发送给RTMP服务器。很多人可能苦于寻找下面的三个编码参数而不得要领。其实要想得到也是很简单的。

2.1 (H264)SPS

对于H264而言,SPS就是编码后的第一帧。如果是读取H264文件,就是第一个帧界定符与第二帧界定符中间的数据长度是4。

2.2 (H264)PPS

对于H264而言,PPS就是编码后的第二帧。如果是读取H264文件,就是第二个帧界定符与第三帧界定符中间的数据,长度不固定。

2.3 (AAC)AudioDecoderSpecificInfo

这个长度为2个字节,可以通过计算或者调用函数获取。
建议通过调用faacEncGetDecoderSpecificInfo(fh,&spec,&len);获取。
一般情况双声道44100采样下,该值是0x1210

3.librtmp的使用

 

 

 

 

4.包类型

4.1 H.264编码信息帧

H.264的编码信息帧是发送给RTMP服务器称为AVC sequence header,RTMP服务器只有收到AVC sequence header中的sps,pps才能解析后续发送的H264帧。

sps与pps怎么获取到呢?

在前面已经说过,H264的第1帧是sps帧,pps是第2帧。

我们在编码时会调用如下接口

我完全可以不用知道sps,pps的具体意义:)

4.2 H.264关键帧

4.3 H.264非关键帧

 

这里要说明一下:

在libx264中每一次调用x264_encoder_encode输出了n个帧,我们要从这n个帧里找出sps和pps,剩下的分次全部发送nal,sps与pps的帧界定符都是00 00 00 01,而普通帧可能是00 00 00 01也有可能00 00 01。
比如说x264_encoder_encode输出了6帧。
分别是 sps帧,pps帧,关键帧,非关键帧,非关键帧,非关键帧。
发送结果应该是,sps,pps合成为一帧调用发送函数,剩下4帧,除去每个nal的界定符,分别发送每一个nal。

如果x264_encoder_encode里没有sps帧与pps帧,则结果除去第一帧的界定符所以帧做为一个整体调用发送函数,它们的类型是由第一帧类型决定。

另外,H264的流的第1帧一定是sps帧(包含帧界定符为8个字节),第2帧一定是pps帧。

4.4 AAC编码信息

 

对于音频解码参数AAC sequence header是通过

下面是获得AAC sequence header的方法

另外如果你是打开aac文件进行发送,那么你可以尝试自己计算这个值,其实也很简单,打开faac源代码看一下faacEncGetDecoderSpecificInfo的实现,也就是几个移位的事:)。
对于一般情况44100Hz双声道,这个值是0x1210,偷懒就是直接用这个值吧。

4.5 AAC普通数据

如前面所述,发送AAC的普通数据要改造一下,因为AAC的前7个字节(包括帧界定符)对于RTMP服务器来说是无用的。

至此所有流程均结束了。
要注意的几件事:
libRTMP多线程发送有时候可能会出现问题,不知道是什么问题,最好改成队列发送。
将填充好的packet通过消息或者其它方式发送给其它线程,发送线程统一发送即可。

5.参考文档

《Video File Format Specification Version 10》 http://www.adobe.com/content/dam/Adobe/en/devnet/flv/pdfs/video_file_format_spec_v10.pdf
《H264视频通过RTMP直播》 http://blog.csdn.net/firehood_/article/details/8783589
rtmpdump-2.3

niesongsong
nie950 at gmail.com

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
SAP Cloud for Customer Rule Editor的使用方法和底层工作原理
SAP Cloud for Customer Rule Editor的使用方法和底层工作原理
62 0
下一代低延时直播CDN:HLS、RTMP 与UDP +WebRTC
在上月落幕帷幕的多媒体领域技术盛会——LiveVideoStackCon2018音视频技术大会上,阿里云的高级技术专家李刚进行了《下一代低延时的直播CDN》技术分享。
6785 0
RTP 打包H264与AAC
static int h264_parse(Track *tr, uint8_t *data, size_t len)   {       h264_priv *priv = tr->private_data;   //    double nal_time; // see page 9 and 7.
1816 0
【H.264/AVC视频编解码技术详解】四. 常见H.264视频编解码器(X264和JM)及参考软件JM的下载与编解码
《H.264/AVC视频编解码技术详解》视频教程已经在“CSDN学院”上线,视频中详述了H.264的背景、标准协议和实现,并通过一个实战工程的形式对H.
2160 0
嵌入式 H264视频通过RTMP直播
前面的文章中提到了通过RTSP(Real Time Streaming Protocol)的方式来实现视频的直播,但RTSP方式的一个弊端是如果需要支持客户端通过网页来访问,就需要在在页面中嵌入一个ActiveX控件,而ActiveX一般都需要签名才能正常使用,否则用户在使用时还需要更改浏览器设置,并且ActiveX还只支持IE内核的浏览器,Chrome、FireFox需要IE插件才能运行,因此会特别影响用户体验。
1309 0
H.264视频的RTP荷载格式
Status of This Memo   This document specifies an Internet standards track protocol for the   Internet community, and requests discussion and suggestions for   improvements.
1542 0
CBitmap的使用
<div class="bct fc05 fc11 nbw-blog ztag"> <br><p style="TEXT-INDENT: 2em;">MFC提供了位图处理的基础类CBitmap,可以完成位图(bmp图像)的创建、图像数据的获取等功能。虽然功能比较少,但是在对位图进行一些简单的处理时,CBitmap类还是可以胜任的。很多人可能会采用一些现成的CDib类进行位图的读取与处理,我觉得
1468 0
+关注
double2li
一个在IT行业摸爬滚打的老司机
文章
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载