h265 sps 解析视频宽高

gcp 2019-12-07 15:40:17 5811

一、NALU 解析
首先来介绍下h265(HEVC)nal单元头,与h264的nal层相比,h265的nal unit header有两个字节构成,如下图所示

0                   1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| F | Type | LayerId | TID |
+------------ - +---------------- - +

其语法如下表中的定义:

从图中可以看出hevc的nal包结构与h264有明显的不同,hevc加入了nal所在的时间层的ID,去除了nal_ref_idc,此信息合并到了naltype中,
通常情况下F为0,layerid为0, TID为1。

H265 帧类型判断:
和264的&0x1f不同。265是 :

int type = (code & 0x7E)>>1;

在文件中查找00 00 00 01NALU头,发现在有6种开头分别为:

再根据H265的NALU类型定义分析,
00 00 00 01 40 01 的nuh_unit_type的值为 32, 语义为视频参数集 VPS
00 00 00 01 42 01 的nuh_unit_type的值为 33, 语义为序列参数集 SPS
00 00 00 01 44 01 的nuh_unit_type的值为 34, 语义为图像参数集 PPS
00 00 00 01 4E 01 的nuh_unit_type的值为 39, 语义为补充增强信息 SEI
00 00 00 01 26 01 的nuh_unit_type的值为 19, 语义为可能有RADL图像的IDR图像的SS编码数据 IDR
00 00 00 01 02 01 的nuh_unit_type的值为1, 语义为被参考的后置图像,且非TSA、非STSA的SS编码数据
在编码过程中,从编码器获取码流的时候,1、2、3、4、5是在一帧数据当中。相当于H264的I帧。

Nalu Type的定义

enum NalUnitType  
{  
  NAL_UNIT_CODED_SLICE_TRAIL_N = 0,   // 0  
  NAL_UNIT_CODED_SLICE_TRAIL_R,   // 1  

  NAL_UNIT_CODED_SLICE_TSA_N,     // 2  
  NAL_UNIT_CODED_SLICE_TLA,       // 3   // Current name in the spec: TSA_R  

  NAL_UNIT_CODED_SLICE_STSA_N,    // 4  
  NAL_UNIT_CODED_SLICE_STSA_R,    // 5  

  NAL_UNIT_CODED_SLICE_RADL_N,    // 6  
  NAL_UNIT_CODED_SLICE_DLP,       // 7 // Current name in the spec: RADL_R  

  NAL_UNIT_CODED_SLICE_RASL_N,    // 8  
  NAL_UNIT_CODED_SLICE_TFD,       // 9 // Current name in the spec: RASL_R  

  NAL_UNIT_RESERVED_10,  
  NAL_UNIT_RESERVED_11,  
  NAL_UNIT_RESERVED_12,  
  NAL_UNIT_RESERVED_13,  
  NAL_UNIT_RESERVED_14,  
  NAL_UNIT_RESERVED_15, NAL_UNIT_CODED_SLICE_BLA,       // 16   // Current name in the spec: BLA_W_LP  
NAL_UNIT_CODED_SLICE_BLA,       // 16   // Current name in the spec: BLA_W_LP  
  NAL_UNIT_CODED_SLICE_BLANT,     // 17   // Current name in the spec: BLA_W_DLP  
  NAL_UNIT_CODED_SLICE_BLA_N_LP,  // 18  
  NAL_UNIT_CODED_SLICE_IDR,       // 19  // Current name in the spec: IDR_W_DLP  
  NAL_UNIT_CODED_SLICE_IDR_N_LP,  // 20  
  NAL_UNIT_CODED_SLICE_CRA,       // 21  
  NAL_UNIT_RESERVED_22,  
  NAL_UNIT_RESERVED_23,  

  NAL_UNIT_RESERVED_24,  
  NAL_UNIT_RESERVED_25,  
  NAL_UNIT_RESERVED_26,  
  NAL_UNIT_RESERVED_27,  
  NAL_UNIT_RESERVED_28,  
  NAL_UNIT_RESERVED_29,  
  NAL_UNIT_RESERVED_30,  
  NAL_UNIT_RESERVED_31,  

  NAL_UNIT_VPS,                   // 32  
  NAL_UNIT_SPS,                   // 33  
  NAL_UNIT_PPS,                   // 34  
  NAL_UNIT_ACCESS_UNIT_DELIMITER, // 35  
  NAL_UNIT_EOS,                   // 36  
  NAL_UNIT_EOB,                   // 37  
  NAL_UNIT_FILLER_DATA,           // 38  
  NAL_UNIT_SEI,                   // 39 Prefix SEI  
  NAL_UNIT_SEI_SUFFIX,            // 40 Suffix SEI  
  NAL_UNIT_RESERVED_41,  
  NAL_UNIT_RESERVED_42,  
  NAL_UNIT_RESERVED_43,  
  NAL_UNIT_RESERVED_44,  
  NAL_UNIT_RESERVED_45,  
  NAL_UNIT_RESERVED_46,  
  NAL_UNIT_RESERVED_47,  
  NAL_UNIT_UNSPECIFIED_48,  
  NAL_UNIT_UNSPECIFIED_49,  
  NAL_UNIT_UNSPECIFIED_50,  
  NAL_UNIT_UNSPECIFIED_51,  
  NAL_UNIT_UNSPECIFIED_52,  
  NAL_UNIT_UNSPECIFIED_53,  
  NAL_UNIT_UNSPECIFIED_54,  
  NAL_UNIT_UNSPECIFIED_55,  
  NAL_UNIT_UNSPECIFIED_56,  
  NAL_UNIT_UNSPECIFIED_57,  
  NAL_UNIT_UNSPECIFIED_58,  
  NAL_UNIT_UNSPECIFIED_59,  
  NAL_UNIT_UNSPECIFIED_60,  
  NAL_UNIT_UNSPECIFIED_61,  
  NAL_UNIT_UNSPECIFIED_62,  
  NAL_UNIT_UNSPECIFIED_63,  
  NAL_UNIT_INVALID,  
};  

二、sps解析代码

