avcodec/sanm: codec37 buffers are private

codec37 operates on 2 buffers, which must be considered private to
the codec and must therefore not be changed by subsequent FOBJs.

Let codec37 therefore operate on frm1/2 instead of frm0/2, but copy
the decoded image to frm0 where other codecs operate on.

Fixes artifacts encountered in Full Throttle "dazed.san" and also
in a lot of Rebel Assault II gameplay videos: these videos consist of
frames with an initial codec37 FOBJ image to set the stage, and
optional codec1-23 FOBJs overlaid on top of that image.

Signed-off-by: Manuel Lauss <manuel.lauss@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
Manuel Lauss 2025-01-13 22:00:24 +01:00 committed by Michael Niedermayer
parent 4322be512b
commit d68d311bcd
No known key found for this signature in database
GPG key ID: B18E8928B3948D64

View file

@ -645,10 +645,11 @@ static int old_codec37(SANMVideoContext *ctx, int top,
ctx->rotate_code = 0;
if (((seq & 1) || !(flags & 1)) && (compr && compr != 2))
rotate_bufs(ctx, 1);
if (((seq & 1) || !(flags & 1)) && (compr && compr != 2)) {
FFSWAP(uint16_t*, ctx->frm1, ctx->frm2);
}
dst = ((uint8_t*)ctx->frm0) + left + top * stride;
dst = ((uint8_t*)ctx->frm1) + left + top * stride;
prev = ((uint8_t*)ctx->frm2) + left + top * stride;
if (mvoff > 2) {
@ -662,7 +663,6 @@ static int old_codec37(SANMVideoContext *ctx, int top,
bytestream2_get_buffer(&ctx->gb, dst, width);
dst += stride;
}
memset(ctx->frm1, 0, ctx->height * stride);
memset(ctx->frm2, 0, ctx->height * stride);
break;
case 1:
@ -729,7 +729,6 @@ static int old_codec37(SANMVideoContext *ctx, int top,
case 2:
if (rle_decode(ctx, dst, decoded_size))
return AVERROR_INVALIDDATA;
memset(ctx->frm1, 0, ctx->frm1_size);
memset(ctx->frm2, 0, ctx->frm2_size);
break;
case 3:
@ -783,6 +782,7 @@ static int old_codec37(SANMVideoContext *ctx, int top,
return AVERROR_PATCHWELCOME;
}
memcpy(ctx->frm0, ctx->frm1, ctx->buf_size);
return 0;
}