[FFmpeg-devel] [PATCH] sanm.c: Implement codec21.
Reimar Döffinger
Reimar.Doeffinger at gmx.de
Sat Apr 2 14:29:46 CEST 2016
Used for cockpit in
http://samples.mplayerhq.hu/game-formats/la-san/rebelassault/L8PLAY.ANM
Signed-off-by: Reimar Döffinger <Reimar.Doeffinger at gmx.de>
---
libavcodec/sanm.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 44 insertions(+), 1 deletion(-)
diff --git a/libavcodec/sanm.c b/libavcodec/sanm.c
index 6aeaa2c..277949e 100644
--- a/libavcodec/sanm.c
+++ b/libavcodec/sanm.c
@@ -602,6 +602,43 @@ static int old_codec1(SANMVideoContext *ctx, int top,
return 0;
}
+static int old_codec21(SANMVideoContext *ctx, int top,
+ int left, int width, int height)
+{
+ uint8_t *dst = ((uint8_t *)ctx->frm0) + left + top * ctx->pitch;
+ int i, len, end;
+
+ for (i = 0; i < height; i++) {
+ int pos = 0;
+ if (bytestream2_get_bytes_left(&ctx->gb) < 4)
+ return AVERROR_INVALIDDATA;
+
+ bytestream2_skip(&ctx->gb, 2); // 00 01 in the files tested
+ end = bytestream2_tell(&ctx->gb);
+ len = bytestream2_get_le16u(&ctx->gb);
+ end += len;
+
+ while (bytestream2_tell(&ctx->gb) < end) {
+ int count;
+ if (bytestream2_get_bytes_left(&ctx->gb) < 4)
+ return AVERROR_INVALIDDATA;
+
+ pos += bytestream2_get_le16u(&ctx->gb);
+ count = bytestream2_get_le16u(&ctx->gb) + 1;
+ if (pos + count > width)
+ return AVERROR_INVALIDDATA;
+ if (bytestream2_get_bytes_left(&ctx->gb) < count)
+ return AVERROR_INVALIDDATA;
+ bytestream2_get_bufferu(&ctx->gb, dst + pos, count);
+ pos += count;
+ }
+ dst += ctx->pitch;
+ }
+ ctx->rotate_code = 0;
+
+ return 0;
+}
+
static inline void codec37_mv(uint8_t *dst, const uint8_t *src,
int height, int stride, int x, int y)
{
@@ -1125,6 +1162,10 @@ static int process_frame_obj(SANMVideoContext *ctx)
return AVERROR_INVALIDDATA;
}
+ // ignore negative values (padding?)
+ if (left & 0x8000) left = 0;
+ if (top & 0x8000) top = 0;
+
if (ctx->width < left + w || ctx->height < top + h) {
int ret = ff_set_dimensions(ctx->avctx, FFMAX(left + w, ctx->width),
FFMAX(top + h, ctx->height));
@@ -1137,7 +1178,7 @@ static int process_frame_obj(SANMVideoContext *ctx)
return AVERROR(ENOMEM);
}
}
- bytestream2_skip(&ctx->gb, 4);
+ bytestream2_skip(&ctx->gb, codec == 21 ? 2 : 4);
switch (codec) {
case 1:
@@ -1147,6 +1188,8 @@ static int process_frame_obj(SANMVideoContext *ctx)
ctx->prev_codec = codec;
return old_codec1(ctx, top, left, w, h);
break;
+ case 21:
+ return old_codec21(ctx, top, left, w, h);
case 37:
if (ctx->prev_codec == 1) FFSWAP(uint16_t*, ctx->frm0, ctx->frm1);
ctx->prev_codec = codec;
--
2.7.0
More information about the ffmpeg-devel
mailing list