This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit e33260809c06572a7423fc689ddb681aecdd81bc
Author:     Andreas Rheinhardt <[email protected]>
AuthorDate: Mon Mar 16 22:44:57 2026 +0100
Commit:     Andreas Rheinhardt <[email protected]>
CommitDate: Thu Mar 19 14:44:08 2026 +0100

    avcodec/x86/mpeg4videodsp: Fix sprite_warping_accuracy 0-2
    
    MPEG-4 GMC uses the following motion prediction scheme:
    For output pixel (x,y), the reference pixel at fractional
    coordinates (ox+dxx*x+dxy*y,oy+dyx*x+dyy*y) is used as prediction;
    the latter is calculated via bilinear interpolation. The coefficients
    here are fixed-point values with 16+shift fractional bits
    where shift is sprite_warping_accuracy+1. For the weights,
    only the shift most significant fractional bits are used.
    shift can be at most four*.
    
    The x86 MMX gmc implementation performs these calculations
    using 16-bit words. To do so, it restricts itself to the case
    in which the four least significant bits of dxx,dxy,dyx,dyy
    are zero and shifts these bits away. Yet in case shift is
    less than four, the 16 bits retained also contain at least
    one bit that actually belongs to the fpel component
    (which is already taken into account by using the correct
    pixels for interpolation).
    
    (This has been uncovered by a to-be-added checkasm test.
    I don't know whether there are actual files in the wild
    using sprite_warping_accuracy 0-2.)
    
    *: It is always four when encoding with xvid and GMC.
    
    Reviewed-by: Lynne <[email protected]>
    Signed-off-by: Andreas Rheinhardt <[email protected]>
---
 libavcodec/x86/mpeg4videodsp.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/libavcodec/x86/mpeg4videodsp.c b/libavcodec/x86/mpeg4videodsp.c
index 6a1c6c5064..a5984ed120 100644
--- a/libavcodec/x86/mpeg4videodsp.c
+++ b/libavcodec/x86/mpeg4videodsp.c
@@ -33,12 +33,16 @@ static void gmc_mmx(uint8_t *dst, const uint8_t *src,
     const int w    = 8;
     const int ix   = ox  >> (16 + shift);
     const int iy   = oy  >> (16 + shift);
-    const int oxs  = ox  >> 4;
-    const int oys  = oy  >> 4;
-    const int dxxs = dxx >> 4;
+    const int ox2  = ox & (1 << (16 + shift)) - 1;
+    const int oy2  = oy & (1 << (16 + shift)) - 1;
+    const int oxs  = ox2 >> 4;
+    const int oys  = oy2 >> 4;
+    const int dxx2 = dxx - (1 << (16 + shift));
+    const int dyy2 = dyy - (1 << (16 + shift));
+    const int dxxs = dxx2 >> 4;
     const int dxys = dxy >> 4;
     const int dyxs = dyx >> 4;
-    const int dyys = dyy >> 4;
+    const int dyys = dyy2 >> 4;
     const uint16_t r4[4]   = { r, r, r, r };
     const uint16_t dxy4[4] = { dxys, dxys, dxys, dxys };
     const uint16_t dyy4[4] = { dyys, dyys, dyys, dyys };
@@ -48,8 +52,8 @@ static void gmc_mmx(uint8_t *dst, const uint8_t *src,
     uint8_t edge_buf[(MAX_H + 1) * MAX_STRIDE];
     int x, y;
 
-    const int dxw = (dxx - (1 << (16 + shift))) * (w - 1);
-    const int dyh = (dyy - (1 << (16 + shift))) * (h - 1);
+    const int dxw = dxx2 * (w - 1);
+    const int dyh = dyy2 * (h - 1);
     const int dxh = dxy * (h - 1);
     const int dyw = dyx * (w - 1);
     int need_emu  =  (unsigned) ix >= width  - w || width < w ||
@@ -57,8 +61,8 @@ static void gmc_mmx(uint8_t *dst, const uint8_t *src,
                      ;
 
     if ( // non-constant fullpel offset (3% of blocks)
-        ((ox ^ (ox + dxw)) | (ox ^ (ox + dxh)) | (ox ^ (ox + dxw + dxh)) |
-         (oy ^ (oy + dyw)) | (oy ^ (oy + dyh)) | (oy ^ (oy + dyw + dyh))) >> 
(16 + shift) ||
+        ((ox2 + dxw) | (ox2 + dxh) | (ox2 + dxw + dxh) |
+         (oy2 + dyw) | (oy2 + dyh) | (oy2 + dyw + dyh)) >> (16 + shift) ||
         // uses more than 16 bits of subpel mv (only at huge resolution)
         (dxx | dxy | dyx | dyy) & 15 ||
         (need_emu && (h > MAX_H || stride > MAX_STRIDE))) {

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to