av_rescale_q和av_rescale_q_rnd和av_rescale_rnd

简介: av_rescale_q和av_rescale_q_rnd和av_rescale_rnd

首先这三个函数所实践的都是a*b/c,它们所做的就是完善一下舍入方案,举个例子考虑c为0的情况等,三个函数的源码比较一下。

int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
{
    return av_rescale_q_rnd(a, bq, cq, AV_ROUND_NEAR_INF);
}
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);
}


可以看出av_rescale_q就是调用了av_rescale_q_rnd,只是第四个参数默认为AV_ROUND_NEAR_INF。

int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd)
{
    int64_t r = 0;
    av_assert2(c > 0);
    av_assert2(b >=0);
    av_assert2((unsigned)(rnd&~AV_ROUND_PASS_MINMAX)<=5 && (rnd&~AV_ROUND_PASS_MINMAX)!=4);
    if (c <= 0 || b < 0 || !((unsigned)(rnd&~AV_ROUND_PASS_MINMAX)<=5 && (rnd&~AV_ROUND_PASS_MINMAX)!=4))
        return INT64_MIN;
    if (rnd & AV_ROUND_PASS_MINMAX) {
        if (a == INT64_MIN || a == INT64_MAX)
            return a;
        rnd -= AV_ROUND_PASS_MINMAX;
    }
    if (a < 0 && a != INT64_MIN)
        return -av_rescale_rnd(-a, b, c, rnd ^ ((rnd >> 1) & 1));
    if (rnd == AV_ROUND_NEAR_INF)
        r = c / 2;
    else if (rnd & 1)
        r = c - 1;
    if (b <= INT_MAX && c <= INT_MAX) {
        if (a <= INT_MAX)
            return (a * b + r) / c;
        else
            return a / c * b + (a % c * b + r) / c;
    } else {
#if 1
        uint64_t a0  = a & 0xFFFFFFFF;
        uint64_t a1  = a >> 32;
        uint64_t b0  = b & 0xFFFFFFFF;
        uint64_t b1  = b >> 32;
        uint64_t t1  = a0 * b1 + a1 * b0;
        uint64_t t1a = t1 << 32;
        int i;
        a0  = a0 * b0 + t1a;
        a1  = a1 * b1 + (t1 >> 32) + (a0 < t1a);
        a0 += r;
        a1 += a0 < r;
        for (i = 63; i >= 0; i--) {
            a1 += a1 + ((a0 >> i) & 1);
            t1 += t1;
            if (c <= a1) {
                a1 -= c;
                t1++;
            }
        }
        return t1;
    }
#else
        AVInteger ai;
        ai = av_mul_i(av_int2i(a), av_int2i(b));
        ai = av_add_i(ai, av_int2i(r));
        return av_i2int(av_div_i(ai, av_int2i(c)));
    }
#endif
}


可以看出av_rescale_q_rnd就是调用了av_rescale_rnd,只是做了一些完善。


image.png

相关文章
|
26天前
|
API
FFmpeg中AVPacket、AVFrame结构的基本使用
FFmpeg中AVPacket和AVFrame结构的内存分配、释放和引用计数处理,以及如何避免内存泄漏。
24 3
|
6月前
|
传感器 缓存 安全
内容安全(AV)
内容安全(AV)
54 6
ffmpeg编码报错:more samples than frame size (avcodec_encode_audio2)
ffmpeg编码报错:more samples than frame size (avcodec_encode_audio2)
109 0
ffmpeg编码报错:more samples than frame size (avcodec_encode_audio2)
|
6月前
|
编解码 算法 C++
【ffmpeg 基础函数】详解FFmpeg中的av_packet_ref函数
【ffmpeg 基础函数】详解FFmpeg中的av_packet_ref函数
61 0
|
缓存 编解码 Ubuntu
avcodec_send_frame和avcodec_receive_packet
avcodec_send_frame和avcodec_receive_packet
322 0
avcodec_send_frame和avcodec_receive_packet
|
容器
FFmpeg读取文件内容AVPacket
FFmpeg读取文件内容AVPacket
226 0
|
存储 编解码 Android开发
【Android FFMPEG 开发】FFMPEG 解码 AVPacket 数据到 AVFrame ( AVPacket->解码器 | 初始化 AVFrame | 解码为 AVFrame 数据 )
【Android FFMPEG 开发】FFMPEG 解码 AVPacket 数据到 AVFrame ( AVPacket->解码器 | 初始化 AVFrame | 解码为 AVFrame 数据 )
302 0
|
存储 编解码 Android开发
【Android FFMPEG 开发】FFMPEG 读取音视频流中的数据到 AVPacket ( 初始化 AVPacket 数据 | 读取 AVPacket )
【Android FFMPEG 开发】FFMPEG 读取音视频流中的数据到 AVPacket ( 初始化 AVPacket 数据 | 读取 AVPacket )
247 0
|
编解码 Rust UED
用Elevator优化AV1视频播放
AOM会员Vimeo通过Elevator改善AV1解码过程中的丢帧和质量下降问题。感谢Google软件工程师姜健对本文做的技术审校。
548 0
用Elevator优化AV1视频播放