音视频学习记录一C/C++解析并修改SPS PPS参数

 本文仅针对为解析并修改SPS以及PPS参数的方便性,记录编程逻辑,不做理论科普

 H264官方标准文档

这个baidu可以找到的,或者关注我私信我发 ,即便理论知识到处都可以查到,但是官方文档还是有必要看一下的,里面针对每一位参数都有详细的介绍以及标明限制情况 

H264的基本结构

此篇章不赘述理论,有非常多的好的理论科普文章,假设已知基本理论知识

只需要记住再获取SPS文件前,需要剥离容器获取裸流文件(.h264文件);

 1.第一步找到SPS

我们如果需要找到SPS,首先应该知道,裸流文件中有非常多的NALU,而只有type=7的NALU含有SPS参数,所以在找到SPS之前应该是找到含有SPS的NALU;

找到NALU:

这一步很简单,无非两种类型0x000001或者0x00000001:

if ((buf[pos] == 0x00 && buf[pos + 1] == 0x00 && buf[pos + 2] == 0x01) ||
(buf[pos] == 0x00 && buf[pos + 1] == 0x00 && buf[pos + 2] == 0x00 && buf[pos + 3] == 0x01))

找到NALU之后再找SPS就很简单了,只需要判断type=7:

uint8_t nalu_type = buf[pos + (is_long_start_code ? 4 : 3)] & 0x1F;

做类型判断就行了

if (nalu_type == 7)

 注意!!!关键的来了,为了后续修改SPS参数的方便性,建议直接打印该包含SPS参数的NALU所在的位置,记录该NALU在原H264文件的第几个NALU,具体实现方法不贴了,加个pos记录起始位置,后续打印出来就行了

到这里,我们需要把包含SPS的这个NALU提取出去,也就是获得了sps数据

2.借助工具进行参数解析

在编程解析之前,先借助工具,例如H264Visa.

先通过工具查看详细的SPS参数,作为我们解析的参考

3.SPS参数解析

解析这一步参考标准文档给出的标准格式进行解析

具体涉及到三种编码格式,详细的理论不做介绍这里只介绍编码过程,在我们获取到含SPS参数的NALU后,需要跳过第一个字节,然后就进入真正的seq_parameter_set_data( ),第一个字节便是profile_idc;,紧接着就是constraint_set_flag,再往下便是level_idc;

 sps->profile_idc = br_get_u8(&br);/*profile_idc*/
    //br_skip_bits(&br, 8);    /*constraint_set_flag*/
    int constraint_set0_flag = br_get_bit(&br);    
    int constraint_set1_flag = br_get_bit(&br);    
    int constraint_set2_flag = br_get_bit(&br);    
    int constraint_set3_flag = br_get_bit(&br);    
    int constraint_set4_flag = br_get_bit(&br);    
    int reserved_zero_3bits  = br_get_bits(&br,3); 
    printf("constraint_set_flag:%d %d %d %d %d %d\n",constraint_set0_flag,constraint_set1_flag,
        constraint_set2_flag,constraint_set3_flag,constraint_set4_flag,reserved_zero_3bits);
    
    sps->level_idc = br_get_u8(&br);   /*level_idc*/

需要注意的是假如 profile_idc满足条件,会进行扩展

if(profile_idc == 100 || profile_idc == 110 || profile_idc == 122 
        || profile_idc == 244 || profile_idc == 44 || profile_idc == 83 
        || profile_idc == 86 || profile_idc == 118 )
    {
            int chroma_format_idc=br_get_ue_golomb(&br);/* chroma_format_idc      */
            if (chroma_format_idc == 3) 
            {
                 br_skip_bit(&br);     /* residual_colour_transform_flag */
            }
           
        br_skip_ue_golomb(&br); /* bit_depth_luma - 8             */
        br_skip_ue_golomb(&br); /* bit_depth_chroma - 8           */
        br_skip_bit(&br);       /* transform_bypass               */
        if (br_get_bit(&br))    /* seq_scaling_matrix_present     */
            for (i = 0; i < ((chroma_format_idc !=3)?8:12); i++)
            {
                if (br_get_bit(&br)) 
                {
                    /* seq_scaling_list_present    */
                    int last = 8, next = 8, size = (i<6) ? 16 : 64;
                    for (j = 0; j < size; j++) 
                    {

                        if (next)
                            next = (last + br_get_se_golomb(&br)) & 0xff;
                        last = next ? next: last;
                    }
                }

           }

    }

 最终可以将SPS参数全部解析出来

这里有一个很关键的地方,就是在解析的过程中加上索引,记录每一位变量在此SPS中的偏移量,实例如下:

   int             pic_index;/*存储pic_height索引位置*/
    int             pic_len;/*存储pic_height编码长度*/
    int sps_nalu_position;/*存储裸流中有SPS的位置*/

4.SPS参数修改

实际上修改这一步,有两个难点

难点一:精准定位到需要修改的参数

难点二:修改哥伦布编码的数据

针对难点一:

实际上如果前述的找到SPS所在NALU时,记录了该NALU所在的位置,假如为pos=24,

在解析各参数的记录了各参数的索引,即相对SPS首地址的偏移量,假设需要修改的参数index=46,

那么定位就变成很简单,直接在原H264文件中找到pos=24的NALU,在其起始位置的基础上+8+46就是我们需要修改的参数首地址了,+8代表NALU第一个字节(记录type等信息),+46则代表在SPS中的偏移。此时就完成了参数的定位;

针对难点二:

假如需要将一位使用哥伦布编码的参数从31修改为29,那么需要先将29编码成哥伦布编码格式,再重新写入,其中注意记录所占字节长度以便写入。

到这里基本上就完成了SPS的解析与修改,PPS参数类似

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值