FU-A分包方式,以及从RTP包里面得到H.264数据和AAC数据的方法
From: http://www.cnweblog.com/fly2700/archive/2012/02/23/319718.html
RFC3984是H.264的baseline码流在RTP方式下传输的规范,这里只讨论FU-A分包方式,以及从RTP包里面得到H.264数据和AAC数据的方法。
1、单个NAL包单元
12字节的RTP头后面的就是音视频数据,比较简单。一个封装单个NAL单元包到RTP的NAL单元流的RTP序号必须符合NAL单元的解码顺序。
2、FU-A的分片格式
数据比较大的H264视频包,被RTP分片发送。12字节的RTP头后面跟随的就是FU-A分片:
FU indicator有以下格式:
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+
FU指示字节的类型域 Type=28表示FU-A。。NRI域的值必须根据分片NAL单元的NRI域的值设置。
FU header的格式如下:
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|S|E|R| Type |
+---------------+
S: 1 bit
当设置成1,开始位指示分片NAL单元的开始。当跟随的FU荷载不是分片NAL单元荷载的开始,开始位设为0。
E: 1 bit
当设置成1, 结束位指示分片NAL单元的结束,即, 荷载的最后字节也是分片NAL单元的最后一个字节。当跟随的FU荷载不是分片NAL单元的最后分片,结束位设置为0。
R: 1 bit
保留位必须设置为0,接收者必须忽略该位。
Type: 5 bits
NAL单元荷载类型定义见下表
表1. 单元类型以及荷载结构总结
Type Packet Type name
---------------------------------------------------------
0 undefined -
1-23 NAL unit Single NAL unit packet per H.264
24 STAP-A Single-time aggregation packet
25 STAP-B Single-time aggregation packet
26 MTAP16 Multi-time aggregation packet
27 MTAP24 Multi-time aggregation packet
28 FU-A Fragmentation unit
29 FU-B Fragmentation unit
30-31 undefined -
3、拆包和解包
拆包:当编码器在编码时需要将原有一个NAL按照FU-A进行分片,原有的NAL的单元头与分片后的FU-A的单元头有如下关系:
原始的NAL头的前三位为FU indicator的前三位,原始的NAL头的后五位为FU header的后五位,FU indicator与FU header的剩余位数根据实际情况决定。
解包:当接收端收到FU-A的分片数据,需要将所有的分片包组合还原成原始的NAl包时,FU-A的单元头与还原后的NAL的关系如下:
还原后的NAL头的八位是由FU indicator的前三位加FU header的后五位组成,即:
nal_unit_type = (fu_indicator & 0xe0) | (fu_header & 0x1f)
4、代码实现
从RTP包里面得到H264视频数据的方法:
// 功能:解码RTP H.264视频
// 参数:1.RTP包缓冲地址 2.RTP包数据大小 3.H264输出地址 4.输出数据大小
// 返回:true:表示一帧结束 false:FU-A分片未结束或帧未结束
#define RTP_HEADLEN 12
bool UnpackRTPH264( void * bufIn, int len, void ** pBufOut, int * pOutLen)
{
* pOutLen = 0 ;
if (len < RTP_HEADLEN)
{
return false ;
}
unsigned char * src = (unsigned char * )bufIn + RTP_HEADLEN;
unsigned char head1 = * src; // 获取第一个字节
unsigned char head2 = * (src + 1 ); // 获取第二个字节
unsigned char nal = head1 & 0x1f ; // 获取FU indicator的类型域,
unsigned char flag = head2 & 0xe0 ; // 获取FU header的前三位,判断当前是分包的开始、中间或结束
unsigned char nal_fua = (head1 & 0xe0 ) | (head2 & 0x1f ); // FU_A nal
bool bFinishFrame = false ;
if (nal == 0x1c ) // 判断NAL的类型为0x1c=28,说明是FU-A分片
{ // fu-a
if (flag == 0x80 ) // 开始
{
* pBufOut = src - 3 ;
* (( int * )( * pBufOut)) = 0x01000000 ; // zyf:大模式会有问题
* (( char * )( * pBufOut) + 4 ) = nal_fua;
* pOutLen = len - RTP_HEADLEN + 3 ;
}
else if (flag == 0x40 ) // 结束
{
* pBufOut = src + 2 ;
* pOutLen = len - RTP_HEADLEN - 2 ;
}
else // 中间
{
* pBufOut = src + 2 ;
* pOutLen = len - RTP_HEADLEN - 2 ;
}
}
else // 单包数据
{
* pBufOut = src - 4 ;
* (( int * )( * pBufOut)) = 0x01000000 ; // zyf:大模式会有问题
* pOutLen = len - RTP_HEADLEN + 4 ;
}
unsigned char * bufTmp = (unsigned char * )bufIn;
if (bufTmp[ 1 ] & 0x80 )
{
bFinishFrame = true ; // rtp mark
}
else
{
bFinishFrame = false ;
}
return bFinishFrame;
}
从RTP包里面得到AAC音频数据的方法:
//功能:解RTP AAC音频包,声道和采样频率必须知道。
//参数:1.RTP包缓冲地址 2.RTP包数据大小 3.H264输出地址 4.输出数据大小
//返回:true:表示一帧结束 false:帧未结束 一般AAC音频包比较小,没有分片。
bool UnpackRTPAAC(void * bufIn, int recvLen, void** pBufOut, int* pOutLen)
{
unsigned char* bufRecv = (unsigned char*)bufIn;
//char strFileName[20];
unsigned char ADTS[] = {0xFF, 0xF1, 0x00, 0x00, 0x00, 0x00, 0xFC};
int audioSamprate = 32000;//音频采样率
int audioChannel = 2;//音频声道 1或2
int audioBit = 16;//16位 固定
switch(audioSamprate)
{
case 16000:
ADTS[2] = 0x60;
break;
case 32000:
ADTS[2] = 0x54;
break;
case 44100:
ADTS[2] = 0x50;
break;
case 48000:
ADTS[2] = 0x4C;
break;
case 96000:
ADTS[2] = 0x40;
break;
default:
break;
}
ADTS[3] = (audioChannel==2)?0x80:0x40;
int len = recvLen - 16 + 7;
len <<= 5;//8bit * 2 - 11 = 5(headerSize 11bit)
len |= 0x1F;//5 bit 1
ADTS[4] = len>>8;
ADTS[5] = len & 0xFF;
*pBufOut = (char*)bufIn+16-7;
memcpy(*pBufOut, ADTS, sizeof(ADTS));
*pOutLen = recvLen - 16 + 7;
unsigned char* bufTmp = (unsigned char*)bufIn;
bool bFinishFrame = false;
if (bufTmp[1] & 0x80)
{
//DebugTrace::D("Marker");
bFinishFrame = true;
}
else
{
bFinishFrame = false;
}
return true;
}
FU-A分包方式,以及从RTP包里面得到H.264数据和AAC数据的方法相关推荐
- Wireshark将UDP包解析成H.264
音视频媒体 Wireshark将UDP包解析成H.264 Wireshark将UDP包解析成H.264 音视频媒体 前言 前言 话不多说,视频会议码流传输用的UDP协议,其网络封装为eth:ether ...
- RTP Payload Format for H.264 Video
H.264 RTP协议的封装格式rfc3984 英文原版:http://tools.ietf.org/html/rfc3984 部分中文翻译: H.264 视频 RTP 负载格式 1. 网络抽象层单 ...
- 国标平台视频流抓取及rtp包解析
最近遇到国标平台无法播放视频流的问题.需要检查视频接收端和播放端视频的收包和发包是否正常.但是只看pcap文件不是很直观,所以将pcap文件中的rtp包解析出来,用播放器将视频播放出来,以更直观的判断 ...
- 基于RTP协议的H.264视频传输系统:实现
实现的原理:基于RTP协议的H.264视频传输系统:原理 相关文章: [1]RTP协议分析 [2]jrtplib简介 [3]Qt调用jrtplib实现单播.多播和广播 [4]RTP 有效负载(载荷)类 ...
- (转载)H.264码流的RTP封包说明
H.264的NALU,RTP封包说明(转自牛人) 2010-06-30 16:28 H.264 RTP payload 格式 H.264 视频 RTP 负载格式 1. 网络抽象层单元类型 (NALU) ...
- H.264视频的RTP有效负载格式 (RFC-3984)
RFC文档链接 本备忘录的状态 略 摘要 本备忘录描述了ITU-T建议的H.264视频编解码器和技术上相同的ISO/IEC国际标准14496-10视频编解码器的RTP有效载荷格式.RTP有效载荷格式允 ...
- H.264的RTP封装
1. 概括 RTP(Real-time Transport Protocol,实时传输协议)是一个网络传输协议.它为数据提供了具有实时特征的端对端传送服务. 随着信息化的发展,人们对于某些信息,更看重 ...
- 音视频传输:RTP协议详解和H.264打包方案
问题背景: 前面讲解了PS.TS.FLV这三种媒体封装格式,现在新开一个系列讲解下传输协议,这里面会包含RTP.RTSP.HLS.RTMP等.当然最复杂的封装格式MP4在准备中,后面会把封装格式这个系 ...
- RTP协议介绍以及C语言实现具有发送H.264视频功能的RTP服务器
RTP封装H.264视频规范以及C语言实现 以前上学时间做嵌入式开发板Hi3516A的流媒体项目,现在又突然想起来,不想学过就忘了浪费了,所以又自己实现了一遍读取本地视频文件发送RTP视频流的程序,算 ...
最新文章
- javascript:使用document.getElementById读取数据为空分析
- 力扣交替打印FooBar
- [MSSQL]也说SQL中显示星期几函数
- 今年双12全天 邮政、快递企业共揽收邮(快)件达4.6亿件
- oracle列转行wm_concat,Oracle列转行函数wm_concat版本不兼容解决方案
- python 中的运算符重载
- 2019-05-22 Java学习日记 day12
- Matlab2021a安装教程
- Holo 使用场景说明
- IPC$局域网入侵详解
- 台式计算机显示不了无线网络,我是台式电脑,插上无线网卡怎么我的链接里不显示无线...
- DRILLNET 2.0------第十三章 尾管固井扭矩/摩阻模型
- 服务器开机黑屏无法进入系统,电脑黑屏无法进入系统怎么办?
- Android Timer和TimerTask解决IllegalStateException:Task already scheduled or cancelled
- 生活照无处不在的细节决定着你的命运
- 冒泡排序算法(bubbling sort)
- 计算机专业课考研试卷谁出卷,考研试卷谁来改?揭开考研阅卷流程内幕
- 基于kettle的数据集成平台(三)
- LeetCode Singer Number
- vue中echarts初次加载图很小的问题
热门文章
- IBM副总裁自述的数据中心简化经验
- Memory-Associated Differential Learning论文及代码解读
- leetcode 922. 按奇偶排序数组 II(双指针)
- leetcode 1024. 视频拼接(dp/贪心)
- leetcode632. 最小区间(堆+多指针)
- 乐高ev3涉及到的一些赛事_使您成为英雄的前五名开发者技能(提示:涉及LEGO)
- [pytorch] Pytorch入门
- POJ1182--带权并查集
- hdu1466(dp)
- Qt编程'hello world