1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Copyright (c) 2005-2012 Michael Niedermayer <michaelni@gmx.at> 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * This file is part of FFmpeg. 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 7cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 8cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 9cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 10cabdff1aSopenharmony_ci * 11cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 12cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 13cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14cabdff1aSopenharmony_ci * Lesser General Public License for more details. 15cabdff1aSopenharmony_ci * 16cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 17cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 18cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19cabdff1aSopenharmony_ci */ 20cabdff1aSopenharmony_ci 21cabdff1aSopenharmony_ci/** 22cabdff1aSopenharmony_ci * @file 23cabdff1aSopenharmony_ci * miscellaneous math routines and tables 24cabdff1aSopenharmony_ci */ 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_ci#include <stdint.h> 27cabdff1aSopenharmony_ci#include <limits.h> 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_ci#include "avutil.h" 30cabdff1aSopenharmony_ci#include "mathematics.h" 31cabdff1aSopenharmony_ci#include "libavutil/intmath.h" 32cabdff1aSopenharmony_ci#include "libavutil/common.h" 33cabdff1aSopenharmony_ci#include "avassert.h" 34cabdff1aSopenharmony_ci 35cabdff1aSopenharmony_ci/* Stein's binary GCD algorithm: 36cabdff1aSopenharmony_ci * https://en.wikipedia.org/wiki/Binary_GCD_algorithm */ 37cabdff1aSopenharmony_ciint64_t av_gcd(int64_t a, int64_t b) { 38cabdff1aSopenharmony_ci int za, zb, k; 39cabdff1aSopenharmony_ci int64_t u, v; 40cabdff1aSopenharmony_ci if (a == 0) 41cabdff1aSopenharmony_ci return b; 42cabdff1aSopenharmony_ci if (b == 0) 43cabdff1aSopenharmony_ci return a; 44cabdff1aSopenharmony_ci za = ff_ctzll(a); 45cabdff1aSopenharmony_ci zb = ff_ctzll(b); 46cabdff1aSopenharmony_ci k = FFMIN(za, zb); 47cabdff1aSopenharmony_ci u = llabs(a >> za); 48cabdff1aSopenharmony_ci v = llabs(b >> zb); 49cabdff1aSopenharmony_ci while (u != v) { 50cabdff1aSopenharmony_ci if (u > v) 51cabdff1aSopenharmony_ci FFSWAP(int64_t, v, u); 52cabdff1aSopenharmony_ci v -= u; 53cabdff1aSopenharmony_ci v >>= ff_ctzll(v); 54cabdff1aSopenharmony_ci } 55cabdff1aSopenharmony_ci return (uint64_t)u << k; 56cabdff1aSopenharmony_ci} 57cabdff1aSopenharmony_ci 58cabdff1aSopenharmony_ciint64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd) 59cabdff1aSopenharmony_ci{ 60cabdff1aSopenharmony_ci int64_t r = 0; 61cabdff1aSopenharmony_ci av_assert2(c > 0); 62cabdff1aSopenharmony_ci av_assert2(b >=0); 63cabdff1aSopenharmony_ci av_assert2((unsigned)(rnd&~AV_ROUND_PASS_MINMAX)<=5 && (rnd&~AV_ROUND_PASS_MINMAX)!=4); 64cabdff1aSopenharmony_ci 65cabdff1aSopenharmony_ci if (c <= 0 || b < 0 || !((unsigned)(rnd&~AV_ROUND_PASS_MINMAX)<=5 && (rnd&~AV_ROUND_PASS_MINMAX)!=4)) 66cabdff1aSopenharmony_ci return INT64_MIN; 67cabdff1aSopenharmony_ci 68cabdff1aSopenharmony_ci if (rnd & AV_ROUND_PASS_MINMAX) { 69cabdff1aSopenharmony_ci if (a == INT64_MIN || a == INT64_MAX) 70cabdff1aSopenharmony_ci return a; 71cabdff1aSopenharmony_ci rnd -= AV_ROUND_PASS_MINMAX; 72cabdff1aSopenharmony_ci } 73cabdff1aSopenharmony_ci 74cabdff1aSopenharmony_ci if (a < 0) 75cabdff1aSopenharmony_ci return -(uint64_t)av_rescale_rnd(-FFMAX(a, -INT64_MAX), b, c, rnd ^ ((rnd >> 1) & 1)); 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_ci if (rnd == AV_ROUND_NEAR_INF) 78cabdff1aSopenharmony_ci r = c / 2; 79cabdff1aSopenharmony_ci else if (rnd & 1) 80cabdff1aSopenharmony_ci r = c - 1; 81cabdff1aSopenharmony_ci 82cabdff1aSopenharmony_ci if (b <= INT_MAX && c <= INT_MAX) { 83cabdff1aSopenharmony_ci if (a <= INT_MAX) 84cabdff1aSopenharmony_ci return (a * b + r) / c; 85cabdff1aSopenharmony_ci else { 86cabdff1aSopenharmony_ci int64_t ad = a / c; 87cabdff1aSopenharmony_ci int64_t a2 = (a % c * b + r) / c; 88cabdff1aSopenharmony_ci if (ad >= INT32_MAX && b && ad > (INT64_MAX - a2) / b) 89cabdff1aSopenharmony_ci return INT64_MIN; 90cabdff1aSopenharmony_ci return ad * b + a2; 91cabdff1aSopenharmony_ci } 92cabdff1aSopenharmony_ci } else { 93cabdff1aSopenharmony_ci#if 1 94cabdff1aSopenharmony_ci uint64_t a0 = a & 0xFFFFFFFF; 95cabdff1aSopenharmony_ci uint64_t a1 = a >> 32; 96cabdff1aSopenharmony_ci uint64_t b0 = b & 0xFFFFFFFF; 97cabdff1aSopenharmony_ci uint64_t b1 = b >> 32; 98cabdff1aSopenharmony_ci uint64_t t1 = a0 * b1 + a1 * b0; 99cabdff1aSopenharmony_ci uint64_t t1a = t1 << 32; 100cabdff1aSopenharmony_ci int i; 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_ci a0 = a0 * b0 + t1a; 103cabdff1aSopenharmony_ci a1 = a1 * b1 + (t1 >> 32) + (a0 < t1a); 104cabdff1aSopenharmony_ci a0 += r; 105cabdff1aSopenharmony_ci a1 += a0 < r; 106cabdff1aSopenharmony_ci 107cabdff1aSopenharmony_ci for (i = 63; i >= 0; i--) { 108cabdff1aSopenharmony_ci a1 += a1 + ((a0 >> i) & 1); 109cabdff1aSopenharmony_ci t1 += t1; 110cabdff1aSopenharmony_ci if (c <= a1) { 111cabdff1aSopenharmony_ci a1 -= c; 112cabdff1aSopenharmony_ci t1++; 113cabdff1aSopenharmony_ci } 114cabdff1aSopenharmony_ci } 115cabdff1aSopenharmony_ci if (t1 > INT64_MAX) 116cabdff1aSopenharmony_ci return INT64_MIN; 117cabdff1aSopenharmony_ci return t1; 118cabdff1aSopenharmony_ci#else 119cabdff1aSopenharmony_ci /* reference code doing (a*b + r) / c, requires libavutil/integer.h */ 120cabdff1aSopenharmony_ci AVInteger ai; 121cabdff1aSopenharmony_ci ai = av_mul_i(av_int2i(a), av_int2i(b)); 122cabdff1aSopenharmony_ci ai = av_add_i(ai, av_int2i(r)); 123cabdff1aSopenharmony_ci 124cabdff1aSopenharmony_ci return av_i2int(av_div_i(ai, av_int2i(c))); 125cabdff1aSopenharmony_ci#endif 126cabdff1aSopenharmony_ci } 127cabdff1aSopenharmony_ci} 128cabdff1aSopenharmony_ci 129cabdff1aSopenharmony_ciint64_t av_rescale(int64_t a, int64_t b, int64_t c) 130cabdff1aSopenharmony_ci{ 131cabdff1aSopenharmony_ci return av_rescale_rnd(a, b, c, AV_ROUND_NEAR_INF); 132cabdff1aSopenharmony_ci} 133cabdff1aSopenharmony_ci 134cabdff1aSopenharmony_ciint64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq, 135cabdff1aSopenharmony_ci enum AVRounding rnd) 136cabdff1aSopenharmony_ci{ 137cabdff1aSopenharmony_ci int64_t b = bq.num * (int64_t)cq.den; 138cabdff1aSopenharmony_ci int64_t c = cq.num * (int64_t)bq.den; 139cabdff1aSopenharmony_ci return av_rescale_rnd(a, b, c, rnd); 140cabdff1aSopenharmony_ci} 141cabdff1aSopenharmony_ci 142cabdff1aSopenharmony_ciint64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) 143cabdff1aSopenharmony_ci{ 144cabdff1aSopenharmony_ci return av_rescale_q_rnd(a, bq, cq, AV_ROUND_NEAR_INF); 145cabdff1aSopenharmony_ci} 146cabdff1aSopenharmony_ci 147cabdff1aSopenharmony_ciint av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b) 148cabdff1aSopenharmony_ci{ 149cabdff1aSopenharmony_ci int64_t a = tb_a.num * (int64_t)tb_b.den; 150cabdff1aSopenharmony_ci int64_t b = tb_b.num * (int64_t)tb_a.den; 151cabdff1aSopenharmony_ci if ((FFABS64U(ts_a)|a|FFABS64U(ts_b)|b) <= INT_MAX) 152cabdff1aSopenharmony_ci return (ts_a*a > ts_b*b) - (ts_a*a < ts_b*b); 153cabdff1aSopenharmony_ci if (av_rescale_rnd(ts_a, a, b, AV_ROUND_DOWN) < ts_b) 154cabdff1aSopenharmony_ci return -1; 155cabdff1aSopenharmony_ci if (av_rescale_rnd(ts_b, b, a, AV_ROUND_DOWN) < ts_a) 156cabdff1aSopenharmony_ci return 1; 157cabdff1aSopenharmony_ci return 0; 158cabdff1aSopenharmony_ci} 159cabdff1aSopenharmony_ci 160cabdff1aSopenharmony_ciint64_t av_compare_mod(uint64_t a, uint64_t b, uint64_t mod) 161cabdff1aSopenharmony_ci{ 162cabdff1aSopenharmony_ci int64_t c = (a - b) & (mod - 1); 163cabdff1aSopenharmony_ci if (c > (mod >> 1)) 164cabdff1aSopenharmony_ci c -= mod; 165cabdff1aSopenharmony_ci return c; 166cabdff1aSopenharmony_ci} 167cabdff1aSopenharmony_ci 168cabdff1aSopenharmony_ciint64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int duration, int64_t *last, AVRational out_tb){ 169cabdff1aSopenharmony_ci int64_t a, b, this; 170cabdff1aSopenharmony_ci 171cabdff1aSopenharmony_ci av_assert0(in_ts != AV_NOPTS_VALUE); 172cabdff1aSopenharmony_ci av_assert0(duration >= 0); 173cabdff1aSopenharmony_ci 174cabdff1aSopenharmony_ci if (*last == AV_NOPTS_VALUE || !duration || in_tb.num*(int64_t)out_tb.den <= out_tb.num*(int64_t)in_tb.den) { 175cabdff1aSopenharmony_cisimple_round: 176cabdff1aSopenharmony_ci *last = av_rescale_q(in_ts, in_tb, fs_tb) + duration; 177cabdff1aSopenharmony_ci return av_rescale_q(in_ts, in_tb, out_tb); 178cabdff1aSopenharmony_ci } 179cabdff1aSopenharmony_ci 180cabdff1aSopenharmony_ci a = av_rescale_q_rnd(2*in_ts-1, in_tb, fs_tb, AV_ROUND_DOWN) >>1; 181cabdff1aSopenharmony_ci b = (av_rescale_q_rnd(2*in_ts+1, in_tb, fs_tb, AV_ROUND_UP )+1)>>1; 182cabdff1aSopenharmony_ci if (*last < 2*a - b || *last > 2*b - a) 183cabdff1aSopenharmony_ci goto simple_round; 184cabdff1aSopenharmony_ci 185cabdff1aSopenharmony_ci this = av_clip64(*last, a, b); 186cabdff1aSopenharmony_ci *last = this + duration; 187cabdff1aSopenharmony_ci 188cabdff1aSopenharmony_ci return av_rescale_q(this, fs_tb, out_tb); 189cabdff1aSopenharmony_ci} 190cabdff1aSopenharmony_ci 191cabdff1aSopenharmony_ciint64_t av_add_stable(AVRational ts_tb, int64_t ts, AVRational inc_tb, int64_t inc) 192cabdff1aSopenharmony_ci{ 193cabdff1aSopenharmony_ci int64_t m, d; 194cabdff1aSopenharmony_ci 195cabdff1aSopenharmony_ci if (inc != 1) 196cabdff1aSopenharmony_ci inc_tb = av_mul_q(inc_tb, (AVRational) {inc, 1}); 197cabdff1aSopenharmony_ci 198cabdff1aSopenharmony_ci m = inc_tb.num * (int64_t)ts_tb.den; 199cabdff1aSopenharmony_ci d = inc_tb.den * (int64_t)ts_tb.num; 200cabdff1aSopenharmony_ci 201cabdff1aSopenharmony_ci if (m % d == 0 && ts <= INT64_MAX - m / d) 202cabdff1aSopenharmony_ci return ts + m / d; 203cabdff1aSopenharmony_ci if (m < d) 204cabdff1aSopenharmony_ci return ts; 205cabdff1aSopenharmony_ci 206cabdff1aSopenharmony_ci { 207cabdff1aSopenharmony_ci int64_t old = av_rescale_q(ts, ts_tb, inc_tb); 208cabdff1aSopenharmony_ci int64_t old_ts = av_rescale_q(old, inc_tb, ts_tb); 209cabdff1aSopenharmony_ci 210cabdff1aSopenharmony_ci if (old == INT64_MAX || old == AV_NOPTS_VALUE || old_ts == AV_NOPTS_VALUE) 211cabdff1aSopenharmony_ci return ts; 212cabdff1aSopenharmony_ci 213cabdff1aSopenharmony_ci return av_sat_add64(av_rescale_q(old + 1, inc_tb, ts_tb), ts - old_ts); 214cabdff1aSopenharmony_ci } 215cabdff1aSopenharmony_ci} 216