• 第43月第29天 rtp分包


    1.

    NALU 头由一个字节组成, 它的语法如下:

    ,以00 00 00 01分割之后的下一个字节就是NALU类型,将其转为二进制数据后,

    解读顺序为从左往右算,如下:

    (1)第1位禁止位,值为1表示语法出错

    (2)第2~3位为参考级别

    (3)第4~8为是nal单元类型

    例如上面00000001后有67,68以及65

    其中0x67的二进制码为:

    0110 0111

    4-8为00111,转为十进制7,参考第二幅图:7对应序列参数集SPS

    其中0x68的二进制码为:

    0110 1000
    4-8为01000,转为十进制8,参考第二幅图:8对应图像参数集PPS

    其中0x65的二进制码为:

    011 00101

    4-8位为00101,转为十进制5,参考第二幅图:5对应IDR图像中的片(I帧)

    所以判断是否为I帧的算法为:

    (NALU类型 & 0001 1111) = 5 即 (NALU类型 & 31) = 5
    比如0x65 & 31 = 5

    rtp

    对于 NALU 的长度小于 MTU 大小的包, 一般采用单一 NAL 单元模式.
    对于一个原始的 H.264 NALU 单元常由[Start Code] [NALU Header] [NALU Payload]三部分组成, 其中 Start Code 用于标示这是一个
    NALU 单元的开始, 必须是 “00 00 00 01” 或 “00 00 01”, NALU 头仅一个字节, 其后都是 NALU 单元内容.

    打包时去除 “00 00 01” 或 “00 00 00 01” 的开始码, 把其他数据封包的 RTP 包即可.

    如有一个 H.264 的 NALU 是这样的:

    [00 00 00 01 67 42 A0 1E 23 56 0E 2F … ]

    这是一个序列参数集 NAL 单元. [00 00 00 01] 是四个字节的开始码, 67 是 NALU 头, 42 开始的数据是 NALU 内容.

    封装成 RTP 包将如下:

    [ RTP Header ] [ 67 42 A0 1E 23 56 0E 2F ]

    即只要去掉 4 个字节的开始码就可以了.

    nal

    FU indicator有以下格式:

    +---------------+
    |0|1|2|3|4|5|6|7|
    +-+-+-+-+-+-+-+-+
    |F|NRI| Type |
    +---------------+

    FU指示字节的类型域的28,29表示FU-A和FU-B。NRI域的值必须根据分片NAL单元的NRI域的值设置。(此处Type就是rtp分片类型) 见下表

    .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

    #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; // 获取FUindicator的类型域,
    
       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 ; // rtpmark
    
        }
    
        else
    
        {
    
           bFinishFrame =   false ;
    
        }
    
        return  bFinishFrame;
    
    }

    https://blog.csdn.net/machh/article/details/52165292

    https://blog.csdn.net/duan_jin_hui/article/details/67638024

  • 相关阅读:
    (二)《机器学习》(周志华)第4章 决策树 笔记 理论及实现——“西瓜树”——CART决策树
    (一)《机器学习》(周志华)第4章 决策树 笔记 理论及实现——“西瓜树”
    python学习笔记——递归算法
    Python爬虫抓取东方财富网股票数据并实现MySQL数据库存储
    MySQL安装总是失败,提示缺少Visual Studio 2013 Redistributable
    Python爬虫简单实现之Q乐园图片下载
    Python爬虫之简单的图片获取
    Springboot启动,URL正确,但是报404
    Linux常用命令
    MYSQL常用的配置参数优化
  • 原文地址:https://www.cnblogs.com/javastart/p/12800258.html
Copyright © 2020-2023  润新知