From 4c263142c5da89745fb956b3c5738f257c873532 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 4 May 2004 02:58:30 +0000 Subject: [PATCH] use AVInteger in av_rescale() so it can finally do 64*64/64 instead of just 64*32/32 Originally committed as revision 3106 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/avcodec.h | 4 ++-- libavcodec/utils.c | 26 +++++++++++++++----------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 678ae5f7ae..6738293f50 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -17,7 +17,7 @@ extern "C" { #define FFMPEG_VERSION_INT 0x000408 #define FFMPEG_VERSION "0.4.8" -#define LIBAVCODEC_BUILD 4711 +#define LIBAVCODEC_BUILD 4712 #define LIBAVCODEC_VERSION_INT FFMPEG_VERSION_INT #define LIBAVCODEC_VERSION FFMPEG_VERSION @@ -1986,7 +1986,7 @@ int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max) * rescale a 64bit integer. * a simple a*b/c isnt possible as it can overflow */ -int64_t av_rescale(int64_t a, int b, int c); +int64_t av_rescale(int64_t a, int64_t b, int64_t c); /** diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 6998f77223..d08c630317 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -27,7 +27,9 @@ #include "avcodec.h" #include "dsputil.h" #include "mpegvideo.h" +#include "integer.h" #include +#include static void avcodec_default_free_buffers(AVCodecContext *s); @@ -816,23 +818,25 @@ int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max) return exact; } -int64_t av_rescale(int64_t a, int b, int c){ - uint64_t h, l; +int64_t av_rescale(int64_t a, int64_t b, int64_t c){ + AVInteger ai, ci; assert(c > 0); assert(b >=0); if(a<0) return -av_rescale(-a, b, c); - h= a>>32; - if(h==0) return a*b/c; + if(b<=INT_MAX && c<=INT_MAX){ + if(a<=INT_MAX) + return (a * b + c/2)/c; + else + return a/c*b + (a%c*b + c/2)/c; + } - l= a&0xFFFFFFFF; - l *= b; - h *= b; - - l += (h%c)<<32; - - return ((h/c)<<32) + l/c; + ai= av_mul_i(av_int2i(a), av_int2i(b)); + ci= av_int2i(c); + ai= av_add_i(ai, av_shr_i(ci,1)); + + return av_i2int(av_div_i(ai, ci)); } /* av_log API */