From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.ffmpeg.org (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id 6F1D44223B for ; Tue, 19 Aug 2025 11:16:36 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTP id BB3ED68D493; Tue, 19 Aug 2025 14:16:31 +0300 (EEST) Received: from c1ad6a1ecdc3 (code.ffmpeg.org [188.245.149.3]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTPS id 5AD4868D485 for ; Tue, 19 Aug 2025 14:16:30 +0300 (EEST) MIME-Version: 1.0 To: ffmpeg-devel@ffmpeg.org Subject: [FFmpeg-devel] =?utf-8?q?=5BPATCH=5D_avcodec/sanm=3A_mv_and_oob_?= =?utf-8?q?fixes_=28PR_=2320284=29?= X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Manuel Lauss via ffmpeg-devel Reply-To: FFmpeg development discussions and patches Cc: Manuel Lauss Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Message-Id: <20250819111631.BB3ED68D493@ffbox0-bg.ffmpeg.org> Date: Tue, 19 Aug 2025 14:16:31 +0300 (EEST) Archived-At: List-Archive: List-Post: PR #20284 opened by Manuel Lauss (mlauss2) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20284 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20284.patch - Fix the old_codec1..31 implementations to check whether a pixel is inside the visible/allocated buffer area. Should render commit 134fbfd1dcb5 obsolete, also since it breaks Rebel Assault 1 videos. - Fix old_codec48 decoding. Commit d5bdb0b705ce broke it, rewrite the MV check and add another row of 8x8 blocks to the allocated buffer space, since even "valid"/released videos try to access data outside the defined image area. The worst I've seen is 8 rows with "Mysteries of the Sith", adding the extra block row restores playback of all videos and does not trigger the MV check. >From c7c8b6ad047c0f93d7cedde6afd2d24bd4286a3f Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Tue, 19 Aug 2025 11:13:46 +0200 Subject: [PATCH 1/2] avcodec/sanm: don't write outside buffer adjust codecs1-34 to check whether the coordinates they want to write to are inside the currently defined buffer. Especially Rebel Assault 1 makes use of FOBJs that are partially outside the defined buffer width, so only draw pixels that are really visible. This also fixes a bug in the Intro of Rebel Assault 1, where a Sun is partially drawn outside the right side of the buffer and the invisible part rendered on the left side. This also undoes 134fbfd1dcb59441e38d870ddd231772f4e8e127 since it breaks Rebel Assault 1. Signed-off-by: Manuel Lauss --- libavcodec/sanm.c | 266 +++++++++++++++++++++++----------------------- 1 file changed, 132 insertions(+), 134 deletions(-) diff --git a/libavcodec/sanm.c b/libavcodec/sanm.c index e4308af647..770fd3a1d0 100644 --- a/libavcodec/sanm.c +++ b/libavcodec/sanm.c @@ -668,72 +668,6 @@ static av_cold int decode_end(AVCodecContext *avctx) return 0; } -static int old_codec4(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, - int w, int h, uint8_t param, uint16_t param2, int codec) -{ - const uint16_t p = ctx->pitch; - const uint32_t maxpxo = ctx->height * p; - uint8_t mask, bits, idx, *gs, *dst = (uint8_t *)ctx->fbuf; - int i, j, k, l, bit, ret; - int32_t pxoff, pxo2; - - if (ctx->c4param != param) { - if (codec > 32) - codec33_gen_tiles(ctx, param); - else - codec4_gen_tiles(ctx, param); - ctx->c4param = param; - } - if (param2 > 0) { - ret = codec4_load_tiles(ctx, gb, param2, param); - if (ret) - return ret; - } - - if (codec > 32) - codec -= 29; - - for (j = 0; j < w; j += 4) { - mask = bits = 0; - for (i = 0; i < h; i += 4) { - pxoff = j + left + ((top + i) * p); - if (param2 > 0) { - if (bits == 0) { - if (bytestream2_get_bytes_left(gb) < 1) - return AVERROR_INVALIDDATA; - mask = bytestream2_get_byteu(gb); - bits = 8; - } - bit = !!(mask & 0x80); - mask <<= 1; - bits--; - } else { - bit = 0; - } - - if (bytestream2_get_bytes_left(gb) < 1) - return AVERROR_INVALIDDATA; - idx = bytestream2_get_byteu(gb); - if ((bit == 0) && (idx == 0x80) && (codec != 5)) - continue; - - gs = &(ctx->c4tbl[bit][idx][0]); - pxo2 = pxoff; - for (k = 0; k < 4; k++) { - for (l = 0; l < 4; l++) { - if (pxo2 >= 0 && pxo2 < maxpxo) { - *(dst + pxo2) = *gs; - } - gs++; - pxo2++; - } - pxo2 = pxo2 - 4 + p; - } - } - } - return 0; -} - static int rle_decode(SANMVideoContext *ctx, GetByteContext *gb, uint8_t *dst, const int out_size) { int opcode, color, run_len, left = out_size; @@ -760,13 +694,97 @@ static int rle_decode(SANMVideoContext *ctx, GetByteContext *gb, uint8_t *dst, c return 0; } +/* helpers to ensure coordinates are always inside the buffer area, to be used + * by old_codec1..31 + */ +static inline int validofs(int x, int y, int maxx, int maxy) +{ + return ((x >= 0) && (y >= 0) && (x < maxx) && (y < maxy)); +} + +static inline uint8_t readpx(const uint8_t *dst, int x, int y, int pitch) +{ + return *(uint8_t *)(dst + x + y * pitch); +} + +static inline void writepx(const uint8_t *dst, int x, int y, int pitch, uint8_t px) +{ + *(uint8_t *)(dst + x + y * pitch) = px; +} + +static inline void chkwrpx(const uint8_t *dst, int x, int y, int maxx, int maxy, uint8_t col) +{ + if (validofs(x, y, maxx, maxy)) + writepx(dst, x, y, maxx, col); +} + +static int old_codec4(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, + int w, int h, uint8_t param, uint16_t param2, int codec) +{ + const uint8_t *dst = (uint8_t *)ctx->fbuf; + const int mx = ctx->width; + const int my = ctx->height; + uint8_t mask, bits, idx, *gs; + int i, j, k, l, bit, ret; + + if (ctx->c4param != param) { + if (codec > 32) + codec33_gen_tiles(ctx, param); + else + codec4_gen_tiles(ctx, param); + ctx->c4param = param; + } + if (param2 > 0) { + ret = codec4_load_tiles(ctx, gb, param2, param); + if (ret) + return ret; + } + + if (codec > 32) + codec -= 29; + + for (j = 0; j < w; j += 4) { + mask = bits = 0; + for (i = 0; i < h; i += 4) { + if (param2 > 0) { + if (bits == 0) { + if (bytestream2_get_bytes_left(gb) < 1) + return AVERROR_INVALIDDATA; + mask = bytestream2_get_byteu(gb); + bits = 8; + } + bit = !!(mask & 0x80); + mask <<= 1; + bits--; + } else { + bit = 0; + } + + if (bytestream2_get_bytes_left(gb) < 1) + return AVERROR_INVALIDDATA; + idx = bytestream2_get_byteu(gb); + if ((bit == 0) && (idx == 0x80) && (codec != 5)) + continue; + + gs = &(ctx->c4tbl[bit][idx][0]); + for (k = 0; k < 4; k++) { + for (l = 0; l < 4; l++) { + chkwrpx(dst, left + j + l, top + i + k, mx, my, *gs++); + } + } + } + } + return 0; +} + static int old_codec23(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int width, int height, uint8_t param, uint16_t param2) { - const uint32_t maxpxo = ctx->height * ctx->pitch; - uint8_t *dst, lut[256], c; + const uint8_t *dst = (uint8_t *)ctx->fbuf; + const int mx = ctx->width; + const int my = ctx->height; + uint8_t lut[256], c; int i, j, k, pc, sk; - int32_t pxoff; if (ctx->subversion < 2) { /* Rebel Assault 1: constant offset + 0xd0 */ @@ -785,11 +803,9 @@ static int old_codec23(SANMVideoContext *ctx, GetByteContext *gb, int top, int l if (bytestream2_get_bytes_left(gb) < 1) return 0; /* some c23 frames just set up the LUT */ - dst = (uint8_t *)ctx->fbuf; for (i = 0; i < height; i++) { if (bytestream2_get_bytes_left(gb) < 2) return 0; - pxoff = left + ((top + i) * ctx->pitch); k = bytestream2_get_le16u(gb); sk = 1; pc = 0; @@ -798,15 +814,13 @@ static int old_codec23(SANMVideoContext *ctx, GetByteContext *gb, int top, int l return AVERROR_INVALIDDATA; j = bytestream2_get_byteu(gb); if (sk) { - pxoff += j; pc += j; } else { while (j--) { - if (pxoff >=0 && pxoff < maxpxo) { - c = *(dst + pxoff); - *(dst + pxoff) = lut[c]; + if (validofs(pc + left, top + i, mx, my)) { + c = readpx(dst, pc + left, top + i, mx); + writepx(dst, pc + left, top + i, mx, lut[c]); } - pxoff++; pc++; } } @@ -819,15 +833,15 @@ static int old_codec23(SANMVideoContext *ctx, GetByteContext *gb, int top, int l static int old_codec21(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int width, int height) { - const uint32_t maxpxo = ctx->height * ctx->pitch; - uint8_t *dst = (uint8_t *)ctx->fbuf, c; - int i, j, k, pc, sk, pxoff; + const uint8_t *dst = (uint8_t *)ctx->fbuf; + const int mx = ctx->width; + const int my = ctx->height; + uint8_t c; + int i, j, k, pc, sk; - dst = (uint8_t *)ctx->fbuf; for (i = 0; i < height; i++) { if (bytestream2_get_bytes_left(gb) < 2) return 0; - pxoff = left + ((top + i) * ctx->pitch); k = bytestream2_get_le16u(gb); sk = 1; pc = 0; @@ -837,17 +851,13 @@ static int old_codec21(SANMVideoContext *ctx, GetByteContext *gb, int top, int l j = bytestream2_get_le16u(gb); k -= 2; if (sk) { - pxoff += j; pc += j; } else { if (bytestream2_get_bytes_left(gb) < (j + 1)) return AVERROR_INVALIDDATA; do { c = bytestream2_get_byteu(gb); - if (pxoff >=0 && pxoff < maxpxo) { - *(dst + pxoff) = c; - } - pxoff++; + chkwrpx(dst, left + pc, top + i, mx, my, c); pc++; j--; k--; @@ -862,9 +872,10 @@ static int old_codec21(SANMVideoContext *ctx, GetByteContext *gb, int top, int l static int old_codec1(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int width, int height, int opaque) { - int i, j, len, flag, code, val, end, pxoff; - const int maxpxo = ctx->height * ctx->pitch; - uint8_t *dst = (uint8_t *)ctx->fbuf; + const uint8_t *dst = (uint8_t *)ctx->fbuf; + int i, j, len, flag, code, val, end, x; + const int mx = ctx->width; + const int my = ctx->height; for (i = 0; i < height; i++) { if (bytestream2_get_bytes_left(gb) < 2) @@ -872,8 +883,8 @@ static int old_codec1(SANMVideoContext *ctx, GetByteContext *gb, int top, len = bytestream2_get_le16u(gb); end = bytestream2_tell(gb) + len; + x = left; - pxoff = left + ((top + i) * ctx->pitch); while (bytestream2_tell(gb) < end) { if (bytestream2_get_bytes_left(gb) < 2) return AVERROR_INVALIDDATA; @@ -883,23 +894,19 @@ static int old_codec1(SANMVideoContext *ctx, GetByteContext *gb, int top, code = (code >> 1) + 1; if (flag) { val = bytestream2_get_byteu(gb); - if (val || opaque) { - for (j = 0; j < code; j++) { - if (pxoff >= 0 && pxoff < maxpxo) - *(dst + pxoff) = val; - pxoff++; - } - } else { - pxoff += code; + for (j = 0; j < code; j++) { + if (val || opaque) + chkwrpx(dst, x, top + i, mx, my, val); + x++; } } else { if (bytestream2_get_bytes_left(gb) < code) return AVERROR_INVALIDDATA; for (j = 0; j < code; j++) { val = bytestream2_get_byteu(gb); - if ((pxoff >= 0) && (pxoff < maxpxo) && (val || opaque)) - *(dst + pxoff) = val; - pxoff++; + if (val || opaque) + chkwrpx(dst, x, top + i, mx, my, val); + x++; } } } @@ -912,9 +919,10 @@ static int old_codec1(SANMVideoContext *ctx, GetByteContext *gb, int top, static int old_codec31(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int width, int height, int p1, int opaque) { - int i, j, len, flag, code, val, end, pxoff; - const int maxpxo = ctx->height * ctx->pitch; - uint8_t *dst = (uint8_t *)ctx->fbuf; + const uint8_t *dst = (uint8_t *)ctx->fbuf; + int i, j, len, flag, code, val, end, x; + const int mx = ctx->width; + const int my = ctx->height; for (i = 0; i < height; i++) { if (bytestream2_get_bytes_left(gb) < 2) @@ -922,8 +930,8 @@ static int old_codec31(SANMVideoContext *ctx, GetByteContext *gb, int top, len = bytestream2_get_le16u(gb); end = bytestream2_tell(gb) + len; + x = left; - pxoff = left + ((top + i) * ctx->pitch); while (bytestream2_tell(gb) < end) { if (bytestream2_get_bytes_left(gb) < 2) return AVERROR_INVALIDDATA; @@ -934,28 +942,24 @@ static int old_codec31(SANMVideoContext *ctx, GetByteContext *gb, int top, if (flag) { val = bytestream2_get_byteu(gb); for (j = 0; j < code; j++) { - if ((0 != (val & 0xf)) || opaque) { - if (pxoff >= 0 && pxoff < maxpxo) - *(dst + pxoff) = p1 + (val & 0xf); - } - pxoff++; - if ((0 != (val >> 4)) || opaque) { - if (pxoff >= 0 && pxoff < maxpxo) - *(dst + pxoff) = p1 + (val >> 4); - } - pxoff++; + if (opaque || (val & 0xf)) + chkwrpx(dst, x, top + i, mx, my, p1 + (val & 0x0f)); + x++; + if (opaque || (val >> 4)) + chkwrpx(dst, x, top + i, mx, my, p1 + (val >> 4)); + x++; } } else { if (bytestream2_get_bytes_left(gb) < code) return AVERROR_INVALIDDATA; for (j = 0; j < code; j++) { val = bytestream2_get_byteu(gb); - if ((pxoff >= 0) && (pxoff < maxpxo) && ((0 != (val & 0xf)) || opaque)) - *(dst + pxoff) = p1 + (val & 0xf); - pxoff++; - if ((pxoff >= 0) && (pxoff < maxpxo) && ((0 != (val >> 4)) || opaque)) - *(dst + pxoff) = p1 + (val >> 4); - pxoff++; + if (opaque || (val & 0xf)) + chkwrpx(dst, x, top + i, mx, my, p1 + (val & 0x0f)); + x++; + if (opaque || (val >> 4)) + chkwrpx(dst, x, top + i, mx, my, p1 + (val >> 4)); + x++; } } } @@ -968,17 +972,16 @@ static int old_codec31(SANMVideoContext *ctx, GetByteContext *gb, int top, static int old_codec2(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int width, int height) { - uint8_t *dst = (uint8_t *)ctx->fbuf, col; - int16_t xpos = left, ypos = top; + const uint8_t *dst = (uint8_t *)ctx->fbuf; + const int mx = ctx->width; + const int my = ctx->height; + uint8_t col; while (bytestream2_get_bytes_left(gb) > 3) { - xpos += bytestream2_get_le16u(gb); - ypos += bytestream2_get_byteu(gb); + left += bytestream2_get_le16u(gb); + top += bytestream2_get_byteu(gb); col = bytestream2_get_byteu(gb); - if (xpos >= 0 && ypos >= 0 && - xpos < ctx->width && ypos < ctx->height) { - *(dst + xpos + ypos * ctx->pitch) = col; - } + chkwrpx(dst, left, top, mx, my, col); } return 0; } @@ -1757,11 +1760,6 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) memset(ctx->fbuf, 0, ctx->frm0_size); } - if (w + FFMAX(left, 0) > ctx->avctx->width || h + FFMAX(top, 0) > ctx->avctx->height) { - avpriv_request_sample(ctx->avctx, "overly large frame\n"); - return AVERROR_PATCHWELCOME; - } - switch (codec) { case 1: case 3: -- 2.49.1 >From 117b05f6026ae5a43557baeccb8469de736aa670 Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Tue, 19 Aug 2025 12:43:17 +0200 Subject: [PATCH 2/2] avcodec/sanm: fix codec48 decoding Commit d5bdb0b705ce ("avcodec/sanm: Check mv in codec48_block()") completely broke decoding of valid codec48 videos. Rewrite the MV check, and most importantly, add another row of 8x8 blocks to the allocated buffer, since even "valid" videos released by LucasArts try to copy blocks from up to 8 rows outside the defined image area. Fixes: d5bdb0b705ce96739e812ca5317361674359369c Signed-off-by: Manuel Lauss --- libavcodec/sanm.c | 51 +++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/libavcodec/sanm.c b/libavcodec/sanm.c index 770fd3a1d0..0e18c0a910 100644 --- a/libavcodec/sanm.c +++ b/libavcodec/sanm.c @@ -446,6 +446,7 @@ static void init_sizes(SANMVideoContext *ctx, int width, int height) ctx->aligned_width = FFALIGN(width, 8); ctx->aligned_height = FFALIGN(height, 8); + ctx->aligned_height += 8; /* for slighly too large MVs in codec37/48 */ ctx->buf_size = ctx->aligned_width * ctx->aligned_height * sizeof(ctx->frm0[0]); ctx->pitch = width; @@ -1430,20 +1431,20 @@ static void c48_4to8(uint8_t *dst, const uint8_t *src, const uint16_t w) } } -static int check_mv(int x, int y, const uint16_t w, int h, int blocksize, int mvofs) { - if (mvofs < -x + -y*w) - return AVERROR_INVALIDDATA; - - if (mvofs > w-x-blocksize + w*(h-y-blocksize)) - return AVERROR_INVALIDDATA; - - return 0; +static inline int c48_valid_mv(int x, int y, const uint16_t w, const int h, int bs, int mvofs) +{ + const int m = (x + bs - 1 + w * (y + bs - 1)); + const int n = (x + w * y); + if ((mvofs < 0 && ((n - mvofs) < 0)) || ((m + mvofs) >= (w * h))) { + return 0; + } + return 1; } -static int codec48_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *db, int x, int y, - const uint16_t w, int h) +static int codec48_block(SANMVideoContext *ctx, int x, int y, const uint16_t w) { - uint8_t opc, sb[16]; + uint8_t opc, sb[16], *dst = (uint8_t *)ctx->frm0 + x + y * w; + uint8_t *db = (uint8_t *)ctx->frm2 + x + y * w; int i, j, k, l; int16_t mvofs; uint32_t ofs; @@ -1466,8 +1467,8 @@ static int codec48_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *db, int x if (bytestream2_get_bytes_left(&ctx->gb) < 2) return 1; mvofs = bytestream2_get_le16(&ctx->gb); - if (check_mv(x, y, w, h, 8, mvofs)) - return 1; + if (!c48_valid_mv(x, y, w, ctx->aligned_height, 8, mvofs)) + break; for (i = 0; i < 8; i++) { ofs = w * i; for (k = 0; k < 8; k++) @@ -1495,8 +1496,8 @@ static int codec48_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *db, int x for (k = 0; k < 8; k += 4) { opc = bytestream2_get_byteu(&ctx->gb); mvofs = c37_mv[opc * 2] + (c37_mv[opc * 2 + 1] * w); - if (check_mv(x+k, y+i, w, h, 4, mvofs)) - return 1; + if (!c48_valid_mv(x+k, y+i, w, ctx->aligned_height, 4, mvofs)) + continue; for (j = 0; j < 4; j++) { ofs = (w * (j + i)) + k; for (l = 0; l < 4; l++) @@ -1511,8 +1512,8 @@ static int codec48_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *db, int x for (i = 0; i < 8; i += 4) { for (k = 0; k < 8; k += 4) { mvofs = bytestream2_get_le16(&ctx->gb); - if (check_mv(x+k, y+i, w, h, 4, mvofs)) - return 1; + if (!c48_valid_mv(x+k, y+i, w, ctx->aligned_height, 4, mvofs)) + continue; for (j = 0; j < 4; j++) { ofs = (w * (j + i)) + k; for (l = 0; l < 4; l++) @@ -1535,8 +1536,8 @@ static int codec48_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *db, int x ofs = (w * i) + j; opc = bytestream2_get_byteu(&ctx->gb); mvofs = c37_mv[opc * 2] + (c37_mv[opc * 2 + 1] * w); - if (check_mv(x+j, y+i, w, h, 2, mvofs)) - return 1; + if (!c48_valid_mv(x+j, y+i, w, ctx->aligned_height, 2, mvofs)) + continue; for (l = 0; l < 2; l++) { *(dst + ofs + l + 0) = *(db + ofs + l + 0 + mvofs); *(dst + ofs + l + w) = *(db + ofs + l + w + mvofs); @@ -1551,8 +1552,8 @@ static int codec48_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *db, int x for (j = 0; j < 8; j += 2) { ofs = w * i + j; mvofs = bytestream2_get_le16(&ctx->gb); - if (check_mv(x+j, y+i, w, h, 2, mvofs)) - return 1; + if (!c48_valid_mv(x+j, y+i, w, ctx->aligned_height, 2, mvofs)) + continue; for (l = 0; l < 2; l++) { *(dst + ofs + l + 0) = *(db + ofs + l + 0 + mvofs); *(dst + ofs + l + w) = *(db + ofs + l + w + mvofs); @@ -1571,8 +1572,8 @@ static int codec48_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *db, int x break; default: // copy 8x8 block from prev, c37_mv from source mvofs = c37_mv[opc * 2] + (c37_mv[opc * 2 + 1] * w); - if (check_mv(x, y, w, h, 8, mvofs)) - return 1; + if (!c48_valid_mv(x, y, w, ctx->aligned_height, 8, mvofs)) + break; for (i = 0; i < 8; i++) { ofs = i * w; for (l = 0; l < 8; l++) @@ -1638,11 +1639,9 @@ static int old_codec48(SANMVideoContext *ctx, int width, int height) if (seq == ctx->prev_seq + 1) { for (j = 0; j < height; j += 8) { for (i = 0; i < width; i += 8) { - if (codec48_block(ctx, dst + i, prev + i, i, j, width, height)) + if (codec48_block(ctx, i, j, width)) return AVERROR_INVALIDDATA; } - dst += width * 8; - prev += width * 8; } } break; -- 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".