FFmpeg有理数相关的源码:AVRational结构体和其相关的函数分析

news2025/1/11 12:48:04

一、引言

有理数是整数(正整数、0、负整数)和分数的统称,是整数和分数的集合。整数也可看作是分母是1的分数。不是有理数的实数称为无理数,即无理数的小数部分是无限不循环的数。

AVRational是FFmpeg源码中的一个结构体,用来抽象有理数。为什么不使用double类型(浮点数)呢?虽然有理数可以表示为浮点数,但浮点操作的转换过程是一个有损过程,使用浮点数计算可能会导致有理数出现精度误差;另一方面,FFmpeg的特性要求高精度的时间戳计算。AVRational结构体和其相关函数可以作为一个通用接口,用于操作作为分子和分母对的有理数。
AVRational相关的函数都带有`_q`后缀,表示数学符号“ℚ”(Q),表示所有有理数的集合。

二、AVRational结构体的声明

AVRational结构体定义在FFmpeg源码(本文演示用的FFmpeg源码版本为7.0.1)的头文件libavutil/rational.h中:

/**
 * Rational number (pair of numerator and denominator).
 */
typedef struct AVRational{
    int num; ///< Numerator
    int den; ///< Denominator
} AVRational;

FFmpeg源码中使用AVRational结构体来表示有理数。

成员变量num:有理数的分子

成员变量den:有理数的分母

三、av_make_q函数的定义

av_make_q函数定义在libavutil/rational.h中:

/**
 * Create an AVRational.
 *
 * Useful for compilers that do not support compound literals.
 *
 * @note The return value is not reduced.
 * @see av_reduce()
 */
static inline AVRational av_make_q(int num, int den)
{
    AVRational r = { num, den };
    return r;
}

其作用是:给有理数的分子和分母赋值并返回。

形参num:输入型参数。传递给有理数分子的值。执行av_make_q函数后,有理数分子的值为num。

形参den:输入型参数。传递给有理数分母的值。执行av_make_q函数后,有理数分母的值为den。

返回值:返回被赋值的AVRational类型的有理数。

四、av_cmp_q函数的定义

(一)av_cmp_q函数的定义

av_cmp_q函数定义在libavutil/rational.h中:

/**
 * Compare two rationals.
 *
 * @param a First rational
 * @param b Second rational
 *
 * @return One of the following values:
 *         - 0 if `a == b`
 *         - 1 if `a > b`
 *         - -1 if `a < b`
 *         - `INT_MIN` if one of the values is of the form `0 / 0`
 */
static inline int av_cmp_q(AVRational a, AVRational b){
    const int64_t tmp= a.num * (int64_t)b.den - b.num * (int64_t)a.den;

    if(tmp) return (int)((tmp ^ a.den ^ b.den)>>63)|1;
    else if(b.den && a.den) return 0;
    else if(a.num && b.num) return (a.num>>31) - (b.num>>31);
    else                    return INT_MIN;
}

其作用是:比较两个有理数的大小。

形参a:输入型参数。被比较的第一个有理数。

形参b:输入型参数。被比较的第二个有理数。

返回值:如果a的值等于b,返回0;如果a>b,返回1;如果a<b,返回-1;如果a或b中有一个有理数的分子和分母同时为0,返回`INT_MIN`(-2147483648)。注意:这函数非常奇怪,如果a或b中有一个有理数的分子不为0但分母为0,这函数不会返回`INT_MIN`;只有当a或b中有一个有理数的分子和分母同时为0,才会返回`INT_MIN`。我们都知道有理数的分母是不能等于零的,分母等于零是没有意义的。av_cmp_q函数内部没有对a和b中分子不为0但分母为0的情况进行处理。所以在使用该函数之前最好要先在其外部判断a和b分母是否为0,避免被比较的有理数分母出现0的情况。

(二)av_cmp_q函数的使用例子

编写测试例子main.c,在Ubuntu中使用9.4.0版本的gcc编译通过:

