From: Manuel Lauss via ffmpeg-devel <ffmpeg-devel@ffmpeg.org> To: ffmpeg-devel@ffmpeg.org Cc: Manuel Lauss <code@ffmpeg.org> Subject: [FFmpeg-devel] [PATCH] WIP: avcodec/sanm: blubb-1 (PR #20307) Date: Thu, 21 Aug 2025 23:02:24 +0300 (EEST) Message-ID: <20250821200224.7EF3F6800A8@ffbox0-bg.ffmpeg.org> (raw) PR #20307 opened by Manuel Lauss (mlauss2) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20307 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20307.patch From 81464c509dfece2e6a17f5608c1b904705c8b7fd Mon Sep 17 00:00:00 2001 From: Manuel Lauss <manuel.lauss@gmail.com> Date: Thu, 21 Aug 2025 22:00:32 +0200 Subject: [PATCH] avcodec/sanm: blubb-1 blubb-2 --- libavcodec/sanm.c | 64 +++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/libavcodec/sanm.c b/libavcodec/sanm.c index 4cf1ac5221..bbc3ad9043 100644 --- a/libavcodec/sanm.c +++ b/libavcodec/sanm.c @@ -277,6 +277,7 @@ typedef struct SANMVideoContext { uint16_t *fbuf, *frm0, *frm1, *frm2; uint8_t *stored_frame; uint32_t fbuf_size, frm0_size, frm1_size, frm2_size; + uint32_t stor_size; uint32_t stored_frame_size; uint8_t *rle_buf; @@ -471,9 +472,11 @@ static av_cold int init_buffers(SANMVideoContext *ctx) av_fast_padded_mallocz(&ctx->frm0, &ctx->frm0_size, ctx->buf_size); av_fast_padded_mallocz(&ctx->frm1, &ctx->frm1_size, ctx->buf_size); av_fast_padded_mallocz(&ctx->frm2, &ctx->frm2_size, ctx->buf_size); - if (!ctx->version) + if (!ctx->version) { av_fast_padded_mallocz(&ctx->stored_frame, &ctx->stored_frame_size, ctx->buf_size); + ctx->stor_size = 0; + } if (!ctx->frm0 || !ctx->frm1 || !ctx->frm2 || (!ctx->stored_frame && !ctx->version)) { @@ -1660,7 +1663,8 @@ static int old_codec48(SANMVideoContext *ctx, int width, int height) return 0; } -static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) +static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb, + int xoff, int yoff) { uint16_t w, h, parm2; uint8_t codec, param; @@ -1669,14 +1673,14 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) codec = bytestream2_get_byteu(gb); param = bytestream2_get_byteu(gb); - left = bytestream2_get_le16u(gb); - top = bytestream2_get_le16u(gb); + left = bytestream2_get_le16u(gb) + xoff; + top = bytestream2_get_le16u(gb) + yoff; w = bytestream2_get_le16u(gb); h = bytestream2_get_le16u(gb); bytestream2_skip(gb, 2); parm2 = bytestream2_get_le16u(gb); - if (w < 1 || h < 1 || w > 800 || h > 600 || left > 800 || top > 600 || left + w <= 0 || top + h <= 0) { + if (w < 1 || h < 1 || w > 640 || h > 480 || left > 640 || top > 480 || left + w <= 0 || top + h <= 0) { av_log(ctx->avctx, AV_LOG_WARNING, "ignoring invalid fobj dimensions: c%d %d %d @ %d %d\n", codec, w, h, left, top); @@ -1700,7 +1704,7 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) if (w > xres || h > yres) return AVERROR_INVALIDDATA; ctx->have_dimensions = 1; - } else if (codec == 37 || codec == 47 || codec == 48) { + } else if (fsc) { /* these codecs work on full frames, trust their dimensions */ xres = w; yres = h; @@ -1716,7 +1720,7 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) xres = w; yres = h; ctx->have_dimensions = 1; - } else if (((xres == 424) && (yres == 260)) || /* RA1 */ + } else if (((xres == 424) && (yres == 260)) || /* RA2 */ ((xres == 320) && (yres == 200)) || /* ft/dig/... */ ((xres == 640) && (yres == 480))) { /* ol/comi/mots... */ ctx->have_dimensions = 1; @@ -1750,6 +1754,10 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) } } + /* users of codecs>=37 are subversion 2, enforce that for STOR/FTCH */ + if (fsc) + ctx->subversion = 2; + /* clear the main buffer on the first fob */ if (ctx->first_fob) { ctx->first_fob = 0; @@ -1819,41 +1827,25 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) static int process_ftch(SANMVideoContext *ctx, int size) { - uint8_t *sf = ctx->stored_frame; - int xoff, yoff, left, top, ret; + int xoff, yoff, ret; GetByteContext gb; - uint32_t sz; /* FTCH defines additional x/y offsets */ - if (size != 12) { - if (bytestream2_get_bytes_left(&ctx->gb) < 6) - return AVERROR_INVALIDDATA; + if (size == 6) { bytestream2_skip(&ctx->gb, 2); xoff = bytestream2_get_le16u(&ctx->gb); yoff = bytestream2_get_le16u(&ctx->gb); - } else { - if (bytestream2_get_bytes_left(&ctx->gb) < 12) - return AVERROR_INVALIDDATA; + } else if (size == 12) { bytestream2_skip(&ctx->gb, 4); xoff = bytestream2_get_be32u(&ctx->gb); yoff = bytestream2_get_be32u(&ctx->gb); - } - - sz = *(uint32_t *)(sf + 0); - if ((sz > 0) && (sz <= ctx->stored_frame_size - 4)) { - /* add the FTCH offsets to the left/top values of the stored FOBJ */ - left = av_le2ne16(*(int16_t *)(sf + 4 + 2)); - top = av_le2ne16(*(int16_t *)(sf + 4 + 4)); - *(int16_t *)(sf + 4 + 2) = av_le2ne16(left + xoff); - *(int16_t *)(sf + 4 + 4) = av_le2ne16(top + yoff); + } else + return 1; + if (ctx->stor_size > 0) { /* decode the stored FOBJ */ - bytestream2_init(&gb, sf + 4, sz); - ret = process_frame_obj(ctx, &gb); - - /* now restore the original left/top values again */ - *(int16_t *)(sf + 4 + 2) = av_le2ne16(left); - *(int16_t *)(sf + 4 + 4) = av_le2ne16(top); + bytestream2_init(&gb, ctx->stored_frame, ctx->stor_size); + ret = process_frame_obj(ctx, &gb, xoff, yoff); } else { /* this happens a lot in RA1: The individual files are meant to * be played in sequence, with some referencing objects STORed @@ -2360,8 +2352,10 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, case MKBETAG('F', 'O', 'B', 'J'): if (size < 16) return AVERROR_INVALIDDATA; - if (ret = process_frame_obj(ctx, &ctx->gb)) + if (ret = process_frame_obj(ctx, &ctx->gb, 0, 0)) { + to_store = 0; return ret; + } have_img = 1; /* STOR: for ANIMv0/1 store the whole FOBJ datablock, as it @@ -2372,12 +2366,12 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, if (to_store) { to_store = 0; if (ctx->subversion < 2) { - if (size + 4 <= ctx->stored_frame_size) { + if (size <= ctx->stored_frame_size) { int pos2 = bytestream2_tell(&ctx->gb); bytestream2_seek(&ctx->gb, pos, SEEK_SET); - *(uint32_t *)(ctx->stored_frame) = size; - bytestream2_get_bufferu(&ctx->gb, ctx->stored_frame + 4, size); + bytestream2_get_bufferu(&ctx->gb, ctx->stored_frame, size); bytestream2_seek(&ctx->gb, pos2, SEEK_SET); + ctx->stor_size = size; } else { av_log(avctx, AV_LOG_ERROR, "FOBJ too large for STOR\n"); ret = AVERROR(ENOMEM); -- 2.49.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
reply other threads:[~2025-08-21 20:02 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20250821200224.7EF3F6800A8@ffbox0-bg.ffmpeg.org \ --to=ffmpeg-devel@ffmpeg.org \ --cc=code@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git