文档章节

H.264中NALU、RBSP、SODB的关系 (弄清码流结构)

zhangyujsj
 zhangyujsj
发布于 2015/01/05 17:15
字数 631
阅读 99
收藏 1

 NALU:Coded H.264 data is stored or transmitted as a series of packets known as NetworkAbstraction LayerUnits. (NALU单元)

      RBSP :A NALU contains a Raw Byte Sequence Payload, a sequence of bytes containingsyntax elements.(原始数据字节流)

      SODB:String Of Data Bits (原始数据比特流, 长度不一定是8的倍数,故需要补齐)

 

      逻辑关系:

 

                                                  SODB  + RBSP trailing bits    =  RBSP

                                                       NAL header(1 byte)      +      RBSP   = NALU

     Start Code Prefix(3 bytes)  +   NALU  +  Start Code Prefix(3 bytes)  +   NALU   + ...+  = H.264BitsStream

 

     说明:

    1. SODB即编码形成的真实码流,为了使一个RBSP为整字节数,需要加trailing bits, 具体加的方法可以看JM8.6中的SODBtoRBSP函数.

[cpp]   view plain copy
  1. void SODBtoRBSP(Bitstream *currStream)  
  2. {  
  3.   currStream->byte_buf <<= 1;  
  4.   currStream->byte_buf |= 1;  
  5.   currStream->bits_to_go--;  
  6.   currStream->byte_buf <<= currStream->bits_to_go;  
  7.   currStream->streamBuffer[currStream->byte_pos++] = currStream->byte_buf;  
  8.   currStream->bits_to_go = 8;  
  9.   currStream->byte_buf = 0;  
  10. }  


 

      2. NALU header为一个字节,这8个比特分别对应forbidden_zero_bit, nal_ref_idc, nal_unit_type. NALU的body其实就是RBSP. 由RBSP转NALU是由RBSPtoNALU函数来实现的.

[cpp]   view plain copy
  1. typedef struct   
  2. {  
  3.   int startcodeprefix_len;      //! 4 for parameter sets and first slice in picture, 3 for everything else (suggested)  
  4.   unsigned len;                 //! Length of the NAL unit (Excluding the start code, which does not belong to the NALU)  
  5.   unsigned max_size;            //! Nal Unit Buffer size  
  6.   int nal_unit_type;            //! NALU_TYPE_xxxx  
  7.   int nal_reference_idc;        //! NALU_PRIORITY_xxxx  
  8.   int forbidden_bit;            //! should be always FALSE  
  9.   byte *buf;        //! conjtains the first byte followed by the EBSP  
  10. } NALU_t;  
[cpp]   view plain copy
  1. int RBSPtoNALU (char *rbsp, NALU_t *nalu, int rbsp_size, int nal_unit_type, int nal_reference_idc,   
  2.                 int min_num_bytes, int UseAnnexbLongStartcode)  
  3. {  
  4.   int len;  
  5.   
  6.   // 断言,以后要学会用assert进行断言,很重要滴.  
  7.   assert (nalu != NULL);  
  8.   assert (nal_reference_idc <=3 && nal_reference_idc >=0);  
  9.   assert (nal_unit_type > 0 && nal_unit_type <= 10);  
  10.   assert (rbsp_size < MAXRBSPSIZE);  
  11.   
  12.   // 下面这个是必须的,所以不需要通过参数传进来  
  13.   nalu->forbidden_bit = 0;  
  14.   // 下面两个通过参数传进来  
  15.   nalu->nal_reference_idc = nal_reference_idc;  
  16.   nalu->nal_unit_type = nal_unit_type;  
  17.   
  18.   // 判断是否在Start Code Prefix前面加Ox00  
  19.   nalu->startcodeprefix_len = UseAnnexbLongStartcode?4:3;  
  20.     
  21.   // 对nalu->buf[i]进行赋值  
  22.   nalu->buf[0] =  
  23.     nalu->forbidden_bit << 7      |  
  24.     nalu->nal_reference_idc << 5  |  
  25.     nalu->nal_unit_type;  
  26.   memcpy (&nalu->buf[1], rbsp, rbsp_size);  
  27.   
  28. // printf ("First Byte %x\n", nalu->buf[0]);  
  29. // printf ("RBSPtoNALU: Before: NALU len %d\t RBSP %x %x %x %x\n", rbsp_size, (unsigned) nalu->buf[1], (unsigned) nalu->buf[2], (unsigned) nalu->buf[3], (unsigned) nalu->buf[4]);  
  30.   
  31.   len = 1 + RBSPtoEBSP (&nalu->buf[1], 0, rbsp_size, min_num_bytes);  
  32.   
  33. // printf ("RBSPtoNALU: After : NALU len %d\t EBSP %x %x %x %x\n", rbsp_size, (unsigned) nalu->buf[1], (unsigned) nalu->buf[2], (unsigned) nalu->buf[3], (unsigned) nalu->buf[4]);  
  34. // printf ("len %d\n\n", len);  
  35.   nalu->len = len;  
  36.   
  37.   return len;  
  38. }  

 

      3. Start Code Prefix为3个字节. 但是,为了寻址方便,要求数据流在长度上对齐,因此H.264建议在Start Code Prefix前面加若干个0.    

      4. 为了简便起见,上面的逻辑关系图没有考虑"防止竞争"机制.

 

     编码foreman_part_qcif.yuv的第一帧,码流如下: (对照trace_enc.txt分析即可,由于码流太多,篇幅有限,故不一一分析)

0000000000000000000000000000000101100111010000100000000000011110111100010110000101100010011000100000000000000000000000000

本文转载自:http://blog.csdn.net/stpeace/article/details/8221945

下一篇: RPC编程
zhangyujsj
粉丝 24
博文 358
码字总数 224241
作品 0
广州
私信 提问
视频的「编解码」与「传输」的那些事儿

本文来自作者 Owen Chan 在 GitChat 上分享「关于视频的编解码与传输技术,你想知道的都在这里」,「阅读原文」查看交流实录 「文末高能」 编辑 | 泰龙 一、如何编译 FFmpag 准备工作 下载 ...

gitchat
2017/11/24
0
0
H.264码流结构 (H.264 Data Structure)

简书地址 : H.264 Data Structure 博客地址 : H.264 Data Structure 掘金地址 : H.264 Data Structure Why ? 相信在你的电脑里,一定存有一些已经下载好的视频文件,如果你硬说没有,那我相信...

__小___东邪___
2017/12/10
0
0
H264—帧,片,参数集,NALU等概念

h264是一个编码压缩的格式,可以使用x264库进行编码,源码开放,可下载编译使用。 ----------------------------------------------------------------------------------------------------...

ssllkkyyaa
2018/04/23
0
0
(推荐阅读)H264, H265硬件编解码基础及码流分析

需求 在移动端做音视频开发不同于基本的UI业务逻辑工作,音视频开发需要你懂得音视频中一些基本概念,针对编解码而言,我们必须提前懂得编解码器的一些特性,码流的结构,码流中一些重要信息如sps...

小东邪啊
05/26
0
0
视音频数据处理入门:H.264视频码流解析

===================================================== 视音频数据处理入门系列文章: 视音频数据处理入门:RGB、YUV像素数据处理 视音频数据处理入门:PCM音频采样数据处理 视音频数据处理...

leixiaohua1020
2016/01/31
0
0

没有更多内容

加载失败,请刷新页面

加载更多

关于AsyncTask的onPostExcute方法是否会在Activity重建过程中调用的问题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/XG1057415595/article/details/86774575 假设下面一种情况...

shzwork
今天
6
0
object 类中有哪些方法?

getClass(): 获取运行时类的对象 equals():判断其他对象是否与此对象相等 hashcode():返回该对象的哈希码值 toString():返回该对象的字符串表示 clone(): 创建并返此对象的一个副本 wait...

happywe
今天
6
0
Docker容器实战(七) - 容器中进程视野下的文件系统

前两文中,讲了Linux容器最基础的两种技术 Namespace 作用是“隔离”,它让应用进程只能看到该Namespace内的“世界” Cgroups 作用是“限制”,它给这个“世界”围上了一圈看不见的墙 这么一...

JavaEdge
今天
8
0
文件访问和共享的方法介绍

在上一篇文章中,你了解到文件有三个不同的权限集。拥有该文件的用户有一个集合,拥有该文件的组的成员有一个集合,然后最终一个集合适用于其他所有人。在长列表(ls -l)中这些权限使用符号...

老孟的Linux私房菜
今天
7
0
面试套路题目

作者:抱紧超越小姐姐 链接:https://www.nowcoder.com/discuss/309292?type=3 来源:牛客网 面试时候的潜台词 抱紧超越小姐姐 编辑于 2019-10-15 16:14:56APP内打开赞 3 | 收藏 4 | 回复24 ...

MtrS
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部