音视频入门基础:H.264专题(11)——计算视频分辨率的公式

一、引言

通过FFmpeg命令可以获取到H.264裸流文件的视频分辨率:

在vlc中也可以获取到视频分辨率(vlc底层也使用了FFmpeg进行解码):

所以FFmpeg和vlc是怎样获取到H.264编码的视频的分辨率呢?它们其实是通过SPS中的属性(pic_width_in_mbs_minus1、pic_height_in_map_units_minus1 、frame_mbs_only_flag、frame_cropping_flag、chroma_format_idc、SubWidthC、SubHeightC、frame_crop_left_offset、frame_crop_right_offset、frame_crop_top_offset、frame_crop_bottom_offset)解析出这个视频的宽高的。

网上广泛流传的计算视频宽高的公式为:

width = (pic_width_in_mbs_minus1 + 1) * 16;
height = (pic_height_in_map_units_minus1 + 1) * 16;

这是不严谨的,因为某些视频的宽高不是16的倍数。而且还得考虑特殊情况,也就是场编码的情况。

二、根据H.264官方文档得到真正计算视频分辨率的公式

上述属性在H.264官方文档《T-REC-H.264-202108-I!!PDF-E.pdf》第44页到45页描述:

根据H.264官方文档《T-REC-H.264-202108-I!!PDF-E.pdf》第78页:

pic_width_in_mbs_minus1加1是指以宏块为单位的每个解码图像的宽度。

以宏块为单元的图像宽度变量PicWidthInMbs=pic_width_in_mbs_minus1 + 1。

亮度分量的图像宽度变量PicWidthInSamplesL=PicWidthInMbs * 16

pic_height_in_map_units_minus1加1表示以条带组映射为单位的一个解码帧或场的高度。PicHeightInMapUnits=pic_height_in_map_units_minus1+1。

PicSizeInMapUnits=PicWidthInMbs * PicHeightInMapUnits

FrameHeightInMbs = ( 2 – frame_mbs_only_flag ) * PicHeightInMapUnits

根据第22页:

在单色采样中只有一个样点阵列,名义上当做亮度阵列。

在4:2:0样点中,两个色度阵列的高度和宽度均为亮度阵列的一半。

在4:2:2样点中,两个色度阵列的高度等于亮度阵列的高度,宽度为亮度阵列的一半。

在4:2:4样点中,两个色度阵列的高度和宽度与亮度阵列的相等。

SPS属性中的chroma_format_idc = 0,并且separate_colour_plane_flag = 0时,色度格式为单色,此时SubWidthC和SubHeightC没有意义。

chroma_format_idc = 1,并且separate_colour_plane_flag = 0时,色度格式为YUV420,此时SubWidthC为2,SubHeightC为2。

chroma_format_idc = 2,并且separate_colour_plane_flag = 0时,色度格式为YUV422,此时SubWidthC为2,SubHeightC为1。

chroma_format_idc = 3,并且separate_colour_plane_flag = 0时,色度格式为YUV444,此时SubWidthC为1,SubHeightC为1。

chroma_format_idc = 3,并且separate_colour_plane_flag = 1时,色度格式为YUV444,此时SubWidthC和SubHeightC没有意义。

根据第79页:

如果chroma_format_idc等于0,CropUnitX和CropUnitY按下列方式计算:

CropUnitX = 1

CropUnitY = 2- frame_mbs_only_flag

否则(chroma_format_idc等于1、2或3),CropUnitX和CropUnitY按下列公式计算:

CropUnitX = SubWidthC

CropUnitY = SubHeightC * (2 - frame_mbs_only_flag)

当frame_cropping_flag等于0时,frame_crop_left_offset、frame_crop_right_offset、frame_crop_top_offset和frame_crop_bottom_offset的值应等于0。

根据第385页:

输出裁剪后的帧区域的宽度CroppedWidth = PicWidthInSamplesL − CropUnitX * ( frame_crop_left_offset + frame_crop_right_offset )

输出裁剪后的帧区域的高度 CroppedHeight = 16 * FrameHeightInMbs − CropUnitY * ( frame_crop_top_offset + frame_crop_bottom_offset )
其中CroppedWidth和CroppedHeight可以认为是视频的宽高。

三、得到最终计算视频分辨率的公式

综上所述,计算H.264编码的视频分辨率的公式为:
int SubWidthC;
int SubHeightC;if (sps->chroma_format_idc == 0 && sps->separate_colour_plane_flag == 0) { //monochromeSubWidthC = SubHeightC = 0;
}
else if (sps->chroma_format_idc == 1 && sps->separate_colour_plane_flag == 0) { //4:2:0 SubWidthC = SubHeightC = 2;
}
else if (sps->chroma_format_idc == 2 && sps->separate_colour_plane_flag == 0) { //4:2:2 SubWidthC = 2;SubHeightC = 1;
}
else if (sps->chroma_format_idc == 3) { //4:4:4if (sps->separate_colour_plane_flag == 0) {SubWidthC = SubHeightC = 1;}else if (sps->separate_colour_plane_flag == 1) {SubWidthC = SubHeightC = 0;}
}int PicWidthInMbs = sps->pic_width_in_mbs_minus1 + 1;int PicHeightInMapUnits = sps->pic_height_in_map_units_minus1 + 1;
int FrameHeightInMbs = (2 - sps->frame_mbs_only_flag) * PicHeightInMapUnits;int crop_left = 0;
int crop_right = 0;
int crop_top = 0;
int crop_bottom = 0;if (sps->frame_cropping_flag) {crop_left = sps->frame_crop_left_offset;crop_right = sps->frame_crop_right_offset;crop_top = sps->frame_crop_top_offset;crop_bottom = sps->frame_crop_bottom_offset;
}int width = PicWidthInMbs * 16 - SubWidthC * (crop_left + crop_right);
int height = FrameHeightInMbs * 16 - SubHeightC * (2 - sps->frame_mbs_only_flag) * (crop_top + crop_bottom);

四、计算视频分辨率的例子

假如某个H.264编码的视频的SPS中的chroma_format_idc值为1,pic_width_in_mbs_minus1值为79,pic_height_in_map_units_minus1值为44,frame_mbs_only_flag值为1,frame_cropping_flag值为0,如下所示:

由于chroma_format_idc等于3的情况下,separate_colour_plane_flag才有意义。上述chroma_format_idc的值为1,所以separate_colour_plane_flag值为默认的0:
所以根据最终计算公式:
SubWidthC = SubHeightC = 2,int PicWidthInMbs
= sps->pic_width_in_mbs_minus1 + 1
= 79 + 1
= 80int PicHeightInMapUnits
= sps->pic_height_in_map_units_minus1 + 1
= 45int FrameHeightInMbs
= (2 - sps->frame_mbs_only_flag) * PicHeightInMapUnits
= (2 - 1) * 45
= 45int width = PicWidthInMbs * 16 - SubWidthC * (crop_left + crop_right)
= 80 * 16 - 2* (0 + 0)
= 1280int height = FrameHeightInMbs * 16 - SubHeightC * (2 - sps->frame_mbs_only_flag) * (crop_top + crop_bottom)
= 45 * 16 - 2 * (2 - 1) * (0 + 0)
= 720

所以该视频的分辨率为1280 * 720。

五、参考文章

《H264 getting frame height and width from sequence parameter set (SPS) NAL unit》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/44664.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入理解Java并发、线程与等待通知机制

目录 一、基础概念 进程和线程 进程 线程 Java 线程的无处不在 进程间的通信 进程间通信有几种方式? CPU 核心数和线程数的关系 上下文切换(Context switch) 并行和并发 二、认识 Java 里的线程 Java 程序天生就是多线程的 线程…

华为机考真题 -- 密码解密

题目描述: 给定一段"密文"字符串 s, 其中字符都是经过"密码本"映射的,现需要将"密文"解密并且输出映射的规则 (a - i)分别用(1 - 9)表示;(j - z)分别用(10* - 26*)表示约束:映射始终唯…

STM32学习和实践笔记(39):I2C EEPROM实验

1.I2C总线介绍 I2C(Inter-Integrated Circuit)总线是由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备,是微电子通信控制领域广泛采用的一种总线标准。 它是同步通信的一种特殊形式,具有接口线少,控制方式简单,器件封装形式小,通信速率较高等优点。I…

一套基于 Ant Design 和 Blazor 的开源企业级组件库

前言 今天大姚给大家分享一套基于Ant Design和Blazor的开源(MIT License)、免费的企业级组件库(喜欢Ant Design风格的同学推荐使用):Ant Design Blazor。 项目特性 提炼自企业级中后台产品的交互语言和视觉风格。 开…

Java核心技术【二十二】Java的I/O流处理:深入文件读写操作、缓冲流、序列化与NIO

Java的I/O流处理:深入文件读写操作、缓冲流、序列化 在Java编程中,I/O流是处理输入输出操作的基础,特别是在文件读写、网络通信等领域。本文将在前文的基础上,进一步探讨缓冲流、序列化以及NIO(New I/O)在…

大数据开发者如何快速熟悉新公司业务

作为一名大数据开发工程师,进入一家新公司后快速熟悉业务是至关重要的。 目录 1. 了解产品形态故事1:电商平台的数据分析故事2:金融科技的风控系统故事3:社交媒体的推荐算法 2. 了解业务流程故事1:物流配送系统的优化故事2:医疗保险的理赔流程故事3:银行的贷款审批流程 3. 走…

通过 tomcat 让手机访问到电脑写的 html 网页

之前实现的 html 小项目只能在自己的电脑上展示,如果要在其他电脑或者在手机上就看不到网页了 想要在手机上访问自己写的网页,我们可以借助 tomcat 首先我们可以从官网下载 tomcat 官网链接:apache官网 我们拉到最底部,找到 a…