#include <stdio.h>
#include <stdint.h>
#include <limits.h>

typedef struct AVRational{
    int num; ///< Numerator
    int den; ///< Denominator
} AVRational;


static inline AVRational av_make_q(int num, int den)
{
    AVRational r = { num, den };
    return r;
}


static inline int av_cmp_q(AVRational a, AVRational b){
    const int64_t tmp= a.num * (int64_t)b.den - b.num * (int64_t)a.den;

    if(tmp) return (int)((tmp ^ a.den ^ b.den)>>63)|1;
    else if(b.den && a.den) return 0;
    else if(a.num && b.num) return (a.num>>31) - (b.num>>31);
    else                    return INT_MIN;
}


int main()
{
    AVRational a = av_make_q(1, 2);
    AVRational b = av_make_q(1, 3);
    printf("av_cmp_q(a, b): %d\n", av_cmp_q(a, b));

    AVRational c = av_make_q(65536, 1);
    AVRational d = av_make_q(2, 0);
    printf("av_cmp_q(c, d): %d\n", av_cmp_q(c, d));

    AVRational e = av_make_q(0, 0);
    AVRational f = av_make_q(1, 3);
    printf("av_cmp_q(e, f): %d\n", av_cmp_q(e, f));

    return 0;
}

输出如下:

五、av_q2d函数的定义

av_q2d函数定义在libavutil/rational.h中:

/**
 * Convert an AVRational to a `double`.
 * @param a AVRational to convert
 * @return `a` in floating-point form
 * @see av_d2q()
 */
static inline double av_q2d(AVRational a){
    return a.num / (double) a.den;
}

该函数作用是:将有理数从AVRational类型转换为double类型(双精度浮点数)。该操作可能会造成精度丢失。

形参a:输入型参数。被转换的有理数。

返回值:由形参a转换出来的double类型数值。

六、av_reduce函数的定义

av_reduce函数可以用来计算视频帧率。关于该函数的用法可以参考:《音视频入门基础:H.264专题(15)——FFmpeg源码中通过SPS属性获取视频帧率的实现》。

七、av_mul_q函数的定义

av_mul_q函数定义在libavutil/rational.c中:

/**
 * Multiply two rationals.
 * @param b First rational
 * @param c Second rational
 * @return b*c
 */
AVRational av_mul_q(AVRational b, AVRational c)
{
    av_reduce(&b.num, &b.den,
               b.num * (int64_t) c.num,
               b.den * (int64_t) c.den, INT_MAX);
    return b;
}

该函数作用是:将有理数b * c的结果作为返回值返回。

八、av_div_q函数的定义

av_div_q函数定义在libavutil/rational.c中:

/**
 * Divide one rational by another.
 * @param b First rational
 * @param c Second rational
 * @return b/c
 */
AVRational av_div_q(AVRational b, AVRational c)
{
    return av_mul_q(b, (AVRational) { c.den, c.num });
}

该函数作用是:将有理数b ÷ c的结果作为返回值返回。

九、av_add_q函数的定义

av_add_q函数定义在libavutil/rational.c中:

/**
 * Add two rationals.
 * @param b First rational
 * @param c Second rational
 * @return b+c
 */
AVRational av_add_q(AVRational b, AVRational c) {
    av_reduce(&b.num, &b.den,
               b.num * (int64_t) c.den +
               c.num * (int64_t) b.den,
               b.den * (int64_t) c.den, INT_MAX);
    return b;
}

该函数作用是:将有理数b + c的结果作为返回值返回。

十、av_sub_q函数的定义

av_sub_q函数定义在libavutil/rational.c中:

/**
 * Subtract one rational from another.
 * @param b First rational
 * @param c Second rational
 * @return b-c
 */
AVRational av_sub_q(AVRational b, AVRational c)
{
    return av_add_q(b, (AVRational) { -c.num, c.den });
}

该函数作用是:将有理数b - c的结果作为返回值返回。

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

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

