OSDN Git Service

use AVInteger in av_rescale() so it can finally do 64*64/64 instead of just 64*32/32
authorMichael Niedermayer <michaelni@gmx.at>
Tue, 4 May 2004 02:58:30 +0000 (02:58 +0000)
committerMichael Niedermayer <michaelni@gmx.at>
Tue, 4 May 2004 02:58:30 +0000 (02:58 +0000)
Originally committed as revision 3106 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavcodec/avcodec.h
libavcodec/utils.c

index 678ae5f..6738293 100644 (file)
@@ -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);
 
 
 /**
index 6998f77..d08c630 100644 (file)
@@ -27,7 +27,9 @@
 #include "avcodec.h"
 #include "dsputil.h"
 #include "mpegvideo.h"
+#include "integer.h"
 #include <stdarg.h>
+#include <limits.h>
 
 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 */