获取H264视频流的尺寸

29

我正在尝试从H264流中获取尺寸(高度和宽度)。 我知道,要从mpeg2流中获取相同的细节,您必须查看序列头启动代码(01B3)后面的四个字节。 同样的逻辑是否适用于H264? 如果有任何帮助,将不胜感激。


请使用以下链接获取此问题的C源代码:https://dev59.com/3WfWa4cB1Zd3GeqPg2td#27636670 - Pankaj Vavadiya
4个回答

50

不行!!!

你必须运行一个复杂的函数来从序列参数集中提取视频尺寸。如何做呢?首先,你必须编写自己的Exp-Golomb解码器或在网络上找到一个...例如,在live555源代码中,就有一个...

然后你必须获取一个SPS帧。它的NAL值为NAL=0x67(NAL是H.264帧中的第一个字节),你可以在SDP中找到它作为Base64编码字符串的形式,出现在sprop-parameter-sets下的第一个逗号之前的第一个Base64字符串。那里的其他逗号分隔的字符串是Picture Parameter Sets...这是一个来自SDP的SPS:Z0KAKYiLQDIBL0IAAB1MAAK/IAg=,你需要将其从Base64解码成一个字节数组。

接着你必须提取原始字节序列负载(RAW BYTE SEQUENCE PAYLOAD),后面紧跟着NAL单元头(NAL UNIT HEADER)!!! 它通常只有一个字节长,但建议继续阅读以确保...RBSP 包含运行 seq_parameter_set_data( ) 函数所需的字节。因此,您需要首先剥离NAL UNIT HEADER(一个或多个字节)。

这里是从SPS NAL UNIT中提取RBSP字节的函数:

NAL UNIT

然后,当你有了SPS(RBSP字节)之后,你需要执行一个函数,解析这个字节数组中的位。下面是该函数已解析出所有参数的示例(完整文档可以在此处找到:http://www.itu.int/rec/T-REC-H.264-201003-I/en,且免费提供):

How to decode SPS

在那里,你可以看到一些奇怪的东西...首先,你的视频尺寸是这样计算的:

Width = ((pic_width_in_mbs_minus1 +1)*16) - frame_crop_right_offset*2 - frame_crop_left_offset*2;
Height = ((2 - frame_mbs_only_flag)* (pic_height_in_map_units_minus1 +1) * 16) - (frame_crop_top_offset * 2) - (frame_crop_bottom_offset * 2);

其次,也是最重要的,在此代码表的DESCRIPTOR列中,说明了您应该如何读取第一列中加粗文本参数的内容。其中值的含义如下:
  • u(N) - 读取一个N位长的无符号数
  • s(N) - 读取一个N位长的有符号数
  • ue(v) - 读取一个无符号Exp-Golomb数(v表示变长,因此与ue()相同)
  • se(v) - 读取一个有符号Exp-Golomb数
这就是您需要使用Exp-Golomb解码器的地方...
因此,请实现此函数,解析SPS,然后您将获得宽度和高度。享受吧... :)

这些 ScalingList4x4[]、DefaultScalingMatrix4x4Flag[] 和 UseDefaultScalingMatrix8x8Flag[] 数组是什么?它们被定义为常量值吗? - Novalis
2
好的,我找到了一个公共的链接...http://www-ee.uta.edu/Dip/Courses/EE5359/H.264%20Standard2007.pdf 但是里面没有关于那些的有用信息... - Novalis
抱歉,但我无法帮助你... 关于那个问题问一个新问题吧?! - Cipi
1
我不知道你从哪里得到Base64的信息,因为在H.264中没有使用过。SPS中的所有内容都是Exp-Golomb编码的。你一定在查看某些软件将其解析成Base64以方便处理。 - SilverbackNet
2” 的裁剪值是从哪里来的?在 H264 ITU 7.4.2.1.1 SPS 语义中,您可以读到将裁剪值乘以 CropUnitX 和 CropUnitY。如果 ChromaArrayType 是“-”,则 CropUnitX 为 1,CropUnitY 为 2-frame_mbs_only_flag。因此,我看不出在这里硬设 2 的原因...谢谢。 - jyavenard
显示剩余3条评论

22
很遗憾,尺寸计算是错误的,应该是:
width = ((pic_width_in_mbs_minus1 +1)*16) - frame_crop_left_offset*2 - frame_crop_right_offset*2;
height= ((2 - frame_mbs_only_flag)* (pic_height_in_map_units_minus1 +1) * 16) - (frame_crop_top_offset * 2) - (frame_crop_bottom_offset * 2);

为什么在 frame_cop_*_offset 上要乘以 2? - jyavenard

6

实际上,只有在SPS中启用[frame_cropping_flag]时才应使用裁剪参数。享受H.264吧!


3
关于帧大小计算,以上公式不正确。
当存在chroma_format_idc时,我们需要从SPS中提取它。当不存在chroma_format_idc时,它应被推断为等于1(4:2:0色度格式)。在这种情况下,separate_color_plane_flag未设置。这意味着chromaArrayType = chroma_format_idc,而subWidthC和subHeightC等于2。
变量cropUnitX和cropUnitY的推导方法如下:
  • If chromaArrayType is equal to 0, cropUnitX and cropUnitY are derived as:

    cropUnitX = 1
    cropUnitY = 2 - frame_mbs_only_flag
    
  • Otherwise (chromaArrayType is equal to 1, 2, or 3), cropUnitX and cropUnitY are derived as:

    cropUnitX = subWidthC
    cropUnitY = subHeightC * ( 2 - frame_mbs_only_flag )
    
现在你可以在上述公式中使用cropUnitXcropUnitY来获得正确的帧大小值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接