相关文章

企业邮箱如何支持免费试用?

企业邮箱如何支持免费试用&#xff1f;Zoho企业邮箱提供多种版本&#xff0c;支持免费试用&#xff0c;具备权威认证、信息安全、全球部署等特点。试用步骤包括访问官网、选择版本、输入信息、验证域名等。特色功能包括定制化界面、搜索、日程安排等。支持多种设备和操作系统。…

linux内核:文件系统的组织(超级块,索引节点,目录项,文件对象)

在虚拟文件系统中抽象了4个对象&#xff1a;超级块、索引节点、目录项和文件对象。 超级块&#xff1a;存放描述文件系统的有关信息。每个文件系统都有自己的超级块&#xff0c;不同文件系统的超级块不同。文件系统的超级块在文件系统安装时建立&#xff0c;在卸载时自动删除。…

【问题解决方案】npm install报错问题:npm ERR! - 多种解决方案,总有一种可以解决

文章目录 1.问题重述2.解决方案方案1.确认根目录正确方案2.确认文件名正确方案3. 确认node.js安装完成&#xff08;注意这个环境变量配置没有写完&#xff09;方案4 改用yarn安装&#xff08;亲测可用&#xff09; 3.延申问题解决方案问题1&#xff1a;需要低版本的node.js 写在…

【计算机毕业设计】727网上拍卖系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

【ArcGIS+CityEngine】自行制作Lod1城市大尺度白膜数据

数据准备 50多个城市建筑矢量数据 链接&#xff1a;https://pan.baidu.com/s/1FiwTfXDwQ6tMDRACAwUZwQ 提取码&#xff1a;DYSK 数据分析 数据属性Floor&#xff0c;为建筑物楼层信息&#xff0c;据此信息下面将在CityEngine软件生成Lod1白膜数据。 软件准备 CityEngi…

MMPV+MMRV 打开物料账期

开物料账期&#xff1a;MMPV 查看物料账期&#xff1a;MMRV 可以看到当前期间和上一期间。 允许过账到上一期间&#xff1a;过账日期可以改到上一月。 物料账期只能一个月一个月的开&#xff0c;不能跨月开。最多打开两个月。 财务账期OB52

Introduction to Data Analysis with PySpark

1.DataFrame and RDDs 2.Spark Architecture 3. Data Formats and Data Sources 倘若您觉得我写的好&#xff0c;那么请您动动你的小手粉一下我&#xff0c;你的小小鼓励会带来更大的动力。Thanks.

【组合数学】【Python】【小练习】一、斯特灵近似式求阶乘

一、问题介绍 斯特灵&#xff08;Stirling&#xff09;近似式&#xff0c;是数学分析中&#xff0c;用于求阶乘近似值的一个常用公式&#xff0c;其简单的表述形式为&#xff1a; 二、Python实现 使用Python&#xff0c;循环从n1至n98&#xff0c;分别输出n的阶乘值、斯特灵公…

在 Debian Bookworm XFCE4 桌面环境中安装原生版 微信

絮絮叨叨&#xff1a; 最近在做一个POC验证&#xff0c;为了启用足够多的虚拟机集群&#xff0c;把自己办公 Debian 重装了&#xff0c;装成了XFCE4桌面环境&#xff0c;需要在这个桌面环境上安装常用的办公与会议工具&#xff0c;既满足POC验证环境所需、又不耽误办公写文档 …

超好用的图片批量处理工具,电商人都在用!你还不知道?

作为一名电商运营人或者经常和图片打交道的小伙伴&#xff0c;是不是经常被大量图片的处理工作搞得焦头烂额&#xff1f;今天我必须给大家分享一个超级实用的宝贝工具——图片批量处理神器&#xff01; 神器介绍&#x1f447; 千鹿设计助手&#xff0c;是一款轻量级、功能非常…

如何应对,AI发展带来的就业挑战和机遇?

