You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何理解H.265头部?H.264与H.265头部差异及解析疑问

H.264与H.265头部差异及H.265 SPS解析问题解答

一、H.264与H.265头部核心差异

  • NALU头部结构:H.264的NALU头部仅1字节,包含1位禁止位、2位参考等级、5位NAL类型;H.265的NALU头部是2字节,包含1位禁止位、6位NAL类型、6位分层ID、3位时间ID+1,结构更复杂,适配更高阶的编码特性。
  • 参数集体系:H.264只有SPS(序列参数集)和PPS(图像参数集);H.265新增了VPS(视频参数集),把全局共享的参数从SPS中拆分出来,层级划分更清晰。
  • 分辨率与宽高比表示:H.264的分辨率需要通过宏块数或直接字段计算,宽高比依赖aspect_ratio_idc及扩展参数;H.265直接在SPS中用pic_width_in_luma_samples和pic_height_in_luma_samples定义亮度分辨率,宽高比逻辑类似但参数位置和前置依赖字段不同。

二、你当前的解析代码存在的问题

先贴你的代码:

while (buf->Size > 0)
{
    //forbidden bit
    flushbits(buf, 1); 

    int nNALType = showbits(buf, 6);

    if (nNALType == NAL_TYPE_SPS)
    {
        // flushbits until I retrieve desired parameter
        flushbits(buf, 4); // sps_video_parameter_set_id
    }
    else
    {
        // align bits
        buf->Size -= buf->BitsLeft & 0x7; 
    }
}

几个明显错误:

  1. NALU头部处理完全错误:H.265的NALU头部是16位(2字节),你只跳过1位禁止位就读6位NAL类型,后面还有6位分层ID和3位时间ID没处理,直接导致后续比特偏移全部错位。
  2. SPS内部解析太潦草:就算找到SPS NALU,你只跳过了sps_video_parameter_set_id,但要拿到目标参数,必须先解析一堆前置字段(比如sps_max_sub_layers_minus1、profile_tier_level结构等),这些不处理根本找不到目标参数的位置。
  3. 非SPS NALU的跳过逻辑无效:buf->Size -= buf->BitsLeft & 0x7这种方式根本跳不过整个NALU,NALU是字节对齐的,你得根据封装格式(Annex-B或AVCC)来确定NALU的长度,再跳过对应字节数,不是简单对齐比特。

三、快速定位H.265 SPS NALU的方法

分两种常见封装格式:

1. Annex-B格式(裸流、TS流等)

  • 先扫缓冲区里的起始码:要么是0x000001(3字节),要么是0x00000001(4字节),每个起始码后面跟着一个完整的NALU。
  • 找到起始码后,读后面2字节的NALU头部,解析出nal_unit_type(禁止位之后的6位),如果是33(SPS的类型值),就开始解析这个NALU内部;否则直接跳过从当前起始码到下一个起始码之间的所有字节。

2. AVCC格式(MP4、FLV等)

  • 每个NALU开头有4字节的长度字段,先读这4字节得到整个NALU的字节数。
  • 接着读后面2字节的NALU头部,解析nal_unit_type,如果是SPS就解析内部;否则直接跳过刚才读到的长度对应的所有字节。

四、提取目标参数的关键解析步骤

要拿到pic_width_in_luma_samples、pic_height_in_luma_samples、aspectRatioH、aspectRatioV,必须按顺序解析前置字段(只列关键的):

  1. 先跳过整个NALU头部的16位(1位禁止位+6位NAL类型+6位分层ID+3位时间ID+1)。
  2. 解析sps_video_parameter_set_id(4位)。
  3. 解析sps_max_sub_layers_minus1(3位)。
  4. 解析sps_temporal_id_nesting_flag(1位)。
  5. 解析profile_tier_level结构(这部分比较繁琐,要按子层数解析对应参数)。
  6. 解析sps_seq_parameter_set_id(4位)。
  7. 解析chroma_format_idc(2位),如果值是3,还要解析separate_colour_plane_flag(1位)。
  8. 这时候才能解析pic_width_in_luma_samples和pic_height_in_luma_samples(都是无符号指数哥伦布编码,要按这个编码规则解码)。
  9. 解析conformance_window_flag(1位),如果是1,还要跳过窗口相关的4个参数。
  10. 解析aspect_ratio_info_present_flag(1位),如果是1:
    • 先解析aspect_ratio_idc(8位),如果这个值是255,才会读取aspectRatioH和aspectRatioV(同样是无符号指数哥伦布编码);否则直接用aspect_ratio_idc对应的预定义宽高比即可。

内容的提问来源于stack exchange,提问作者Max

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 17:36:15