我正在尝试从 H264 流中获取尺寸(高度和宽度)。我知道要从 mpeg2 流中获取相同的详细信息,您必须查看序列头开始代码 ((01B3)) 之后的四个字节。相同的逻辑是否适用于 H264?将不胜感激任何帮助我得到..
4 回答
不!!!
您必须运行一个复杂的函数来从序列参数集中提取视频尺寸。这个怎么做?那么首先你必须编写自己的 Exp-Golomb 解码器,或者在网上找到一个......在 live555 源代码中的某个地方有一个例如......
然后你必须得到一个 SPS 帧。它具有NAL=0x67
(NAL 是 H.264 帧中的第一个字节),您可以在 SDP 中sprop-parameter-sets
的第一个逗号之前的第一个 Base64 字符串下找到它作为 Base64 编码的字符串。其他逗号分隔的字符串还有图片参数集...这是来自 SDP 的一个 SPS,Z0KAKYiLQDIBL0IAAB1MAAK/IAg=
您需要将类似这样的内容从 Base64 解码为字节数组。
然后,您必须提取 RAW BYTE SEQUENCE PAYLOAD,然后在该字节数组中提取 NAL UNIT HEADER !!!它通常是一个字节长,但请继续阅读以确保... RBSP 包含运行该seq_parameter_set_data( )
函数所需的字节。所以你需要先去掉 NAL UNIT HEADER(一个或多个字节)。
这是从 SPS NAL UNIT 中提取 RBSP 字节的函数:
然后,当您有 SPS(RBSP 字节)时,您需要执行一个函数来解析此字节数组中的位。这是在那里解析所有参数的函数(整个文档可以在这里找到:http ://www.itu.int/rec/T-REC-H.264-201003-I/en及其免费):
在那里你可以看到一些奇怪的东西......首先,你的视频尺寸是这样计算的:
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,你会得到你的宽度和高度。享受... :)
不幸的是,尺寸计算是错误的,应该是:
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);
实际上,只有在 SPS 中启用 [frame_cropping_flag] 时才应使用裁剪参数。享受 H.264!
关于帧大小的计算,上面的公式是不正确的。
当chroma_format_idc
存在时,我们必须从 SPS 中提取它。当chroma_format_idc
不存在时,应推断为等于 1(4:2:0 色度格式)。在这种情况下,separate_color_plane_flag
未设置。这意味着chromaArrayType = chroma_format_idc
andsubWidthC
和subHeightC
不等于 2。
变量cropUnitX 和cropUnitY 派生如下:
如果
chromaArrayType
等于0
,cropUnitX
并且cropUnitY
导出为:cropUnitX = 1 cropUnitY = 2 - frame_mbs_only_flag
否则 (
chromaArrayType
等于1
,2
, 或3
),cropUnitX
并cropUnitY
派生为:cropUnitX = subWidthC cropUnitY = subHeightC * ( 2 - frame_mbs_only_flag )
现在您可以在上面的公式中使用cropUnitX
andcropUnitY
来获得帧大小的正确值。