科普文:Java对象在堆中的内存结构

概叙 今天来讲些抽象的东西 -- 对象头,因为我在学习的过程中发现很多地方都关联到了对象头的知识点,例如JDK中的 synchronized锁优化 和 JVM 中对象年龄升级等等。 对象内存构成# Java 中通过 new 关键字创建一个类的实例对象,对象存于内存的…

7.10日学习打卡----初学Redis(五)

7.10日学习打卡 目录: 7.10日学习打卡一. redis功能流水线pipeline什么是流水线?pipeline实现使用pipeline 发布与订阅Redis的发布与订阅发布订阅命令行实现 慢查询Redis命令执行的整个过程如何进行配置实践建议 二 . redis的持久化机制RDB持久化机制触发…

Golang | Leetcode Golang题解之第227题基本计算器II

题目&#xff1a; 题解&#xff1a; func calculate(s string) (ans int) {stack : []int{}preSign : num : 0for i, ch : range s {isDigit : 0 < ch && ch < 9if isDigit {num num*10 int(ch-0)}if !isDigit && ch ! || i len(s)-1 {switch preS…

洞察消费者心理:Transformer模型在消费者行为分析的创新应用

洞察消费者心理&#xff1a;Transformer模型在消费者行为分析的创新应用 在数字化时代&#xff0c;消费者行为分析对于企业理解市场动态、制定营销策略至关重要。Transformer模型&#xff0c;以其在处理序列数据方面的优势&#xff0c;为消费者行为分析提供了新的视角和工具。…

【大模型】解码LLM:GPT-3与LaMDA的架构比较与对比

解码LLM&#xff1a;GPT-3与LaMDA的架构比较与对比 引言一、GPT-3&#xff1a;解密大规模预训练的奥秘1.1 架构概览1.2 关键技术1.3 应用场景 二、LaMDA&#xff1a;对话智能的新篇章2.1 架构概览2.2 关键技术2.3 应用场景 三、比较与对比&#xff1a;GPT-3 vs. LaMDA3.1 架构设…

JavaSE学习笔记第二弹——对象和多态(下)

今天我们继续复习与JavaSE相关的知识&#xff0c;使用的编译器仍然是IDEA2022&#xff0c;大家伙使用eclipse或其他编译环境是一样的&#xff0c;都可以。 目录 数组 定义 一维数组 ​编辑 二维数组 多维数组 数组的遍历 for循环遍历 ​编辑 foreach遍历 封装、继承和…

宝塔:如何开启面板ssl并更新过期ssl

1、登录宝塔面板 > 前往面板设置 > 最上方的安全设置 > 面板SSL > 面板SSL配置 打开后先查看自签证书的时间&#xff0c;如果时间是已经过期的&#xff0c;就前往这个目录&#xff0c;将该目录下所有文件都删掉 重新回到面板SSL配置的位置&#xff0c;打开后会看到…

【山东大学】web数据管理——复习笔记

写在前面 若有图片加载失败&#xff0c;请科学上网 。本文为对软件学院连老师的PPT课件总结所得的复习笔记&#xff0c;仅供参考。不保证对考点的全覆盖&#xff0c;以PPT为主。对往年考过的题相关知识点前面都标注了“考过”&#xff0c;并高亮&#xff0c;供参考。写的比较匆…

iCloud数据宝库:全方位掌握笔记应用数据存储

iCloud数据宝库&#xff1a;全方位掌握笔记应用数据存储 在数字化时代&#xff0c;我们的日常生活和工作中产生了大量的笔记数据&#xff0c;这些数据的安全性、可访问性和同步性至关重要。苹果的iCloud服务提供了一个强大而便捷的解决方案&#xff0c;允许用户在所有设备上存…

【PB案例学习笔记】-31制作一个动态设置菜单的程序

写在前面 这是PB案例学习笔记系列文章的第31篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gite…

初识C++语言(1)

目录 C语言简介 C 语言概述 C 语言的特点 语言简洁紧凑&#xff0c;使用灵活方便 运算符丰富 数据结构丰富 结构化语言 生成的代码质量高 可移植性强 C程序结构 C语言系统的使用 一.启动Dev-C 二、新建源程序 三…

星辰计划02-独特视角的spring动态代理

承接上一文 动态代理 &#xff0c;这里探究spring 动态代理 会话1&#xff1a;spring动态代理 quick start &#x1f467;哥哥&#xff0c;哥哥&#xff0c;spring 怎么去搞动态代理的呢&#x1f468; 来来来&#xff0c;听我细细来说 quick start通过Spring的 ProxyFactory…

nvm安装node一直没有npm

报错问题&#xff1a;使用nvm安装Node.js后没有npm。 解释&#xff1a; NVM (Node Version Manager) 是一个用于管理Node.js版本的工具&#xff0c;它允许你在同一台机器上安装和使用不同版本的Node.js。通常情况下&#xff0c;安装Node.js的过程中会自动包含npm&#xff08;…