FFmpeg开发笔记(二十二)FFmpeg中SAR与DAR的显示宽高比
《FFmpeg开发实战:从零基础到短视频上线》一书提到:通常情况下,在视频流解析之后,从AVCodecContext结构得到的宽高就是视频画面的宽高。然而有的视频文件并非如此,如果按照AVCodecContext设定的宽高展示视频,会发现画面被压扁或者拉长了。比如该书第10章源码playsync.c在播放meg.vob时的视频画面如下图所示:

可见按照现有方式展示的话,视频画面被拉长了。这是因为视频尺寸有三种宽高概念,说明如下:
1、采样宽高比,指的是摄像头在采集画面时,方格内部的宽度与高度的采样点数量比例。采样宽高比的英文叫做“Sample Aspect Ratio”,简称SAR。
2、像素宽高比,指的是视频画面保存到文件时,宽度和高度各占据多少像素。像素宽高比的英文叫做“Pixel Aspect Ratio”,简称PAR。
3、显示宽高比,指的是视频画面渲染到屏幕时,显示出来的宽度与高度比例。显示宽高比的英文叫做“Display Aspect Ratio”,简称DAR。
采样宽高比对应AVCodecParameters结构的sample_aspect_ratio字段,该字段为分数类型AVRational。
像素宽高比对应AVCodecContext结构的width与height两个字段,比例值等于width/height。
显示宽高比对应最终要显示的画面尺寸,该值需要额外计算。多数时候sample_aspect_ratio的num与den均为1,表示宽高两个方向的采样点比例为1:1,此时像素宽高比等于显示宽高比。
由此可见,当sample_aspect_ratio的num与den均为1时,表示像素点是个正方形,此时AVCodecContext结构的宽高就是视频的宽高,无需另外处理。只有sample_aspect_ratio的num不等于den时,表示像素点是个长方形,才需要另外计算显示宽高比,并根据视频高度计算视频的实际宽度。
已知三个宽高比的转换式子如下:
DAR = PAR x SAR
令DAR=实际宽度/实际高度,则代入具体的字段,可得详细的转换式子如下:
实际宽度 width sample_aspect_ratio.num
——————— = —————— X —————————————————————————
实际高度 height sample_aspect_ratio.den
当实际高度为height时,表示保持原画面尺寸,则实际的画面宽度计算式子如下。
sample_aspect_ratio.num
实际宽度 = width X —————————————————————————
sample_aspect_ratio.den
假如已经求得DAR值并保存在变量display_aspect_ratio中,那么实际宽度 = 实际高度 * PAR = 实际高度 * display_aspect_ratio.num / display_aspect_ratio.den。
根据上述所列的几个计算式子,编写如下的宽高比以及实际宽度的求解代码如下所示。
int origin_width = video_decode_ctx->width;
int origin_height = video_decode_ctx->height;
AVRational aspect_ratio = src_video->codecpar->sample_aspect_ratio;
AVRational display_aspect_ratio;
av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
origin_width * aspect_ratio.num,
origin_height * aspect_ratio.den,
1024 * 1024);
av_log(NULL, AV_LOG_INFO, "origin size is %dx%d, SAR %d:%d, DAR %d:%d\n",
origin_width, origin_height,
aspect_ratio.num, aspect_ratio.den,
display_aspect_ratio.num, display_aspect_ratio.den);
int real_width = origin_width;
// 第一种方式:根据SAR的采样宽高比,由原始的宽度算出实际的宽度
if (aspect_ratio.num!=0 && aspect_ratio.den!=0 && aspect_ratio.num!=aspect_ratio.den) {
real_width = origin_width * aspect_ratio.num / aspect_ratio.den;
}
int target_height = 270;
int target_width = target_height*origin_width/origin_height;
// 第二种方式:根据DAR的显示宽高比,由目标的高度算出目标的宽度
if (aspect_ratio.num!=0 && aspect_ratio.den!=0 && aspect_ratio.num!=aspect_ratio.den) {
target_width = target_height * display_aspect_ratio.num / display_aspect_ratio.den;
}
av_log(NULL, AV_LOG_INFO, "real size is %dx%d, target_width=%d, target_height=%d\n",
real_width, origin_height, target_width, target_height);
上述修改后的代码已经附在了《FFmpeg开发实战:从零基础到短视频上线》一书第10章的源码chapter10/playsync2.c中,这个c代码是playsync.c的改进版,能够根据sample_aspect_ratio的宽高比例调整目标视频的画面尺寸。
接着执行下面的编译命令。
gcc playsync2.c -o playsync2 -I/usr/local/ffmpeg/include -L/usr/local/ffmpeg/lib -I/usr/local/sdl2/include -L/usr/local/sdl2/lib -lsdl2 -lavformat -lavdevice -lavfilter -lavcodec -lavutil -lswscale -lswresample -lpostproc -lm
编译完成后执行以下命令启动测试程序,期望播放视频文件meg.vob。
./playsync2 ../meg.vob
程序运行完毕,发现控制台输出以下的日志信息。
Success open input_file ../meg.vob.
origin size is 720x576, SAR 64:45, DAR 16:9
real size is 1024x576, target_width=480, target_height=270
……
同时弹出SDL窗口播放视频画面,如下图所示:

可见画面尺寸符合该视频的实际宽高比例,表示上述代码正确实现了调整视频尺寸的功能。
FFmpeg开发笔记(二十二)FFmpeg中SAR与DAR的显示宽高比的更多相关文章
- FFmpeg开发笔记(十):ffmpeg在ubuntu上的交叉编译移植到海思HI35xx平台
FFmpeg和SDL开发专栏(点击传送门) 上一篇:<FFmpeg开发笔记(九):ffmpeg解码rtsp流并使用SDL同步播放>下一篇:敬请期待 前言 将ffmpeg移植到海思H ...
- 树莓派开发笔记(十二):入手研华ADVANTECH工控树莓派UNO-220套件(一):介绍和运行系统
前言 树莓派也可以做商业应用,工业控制,其稳定性和可靠性已经得到了验证,故而工业控制,一些停车场等场景也有采用树莓派作为主控的,本片介绍了研华ADVANTECH的树莓派套件组UNO-220-P4N ...
- 安卓开发笔记(十二):SQLite数据库储存(上)
SQLite数据库存储(上) 创建数据库 Android专门提供了一个 SQLiteOpenHelper帮助类对数据库进行创建和升级 SQLiteOpenHelper需要创建一个自己的帮助类去继承它并 ...
- .net开发笔记(十二) 设计时与运行时的区别(续)
上一篇博客详细讲到了设计时(DesignTime)和运行时(RunTime)的概念与区别,不过没有给出实际的Demo,今天整理了一下,做了一个例子,贴出来分享一下,巩固前一篇博客讲到的内容. 简单回顾 ...
- Java开发笔记(十二)布尔变量论道与或非
在编程语言的设计之初,它们除了可以进行数学计算,还常常用于逻辑推理和条件判断.为了实现逻辑判断的功能,Java引入了一种布尔类型boolean,用来表示“真”和“假”.该类型的变量只允许两个取值,即t ...
- PID控制器开发笔记之十二:模糊PID控制器的实现
在现实控制中,被控系统并非是线性时不变的,往往需要动态调整PID的参数,而模糊控制正好能够满足这一需求,所以在接下来的这一节我们将讨论模糊PID控制器的相关问题.模糊PID控制器是将模糊算法与PID控 ...
- ESP32 开发笔记(十二)LittlevGL 添加自定义字体和物理按键
LittlevGL 添加自定义字体获取字库 ttf 文件可以从一些网站上获取字库文件,比如请注意字体许可证 生成源文件使用 LittlevGL 提供的字库文件转换工具,将 ttf 字库文件转换为源文件 ...
- Hi3516开发笔记(十):Qt从VPSS中获取通道图像数据存储为jpg文件
前言 上一篇已经将himpp套入qt的基础上进行开发.那么qt中拿到frame则是很关键的交互,这是qt与海思可能编解码交叉开发的关键步骤. 受限制 因为直接配置sample的vi比较麻烦 ...
- python3.4学习笔记(二十二) python 在字符串里面插入指定分割符,将list中的字符转为数字
python3.4学习笔记(二十二) python 在字符串里面插入指定分割符,将list中的字符转为数字在字符串里面插入指定分割符的方法,先把字符串变成list然后用join方法变成字符串str=' ...
- FFmpeg开发笔记(四):ffmpeg解码的基本流程详解
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
随机推荐
- OpenHarmony加速行业应用落地,多款软件发行版正通过兼容性测评
4 月 25 日,OpenAtom OpenHarmony(以下简称"OpenHarmony")技术日在深圳举办,大会聚焦 OpenHarmony 3.1 Release 版本核心 ...
- ArkUI中的线程和看门狗机制
一.前言 本文主要分析ArkUI中涉及的线程和看门狗机制. 二.ArkUI中的线程 应用Ability首次创建界面的流程大致如下: 说明: • AceContainer是一个容器类,由前端.任务执行器 ...
- openEuler20.03操作系统上安装部署MogDB2.1.1
openEuler20.03 操作系统上安装部署 MogDB2.1.1 本文出处:https://www.modb.pro/db/378319 openEuler 操作系统上安装 mogdb: 下载 ...
- 基于Traefik如何实现向后转发自动去掉前缀?
前言 Traefik 是一个现代的 HTTP 反向代理和负载均衡器,使部署微服务变得容易. Traefik 可以与现有的多种基础设施组件(Docker.Swarm 模式.Kubernetes.Mara ...
- chrome浏览器代理插件SwitchyOmega使用
第一步:下载SwitchyOmega插件 Proxy_SwitchyOmega_2.5.21.crx 第二步:安装插件, 1,在chrome扩展程序开启开发者模式: 2,将插件拖过来: 第三步:设置代 ...
- javascript现代编程系列教程之三——数值表示方式
在64位浮点数的表示中,我们使用了一个叫做"偏移二进制"的技术来存储指数.这是因为我们需要在有限的位数(在这种情况下是11位)内表示正数和负数. 让我们更详细地解释一下: 符号位: ...
- next.js app目录 i18n国际化简单实现
最近在用next写一个多语言的项目,找了好久没找到简单实现的教程,实践起来感觉都比较复杂,最后终于是在官方文档找到了,结合网上找到的代码demo,终于实现了,在这里简单总结一下. 此教程适用于比较简单 ...
- 阿里云荣获可信云容器安全能力先进级认证, ACK/ACR为企业级安全护航
阿里云关注企业级用户的Kubernetes生产落地痛点,结合企业生产环境的大量实践,全面帮助企业真正落地云原生架构.安全侧问题,是众多大中型或金融领域企业的核心关注点. 端到端云原生安全架构 早在20 ...
- Spring Cloud Gateway 突发高危漏洞,下一代云原生网关恰逢其时?
简介:Log4j2 的漏洞刚告一段落,Spring 官方在 2022 年 3 月 1 日发布了 Spring Cloud Gateway 的两个 CVE 漏洞:分别为 CVE-2022-22946( ...
- 开课啦 dubbo-go 微服务升级实战
简介: 杭州开课啦教育科技有限公司是一家致力于为中小学生提供学习辅导的在线教育公司,目前公司后端服务基础设施主要依托于阿里云原生,其中包含计算.网络.存储以及 Kubernetes 服务. 技术选型背 ...