avcodec/sanm: bl16: fix artifacts in larger videos
The DOS/Windows decoder precomputes a table of linear offsets of all motion vectors given the current image width. For larger widths (>=762), the pairs starting at indices 1 and 254 of motion_vectors[] will overflow the int16_t, changing the sign. Playing back the 800x600 "jonesopn_8.snm" video of "Indiana Jones and the Infernal Machine" reveals a lot of artifacts and a lot of "Ignoring invalid motion vector (149, -41)->(136, 0), block size = 8" messages, hinting at the wrong direction of the motion vectors. Fix this by doing the calculation that the DOS/Windows players do, let the value overflow and reextract the "new" mvec x/y components.
This commit is contained in:
parent
8426622bb9
commit
0226b6fb2c
1 changed files with 14 additions and 0 deletions
|
|
@ -2074,6 +2074,20 @@ static int codec2subblock(SANMVideoContext *ctx, int cx, int cy, int blk_size)
|
||||||
mx = motion_vectors[opcode][0];
|
mx = motion_vectors[opcode][0];
|
||||||
my = motion_vectors[opcode][1];
|
my = motion_vectors[opcode][1];
|
||||||
|
|
||||||
|
/* The original implementation of this codec precomputes a table
|
||||||
|
* of int16_t all motion vectors for given image width.
|
||||||
|
* For larger widths, starting with 762 pixels, the calculation of
|
||||||
|
* mv table indices 1+ and 255- overflow the int16_t, inverting the
|
||||||
|
* sign of the offset. This is actively exploited in e.g. the
|
||||||
|
* "jonesopn_8.snm" video of "Indiana Jones and the Infernal Machine".
|
||||||
|
* Therefore let the overflow happen and extract x/y components from
|
||||||
|
* the new value.
|
||||||
|
*/
|
||||||
|
if (ctx->width > 761) {
|
||||||
|
index = (int16_t)(my * ctx->width + mx);
|
||||||
|
mx = index % ctx->width;
|
||||||
|
my = index / ctx->width;
|
||||||
|
}
|
||||||
if (good_mvec(ctx, cx, cy, mx, my, blk_size)) {
|
if (good_mvec(ctx, cx, cy, mx, my, blk_size)) {
|
||||||
copy_block(ctx->frm0 + cx + ctx->pitch * cy,
|
copy_block(ctx->frm0 + cx + ctx->pitch * cy,
|
||||||
ctx->frm2 + cx + mx + ctx->pitch * (cy + my),
|
ctx->frm2 + cx + mx + ctx->pitch * (cy + my),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue