• ffmpeg 中av_rescale_rnd 的含义


    ffmpeg 中av_rescale_rnd 的含义

    我看了网上若干帖子,包括分析代码的,感觉都说得不是太清晰,所以自己也来说说.

    函数声明:
    int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd)
    它的作用是计算 "a * b / c" 的值

    我们把这个函数的名称翻译为"重新计算(rescale)并且取整(round)方便我们记忆!

    由于其结果不一定能整除,但其结果是一个整数,所以就牵扯一个取整问题,
    这里它定义了五种取整方式

    enum AVRounding {
        AV_ROUND_ZERO     = 0, ///< Round toward zero.
        AV_ROUND_INF      = 1, ///< Round away from zero.
        AV_ROUND_DOWN     = 2, ///< Round toward -infinity.
        AV_ROUND_UP       = 3, ///< Round toward +infinity.
        AV_ROUND_NEAR_INF = 5, ///< Round to nearest and halfway cases away from zero.
        AV_ROUND_PASS_MINMAX = 8192, //这个位是个附加位,必需与其它位组合使用,所以算5种模式
    };
    我们先把英文的翻译成汉文:

    AV_ROUND_ZERO ,向0舍入,解释为趋于0,是什么意思?
    AV_ROUND_INF ,向无穷舍入,解释为远离0,是什么意思?
    AV_ROUND_DOWN, 向下舍入,注释为趋于负无穷
    AV_ROUND_UP,  向上舍入,注释为趋于正无穷
    AV_ROUND_NEAR_INF 就近无穷, 解释为向最近的方向,1半的化要远离0, 总之就是4舍5入的意思
    AV_ROUND_PASS_MINMAX = 8192, //这个位置位时,当a=INT64_MIN或a=INT64_MAX时  a值pass throuth

    这么绕, 翻译了也不是太清楚,嗯, 我们从容易理解的地方着手!
    我们可以容易理解的是3种:
    1. 向上舍入就是入       例如: 123.1 向上舍入为124, 123.9向上舍入为124
    2. 向下舍入就是舍        例如: 123.1 向下舍入为123, 123.9向下舍入为123
    3. 4舍5入,        例如: 123.1 4舍5入为123, 123.9 4舍5入为124, 123.5 舍5入为124

    那趋于0舍入,趋于无穷舍入又是什么玩意?


    下面看代码, 我没有直接复制,没必要,拣关键的说明问题:
    在(libavutil/mathematics.c):58行 (ffmpeg4.4)
    int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd)

    1. 当有AV_ROUND_PASS_MINMAX 标志时,如果时INT64_MIN,INT64_MAX, 直接返回a
        if (rnd & AV_ROUND_PASS_MINMAX) {
            if (a == INT64_MIN || a == INT64_MAX)
                return a;
        }

    2. 其它核心运算
        r = 0;                            //默认余数为0,实际包含了模式0(AV_ROUND_ZERO),模式2(AV_ROUND_DOWN)
        if (rnd == AV_ROUND_NEAR_INF)    //这是模式5(AV_ROUND_NEAR_INF)
            r = c / 2;                    //当4舍5入时,我们取余数为c/2
        else if (rnd & 1)                //这里包含了模式1(AV_ROUND_INF),模式3(AV_ROUND_UP)
            r = c - 1;                    //当趋于无穷或者UP时,取余数c-1
        return (a * b + r) / c;            // 计算(a*b+余数)/c

        由此我们看到,其实不是五种舍入方式,还是3种舍入方式.
        所谓的趋于0舍入就是下舍入。
        所谓的趋于无穷舍入就是上舍入。
        搞得这么玄幻,何必呢? 可能是历史原因吧.


    在FFmpeg中,  一般不直接调用av_rescale_rnd, 而是使用 av_rescale_q_rnd
    它的意义是以bq为时基表示的数值a, 表达成以cq为时基的数值, 计算方式为: a*bq/cq
    它的声明及代码如下:
    int64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq, enum AVRounding rnd)
    {
        int64_t b = bq.num * (int64_t)cq.den;
        int64_t c = cq.num * (int64_t)bq.den;
        return av_rescale_rnd(a, b, c, rnd);
    }

    例如:
        常见的视频帧时长3600 是以 90K为时基(1,90000)表示成1M时基(1,1000000)
        3600*(1/90000)/(1/1000000)=3600*100/9=40000 (us) = 40(ms) 等于 25帧/s
        用函数表示:
        av_rescale_q_rnd(duration,base_90k,base_us);

  • 相关阅读:
    Day18_8 Java学习之缓冲流、转换流与序列化流
    #QT(网络文件下载)
    100.一个linux内核选项对ssh的影响
    SSM+医院移动收费运维平台 毕业设计-附源码161045
    栈,队列与循环队列 模拟
    【无标题】
    如何在Ubuntu系统部署RabbitMQ服务器并公网访问【内网穿透】
    R语言lavaan结构方程模型在复杂网络分析中的科研技术新趋势
    分布式系统原理-BASE,可用性高于强一致性
    最小可用产品MVP,投石问路
  • 原文地址:https://blog.csdn.net/hejinjing_tom_com/article/details/128036892