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]