机遇与挑战并存 AI Job Impact AI时代的就业挑战 随着AI技术的飞速发展&#xff0c;它对全球就业市场产生了深远影响。一方面&#xff0c;一些传统职位正逐渐被自动化取代&#xff1b;另一方面&#xff0c;AI也创造了大量新兴职位。面对这一变革&#xff0c;我们需积极适应&…

【Python实战因果推断】69_图因果模型4

目录 Querying a Graph in Python Querying a Graph in Python 在接下来的时刻&#xff0c;你将把这个图输入到一个Python库中&#xff0c;这将使得回答关于它的问题变得相当容易。但在你这样做之前&#xff0c;作为一项练习&#xff0c;为了更好地理解你刚刚学到的概念&#x…

(七)Appdesigner-初步入门及常用组件的使用方法说明

目录 前言 一、Appsesigner初步入门 &#xff08;一&#xff09;Appsesigner简介 &#xff08;二&#xff09;功能布局 二、常用组件 &#xff08;一&#xff09;基础知识 &#xff08;二&#xff09;实际操作 1.HTML 2.下拉框 3.切换按钮组 4.列表框 5.单选按钮组…

ShardingSphere实战(4)- 广播表和默认数据源

上篇博客&#xff0c;我们讲了 ShardingSphere实战&#xff08;3&#xff09;- 快速实现分库分表 &#xff0c;这篇博客&#xff0c;我们解决分库分表以后遗留的两个小问题。 一、广播表 1. 广播表介绍 广播表&#xff08;Broadcast Table&#xff09;是一种特殊的表类型&am…

SSM学习10:整合MyBatis、MyBatisPlus

SpringBoot整合MyBatis 与创建spring web项目类型&#xff0c;添加上相应依赖 实体类 public class Account {private int id;public int getId() {return id;}public void setId(int id) {this.id id;}public String getName() {return name;}public void setName(String …

word打印---doc转html后进行打印,window.print、print-js、vue-print-nb

提示&#xff1a;word预览方式—插件 文章目录 [TOC](文章目录) 前言一、vue-office-docx把docx转换html二、调取window.print三、print-js四、vue-print-nb总结 前言 word预览 一、vue-office-docx把docx转换html npm install vue-office-docx -S-DofficeDocx.vue <templ…

Meta发布最新图形分割模型SAM 2:实时视频分割性能大幅提升

Meta发布最新图形分割模型SAM 2:实时视频分割性能大幅提升 在人工智能领域,图形分割是一项重要的技术,它能够识别和提取图像或视频中的目标对象。Meta近期发布的SAM 2(Segment Anything 2)模型在这一领域取得了重大突破。本文将详细介绍SAM 2的创新之处及其在视频对象实时…

vue3学习day02-组合式API-setup选项、reactive(将非响应式数据变为响应式数据)、computed(基本思想和vue2一致)、watch

6、setup选项 &#xff08;1&#xff09;setup选项的执行时机&#xff08;获取不到this&#xff0c;this是undefined&#xff09;&#xff1a;beforeCreate函数之前&#xff0c;自动执行 &#xff08;2&#xff09;写法 1&#xff09;原始写法 需要返回 ①在script中导出s…

【DeepSeek-V2 技术要点介绍】

DeepSeek-V2 是一款基于 Transformer 架构的先进模型&#xff0c;其中每个Transformer块由一个注意力模块和一个前馈网络&#xff08;FFN)组成。然而&#xff0c;对于注意力模块和 FFN&#xff0c;研究团队设计并采用了创新的架构。旨在通过创新的设计提升推理和训练效率。以下…

行为验证码的分类推荐

行为验证码 行为验证码是一种用于确认用户身份或验证用户行为的技术手段&#xff0c;通常用于防止自动化程序&#xff08;例如机器人&#xff09;对网站或应用程序进行恶意操作。它的核心思想是通过要求用户执行特定的交互动作来验证其为真实的人类 是一种通过用户的操作行为…