Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >如何在H264码流的SPS中获取宽和高信息?

如何在H264码流的SPS中获取宽和高信息?

作者头像
liuzhen007
发布于 2023-03-08 08:40:55
发布于 2023-03-08 08:40:55
3.8K00
代码可运行
举报
文章被收录于专栏:流媒体音视频流媒体音视频
运行总次数:0
代码可运行

前言

了解H264视频编码格式的小伙伴都知道,H264编码中存在两个非常重要的参数集。没错,它们就是序列参数集(SPS)和图像参数集(PPS),而且通常情况下,PPS会依赖SPS中的部分参数信息,同时,视频码流的宽高信息也存储在SPS中。那么如何从中获取视频的宽高信息呢,就是今天本文的主要内容。

正文

一、SPS的结构

对H264码流进行解码时,肯定会用到SPS中的相关参数,因此,我们非常有必要了解其中参数的含义。其中,H.264标准协议中(文档的7.3.2.1.1部分)规定的SPS格式如下图所示:

接下来,介绍一下上图中的部分参数。

(1) profile_idc

标识当前H.264码流的profile。我们知道,H.264中定义了三种常用的档次profile:

基准档次:baseline profile;

主要档次:main profile;

扩展档次:extended profile;

在H.264的SPS中,第一个字节表示profile_idc,根据profile_idc的值可以确定码流符合哪一种档次。判断规律如下:

profile_idc = 66 → baseline profile;

profile_idc = 77 → main profile;

profile_idc = 88 → extended profile;

在新版的标准中,还包括了High、High 10、High 4:2:2、High 4:4:4、High 10 Intra、High

4:2:2 Intra、High 4:4:4 Intra、CAVLC 4:4:4 Intra等,每一种都由不同的profile_idc表示。

另外,constraint_set0_flag ~ constraint_set5_flag是在编码的档次方面对码流增加的其他一些额外限制性条件。

(2) level_idc

标识当前码流的Level。编码的Level定义了某种条件下的最大视频分辨率、最大视频帧率等参数,码流所遵从的level由level_idc指定。

当前码流中,level_idc = 0x1e = 30,因此码流的级别为3。

(3) seq_parameter_set_id

表示当前的序列参数集的id。通过该id值,图像参数集pps可以引用其代表的sps中的参数。

(4) log2_max_frame_num_minus4

用于计算MaxFrameNum的值。计算公式如下:

MaxFrameNum = 2^(log2_max_frame_num_minus4 + 4)

MaxFrameNum是frame_num的上限值,frame_num是图像序号的一种表示方法,在帧间编码中常用作一种参考帧标记的手段。

(5) pic_order_cnt_type

表示解码picture order count(POC)的方法。POC是另一种计量图像序号的方式,与frame_num有着不同的计算方法。该语法元素的取值为0、1或2。

(6) log2_max_pic_order_cnt_lsb_minus4

用于计算MaxPicOrderCntLsb的值,该值表示POC的上限。计算公式如下:

MaxPicOrderCntLsb = 2^(log2_max_pic_order_cnt_lsb_minus4 + 4)

(7) max_num_ref_frames

用于表示参考帧的最大数目。

(8) gaps_in_frame_num_value_allowed_flag

标识位,说明frame_num中是否允许不连续的值。

(9) pic_width_in_mbs_minus1

用于计算图像的宽度,单位为宏块个数。

(10) pic_height_in_map_units_minus1

使用PicHeightInMapUnits来度量视频中一帧图像的高度。PicHeightInMapUnits并非图像明确的以像素或宏块为单位的高度,而需要考虑该宏块是帧编码或场编码。

(11) frame_mbs_only_flag

标识位,说明宏块的编码方式。当该标识位为0时,宏块可能为帧编码或场编码;该标识位为1时,所有宏块都采用帧编码。根据该标识位取值不同,PicHeightInMapUnits的含义也不同,为0时表示一场数据按宏块计算的高度,为1时表示一帧数据按宏块计算的高度。

按照宏块计算的图像实际高度FrameHeightInMbs的计算方法为:

