[FFmpeg-devel] [PATCH] libavcodec/sanm: implement codec37 subcodec1
Manuel Lauss
manuel.lauss at gmail.com
Tue Jan 7 16:46:09 EET 2025
RLE-compressed stream of motion vector indices and a special opcode
to fill a block with data from the source stream.
It is used in the LucasArts "Full Throttle" blink*.san animations.
Signed-off-by: Manuel Lauss <manuel.lauss at gmail.com>
---
libavcodec/sanm.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 63 insertions(+), 1 deletion(-)
diff --git a/libavcodec/sanm.c b/libavcodec/sanm.c
index a278ef24b1..b6e599c120 100644
--- a/libavcodec/sanm.c
+++ b/libavcodec/sanm.c
@@ -625,7 +625,7 @@ static int old_codec37(SANMVideoContext *ctx, int top,
int left, int width, int height)
{
ptrdiff_t stride = ctx->pitch;
- int i, j, k, t;
+ int i, j, k, l, t;
uint8_t *dst, *prev;
int skip_run = 0;
int compr = bytestream2_get_byte(&ctx->gb);
@@ -665,6 +665,68 @@ static int old_codec37(SANMVideoContext *ctx, int top,
memset(ctx->frm1, 0, ctx->height * stride);
memset(ctx->frm2, 0, ctx->height * stride);
break;
+ case 1:
+ int run = 0;
+ int len = -1;
+ int code = 0;
+ int skip, mx, my;
+
+ for (j = 0; j < height; j += 4) {
+ for (i = 0; i < width; i += 4) {
+ if (len < 0) {
+ if (bytestream2_get_bytes_left(&ctx->gb) < 1)
+ return AVERROR_INVALIDDATA;
+ code = bytestream2_get_byte(&ctx->gb);
+ len = code >> 1;
+ run = code & 1;
+ skip = 0;
+ } else {
+ skip = run;
+ }
+
+ if (!skip) {
+ if (bytestream2_get_bytes_left(&ctx->gb) < 1)
+ return AVERROR_INVALIDDATA;
+ code = bytestream2_get_byte(&ctx->gb);
+ if (code == 0xff) {
+ len--;
+ for (k = 0; k < 4; k++) {
+ for (l = 0; l < 4; l++) {
+ if (len < 0) {
+ if (bytestream2_get_bytes_left(&ctx->gb) < 1)
+ return AVERROR_INVALIDDATA;
+ code = bytestream2_get_byte(&ctx->gb);
+ len = code >> 1;
+ run = code & 1;
+ if (run) {
+ if (bytestream2_get_bytes_left(&ctx->gb) < 1)
+ return AVERROR_INVALIDDATA;
+ code = bytestream2_get_byte(&ctx->gb);
+ }
+ }
+ if (!run) {
+ if (bytestream2_get_bytes_left(&ctx->gb) < 1)
+ return AVERROR_INVALIDDATA;
+ code = bytestream2_get_byte(&ctx->gb);
+ }
+ *(dst + i + (k * stride) + l) = code;
+ len--;
+ }
+ }
+ continue;
+ }
+ }
+ /* 4x4 block copy from prev with MV */
+ mx = c37_mv[(mvoff * 255 + code) * 2];
+ my = c37_mv[(mvoff * 255 + code) * 2 + 1];
+ codec37_mv(dst + i, prev + i + mx + my * stride,
+ ctx->height, stride, i + mx, j + my);
+ len--;
+ }
+ dst += stride * 4;
+ prev += stride * 4;
+ }
+ break;
case 2:
if (rle_decode(ctx, dst, decoded_size))
return AVERROR_INVALIDDATA;
--
2.47.1
More information about the ffmpeg-devel
mailing list