bool  ParseSequenceParameterSet(BYTE* data,int size, vc_params_t& params)
{
    if (size < 20)
    {
        return false;
    }

    NALBitstream bs(data, size);

    // seq_parameter_set_rbsp()
    bs.GetWord(4);// sps_video_parameter_set_id
    int sps_max_sub_layers_minus1 = bs.GetWord(3); // "The value of sps_max_sub_layers_minus1 shall be in the range of 0 to 6, inclusive."
    if (sps_max_sub_layers_minus1 > 6)
    {
        return false;
    }
    bs.GetWord(1);// sps_temporal_id_nesting_flag
    // profile_tier_level( sps_max_sub_layers_minus1 )
    {
        bs.GetWord(2);// general_profile_space
        bs.GetWord(1);// general_tier_flag
        params.profile = bs.GetWord(5);// general_profile_idc
        bs.GetWord(32);// general_profile_compatibility_flag[32]
        bs.GetWord(1);// general_progressive_source_flag
        bs.GetWord(1);// general_interlaced_source_flag
        bs.GetWord(1);// general_non_packed_constraint_flag
        bs.GetWord(1);// general_frame_only_constraint_flag
        bs.GetWord(44);// general_reserved_zero_44bits
        params.level   = bs.GetWord(8);// general_level_idc
        uint8 sub_layer_profile_present_flag[6] = {0};
        uint8 sub_layer_level_present_flag[6]   = {0};
        for (int i = 0; i < sps_max_sub_layers_minus1; i++)
        {
            sub_layer_profile_present_flag[i]= bs.GetWord(1);
            sub_layer_level_present_flag[i]= bs.GetWord(1);
        }
        if (sps_max_sub_layers_minus1 > 0)
        {
            for (int i = sps_max_sub_layers_minus1; i < 8; i++)
            {
                uint8 reserved_zero_2bits = bs.GetWord(2);
            }
        }
        for (int i = 0; i < sps_max_sub_layers_minus1; i++)
        {
            if (sub_layer_profile_present_flag[i])
            {
                bs.GetWord(2);// sub_layer_profile_space[i]
                bs.GetWord(1);// sub_layer_tier_flag[i]
                bs.GetWord(5);// sub_layer_profile_idc[i]
                bs.GetWord(32);// sub_layer_profile_compatibility_flag[i][32]
                bs.GetWord(1);// sub_layer_progressive_source_flag[i]
                bs.GetWord(1);// sub_layer_interlaced_source_flag[i]
                bs.GetWord(1);// sub_layer_non_packed_constraint_flag[i]
                bs.GetWord(1);// sub_layer_frame_only_constraint_flag[i]
                bs.GetWord(44);// sub_layer_reserved_zero_44bits[i]
            }
            if (sub_layer_level_present_flag[i])
            {
                bs.GetWord(8);// sub_layer_level_idc[i]
            }
        }
    }
    uint32 sps_seq_parameter_set_id= bs.GetUE(); // "The  value  of sps_seq_parameter_set_id shall be in the range of 0 to 15, inclusive."
    if (sps_seq_parameter_set_id > 15)
    {
        return false;
    }
    uint32 chroma_format_idc = bs.GetUE(); // "The value of chroma_format_idc shall be in the range of 0 to 3, inclusive."
    if (sps_seq_parameter_set_id > 3)
    {
        return false;
    }
    if (chroma_format_idc == 3)
    {
        bs.GetWord(1);// separate_colour_plane_flag
    }
    params.width  = bs.GetUE(); // pic_width_in_luma_samples
    params.height  = bs.GetUE(); // pic_height_in_luma_samples
    if (bs.GetWord(1))
    {// conformance_window_flag
        bs.GetUE();  // conf_win_left_offset
        bs.GetUE();  // conf_win_right_offset
        bs.GetUE();  // conf_win_top_offset
        bs.GetUE();  // conf_win_bottom_offset
    }
    uint32 bit_depth_luma_minus8= bs.GetUE();
    uint32 bit_depth_chroma_minus8= bs.GetUE();
    if (bit_depth_luma_minus8 != bit_depth_chroma_minus8)
    {
        return false;
    }
    //...

    return true;
}

三、测试代码

int main(int argc, _TCHAR* argv[])
{
    vc_params_t params = {0};

    BYTE sps1080[] = {0x42,0x01,0x01,0x01,0x60,0x00,0x00,0x03,0x00,0xb0,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x7b,0xa0,0x03,0xc0,0x80,0x10,0xe5,0x8d,0xae,0x49,0x32,0xf4,0xdc,0x04,0x04,0x04,0x02};
    BYTE sps720[]={0x42,0x01,0x01,0x01,0x60,0x00,0x00,0x03,0x00,0xb0,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x5d,0xa0,0x02,0x80,0x80,0x2d,0x16,0x36,0xb9,0x24,0xcb,0xd3,0x70,0x10,0x10,0x10,0x08};
    BYTE spsD1[]={0x42,0x01,0x01,0x01,0x60,0x00,0x00,0x03,0x00,0xb0,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x5a,0xa0,0x05,0xa2,0x00,0x90,0x58,0xda,0xe4,0x93,0x2f,0x4d,0xc0,0x40,0x40,0x40,0x20};
    ParseSequenceParameterSet(sps1080,sizeof(sps1080),params);
    printf("%d-%d-%d\n",params.width,params.height,params.level);
    ParseSequenceParameterSet(sps720,sizeof(sps720),params);
    printf("%d-%d-%d\n",params.width,params.height,params.level);
    ParseSequenceParameterSet(spsD1,sizeof(spsD1),params);
    printf("%d-%d-%d\n",params.width,params.height,params.level);

    return 0;
}

声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
gcp
红包 点赞 收藏 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
关于作者
gcp

gcp

暂无个性签名~

原创12
阅读6.4w
收藏0
点赞6
评论1
打赏用户 0
我要创作
分享技术经验,可获取创作收益
分类专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
gcp
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区