FrameHeightInMbs = ( 2 − frame_mbs_only_flag ) * PicHeightInMapUnits

(12) mb_adaptive_frame_field_flag

标识位,说明是否采用了宏块级的帧场自适应编码。当该标识位为0时,不存在帧编码和场编码之间的切换;当标识位为1时,宏块可能在帧编码和场编码模式之间进行选择。

(13) direct_8x8_inference_flag

标识位,用于B_Skip、B_Direct模式运动矢量的推导计算。

(14) frame_cropping_flag

标识位,说明是否需要对输出的图像帧进行裁剪。

(15) vui_parameters_present_flag

标识位,说明SPS中是否存在VUI信息。

二、SPS的存储位置

在H264码流中,都是以"0x00 0x00 0x01"或者"0x00 0x00 0x00 0x01"作为起始码的,找到起始码之后,使用开始码之后的第一个字节的低5位判断是否为7,也就是SPS类型标识,伪代码如下:

data[3] & 0x1f == 7 data[4] & 0x1f == 7

SPS 对于H264而言,就是编码后的第一帧,如果是读取的H264文件,就是第一个帧界定符和第二个帧界定符之间的数据,一般长度是4。

三、如何计算宽高信息

根据SPS信息计算视频宽高的常用公式如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
width = (pic_width_in_mbs_minus1+1)*16;
height = (pic_height_in_map_units_minus1+1)*16;
代码语言:javascript
代码运行次数:0
运行
复制

但是这是针对宽高是16的整数倍的情况,如果宽高不是16整数倍时,frame_cropping_flag值为1,frame_mbs_only_flag为1,公式如下:(也可以认为这是统一公式)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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);

四、举例分析

比如一个1080P视频的SPS信息如下:

pic_width_in_mbs_minus1 : 119 pic_height_in_map_units_minus1 : 67 frame_mbs_only_flag : 1 mb_adaptive_frame_field_flag : 0 direct_8x8_inference_flag : 1 frame_cropping_flag : 1 frame_crop_left_offset : 0 frame_crop_right_offset : 0 frame_crop_top_offset : 0 frame_crop_bottom_offset : 4

根据上面的统一公式,计算结果如下:

width = (119+1) * 18 - 0*2 - 0*2 = 1920 height = (2-1) * (67+1)*16 - 0*2 - 4*2 = 1088 - 8 = 1080

代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    // 宽高计算公式
    width  = (sps->pic_width_in_mbs_minus1+1) * 16;
    height = (2 - sps->frame_mbs_only_flag) * (sps->pic_height_in_map_units_minus1 +1) * 16);

    if (sps->frame_cropping_flag)
    {
        unsigned int crop_unit_x;
        unsigned int crop_unit_y;
        if (0 == sps->chroma_format_idc) // monochrome
        {
            crop_unit_x = 1;
            crop_unit_y = 2 - sps->frame_mbs_only_flag;
        }
        else if (1 == sps->chroma_format_idc) // 4:2:0
        {
            crop_unit_x = 2;
            crop_unit_y = 2 * (2 - sps->frame_mbs_only_flag);
        }
        else if (2 == sps->chroma_format_idc) // 4:2:2
        {
            crop_unit_x = 2;
            crop_unit_y = 2 - sps->frame_mbs_only_flag;
        }
        else // 3 == sps.chroma_format_idc   // 4:4:4
        {
            crop_unit_x = 1;
            crop_unit_y = 2 - sps->frame_mbs_only_flag;
        }
        
        width  -= crop_unit_x * (sps->frame_crop_left_offset + sps->frame_crop_right_offset);
        height -= crop_unit_y * (sps->frame_crop_top_offset  + sps->frame_crop_bottom_offset);
    }

作者简介:😄大家好,我是 Data-Mining(liuzhen007),是一名典型的音视频技术爱好者,前后就职于传统广电巨头和音视频互联网公司,具有丰富的音视频直播和播相关经验,对 WebRTC、FFmpeg 和 Electron 有非常深入的了解。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-02-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 玩转音视频 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
FFmpeg开发笔记(三十)解析H.264码流中的SPS帧和PPS帧
​《FFmpeg开发实战:从零基础到短视频上线》一书的“2.1.1  音视频编码的发展历程”介绍了H.26x系列的视频编码标准,其中H.264至今仍在广泛使用,无论视频文件还是网络直播,H.264标准都占据着可观的市场份额。
aqi00
2024/06/16
2.3K0
FFmpeg开发笔记(三十)解析H.264码流中的SPS帧和PPS帧
视频编码(1):可能是最详尽的 H.264 编码相关概念介绍丨音视频基础
(本文基本逻辑:视频编码的理论基础是什么 → H.264 视频编码的基本概念、编码工具、编码流程及码流结构 → H.265 的编码工具及改进 → H.266 的编码工具及改进)
关键帧
2022/06/13
9K0
视频编码(1):可能是最详尽的 H.264 编码相关概念介绍丨音视频基础
H265 Nalu类型判断及 sps 数据解析
首先来介绍下h265(HEVC)nal单元头,与h264的nal层相比,h265的nal unit header有两个字节构成,如下图所示 :
lcyw
2022/06/10
5.2K0
H265 Nalu类型判断及 sps 数据解析
H264码流之AnnexB和AVCC
H264的主要目标是实现高的视频压缩比和提供良好的网络亲和性(可适用于各种网络传输),因此在功能层面上划分为视频编码层VCL和网络提取层NAL两层
雪月清
2022/09/21
2.3K0
H264码流之AnnexB和AVCC
音视频面试题集锦 2023.08
比如,对一个视频做 2 倍速播放,假设原来各视频帧的 pts 依次是 0, 30, 60, 90 ...,倍速处理及将它们除以 2 变成 0, 15, 30, 45 ...。这样处理后,视频的帧率和总时长相应的也发生了变化,帧率变为原来的 2 倍,总时长变为原来的 1/2。
关键帧
2023/09/01
7090
音视频面试题集锦 2023.08
FFmpeg源码分析:av_parser_parse2()解析数据包
在FFmpeg的libavcodec模块提供解析数据包和编解码功能。其中,av_parser_parse2()函数用来解析数据包,在使用av_read_frame()读取音视频帧时,会调用到该函数进行数据包解析。关于读取音视频帧的源码分析请查看:av_read_frame()文章。
全栈程序员站长
2022/09/27
1.5K0
FFmpeg源码分析:av_parser_parse2()解析数据包
【音视频】H264编码基础
视频是由一帧帧图像组成,视频为了不卡顿,一秒钟至少要16帧画面,但是图片内容太大,传输不现实。因此需要对他们编码。
后端码匠
2022/12/05
1.4K0
【音视频】H264编码基础
H264之NALU解析
H.264从1999年开始,到2003年形成草案,最后在2007年定稿有待核实。在ITU的标准⾥称 为H.264,在MPEG的标准⾥是MPEG-4的⼀个组成部分–MPEG-4 Part 10,⼜叫Advanced Video Codec,因此常常称为MPEG-4 AVC或直接叫AVC:
用户6280468
2022/03/21
2.4K0
H264之NALU解析
音视频八股文(8)-- h264 AnnexB
H.264从1999年开始,到2003年形成草案,最后在2007年定稿有待核实。在ITU的标准⾥称为H.264,在MPEG的标准⾥是MPEG-4的⼀个组成部分–MPEG-4 Part 10,⼜叫Advanced Video Codec,因此常常称为MPEG-4 AVC或直接叫AVC。
福大大架构师每日一题
2023/06/09
6700
音视频八股文(8)-- h264 AnnexB
流媒体面试被问到的一些问题汇总!
大家晚上好,今天给大家分享一些我最近利用空闲时间去面试的一些流媒体岗位,面试问的一些问题。
用户6280468
2022/03/21
1.2K0
H264和H265的nalu介绍
本篇介绍下H264和H264的编码格式,包括avcc,annexb,以及转换方法。annexb 用于实时流的场景,avcc用于多媒体文件,如mp4,mkv等场景。
一只小虾米
2022/10/25
2.9K0
H264和H265的nalu介绍
H264码流分析导读
H.264的功能分为两层:视频编码层(VCL, Video Coding Layer)和网络提取层(NAL, Network Abstraction Layer) VCL数据即编码处理的输出,它表示被压缩编码后的视频数据序列。在VCL数据传输或存储之前,这些编码的VCL数据,先被映射或封装进NAL单元中。每个NAL单元包括一个原始字节序列负荷(RBSP, Raw Byte Sequence Payload)、一组对应于视频编码的NAL头信息。RBSP的基本结构是:在原始编码数据的后面填加了结尾比特。一个bit“1”若干比特“0”,以便字节对齐。
deep_sadness
2018/08/30
2.1K0
H264码流分析导读
Android MediaCodec 硬编码 H264 文件
在 Android 4.1 版本提供了 MediaCodec 接口来访问设备的编解码器,不同于 FFmpeg 的软件编解码,它采用的是硬件编解码能力,因此在速度上会比软解更具有优势,但是由于 Android 的碎片化问题,机型众多,版本各异,导致 MediaCodec 在机型兼容性上需要花精力去适配,并且编解码流程不可控,全交由厂商的底层硬件去实现,最终得到的视频质量不一定很理想。
音视频开发进阶
2019/11/18
3.6K0
H.264码流结构及QP值提取
在H.264中,量化参数分3个级别给出:图像参数集(pps)、片头(slice_header)、宏块(mb)。
walkerfang
2019/08/25
5.5K0
H.264码流结构及QP值提取
h264解码器基础学习(1)
相信很多人和我一样,刚开始的时候都会很好奇,为什么h264可以实现这么强大的压缩比,要知道,1张1080p的YUV420就是3MB,想实现1秒钟30帧,千兆网就基本跑满了,这也太可怕了,基本上只有条件很好的局域网才能达到这个水平。但是h264的出现把这个数据量降到了百分之一,2个数量级,这实在太可怕了,技术的发展真的是强大。
用户6280468
2023/09/12
7220
h264解码器基础学习(1)
H.264 媒体流 AnnexB 和 AVCC 格式分析 及 FFmpeg 解析mp4的H.264码流方法
来源:https://blog.csdn.net/shaosunrise/article/details/121548065
音视频开发进阶
2022/10/31
2.4K0
音视频开发之旅(56) -H264/AVC基本结构
音视频编码的标准由标准发展组织制定,主要两大组织:ISO(国际标准化组织和国际电工委员会)和ITU-T(国际电信联盟的电信标准化部门)
音视频开发之旅
2021/09/04
1K0
Android 音视频系列:H264视频编码介绍
H264视频编码技术,是对序列帧图像进行压缩的技术。压缩之所以可能,是因为存在冗余数据。
天天P图攻城狮
2018/06/28
2.6K3
「Android音视频编码那点破事」第八章,X264实现H264编码以及MediaMuxer的另类用法
  x264是目前使用最广泛、效率最高的h264编码库,著名的音视频处理库ffmpeg也支持x264的扩展。如果你的项目用于商业用途,建议选用免费的openh264。   相比x264,可能著名的ffmpeg更广为人知。但是我们为什么不使用ffmpeg呢。正如本系列文章的序章所说,如果你只是打算用于h264编码,完全没必要使用庞大复杂ffmpeg,反而选择短小精悍的x264更适合你。不仅可以使用更小的so库(这在移动平台很有必要),而且也不需要再去啃ffmpeg枯燥复杂的代码。我是前前后后看了五遍才勉强看懂,一直处于看了又忘,忘了又看的状态,似会非会的叠加状态。相比之下x264的流程更为短小清晰,使用更为简单。
阿利民
2022/05/16
1.1K0
「Android音视频编码那点破事」第八章,X264实现H264编码以及MediaMuxer的另类用法
Android音视频H264码流结构
format,这个是官方h264协议文档中规定的格式,所以它是大多数编码器默认的编码后的输出格式。它的基本数据单位为NAL单元,简称NALU`(Network
花落花相惜
2021/11/24
6410
推荐阅读
相关推荐
FFmpeg开发笔记(三十)解析H.264码流中的SPS帧和PPS帧
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验