static int old_codec37(SANMVideoContext *ctx, int top, int left, int width, int height) { int stride = ctx->pitch; int i, j, k, t; int skip_run = 0; int compr, mvoff, seq, flags; uint32_t decoded_size; uint8_t *dst, *prev; compr = bytestream2_get_byte(&ctx->gb); mvoff = bytestream2_get_byte(&ctx->gb); seq = bytestream2_get_le16(&ctx->gb); decoded_size = bytestream2_get_le32(&ctx->gb); bytestream2_skip(&ctx->gb, 4); flags = bytestream2_get_byte(&ctx->gb); bytestream2_skip(&ctx->gb, 3); if (decoded_size > height * stride - left - top * stride) { decoded_size = height * stride - left - top * stride; av_log(ctx->avctx, AV_LOG_WARNING, "decoded size is too large\n"); } ctx->rotate_code = 0; if (((seq & 1) || !(flags & 1)) && (compr && compr != 2)) rotate_bufs(ctx, 1); dst = ((uint8_t*)ctx->frm0) + left + top * stride; prev = ((uint8_t*)ctx->frm2) + left + top * stride; if (mvoff > 2) { av_log(ctx->avctx, AV_LOG_ERROR, "invalid motion base value %d\n", mvoff); return AVERROR_INVALIDDATA; } av_dlog(ctx->avctx, "compression %d\n", compr); switch (compr) { case 0: for (i = 0; i < height; i++) { 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 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: case 4: if (flags & 4) { for (j = 0; j < height; j += 4) { for (i = 0; i < width; i += 4) { int code; if (skip_run) { skip_run--; copy_block4(dst + i, prev + i, stride, stride, 4); continue; } if (bytestream2_get_bytes_left(&ctx->gb) < 1) return AVERROR_INVALIDDATA; code = bytestream2_get_byteu(&ctx->gb); switch (code) { case 0xFF: if (bytestream2_get_bytes_left(&ctx->gb) < 16) return AVERROR_INVALIDDATA; for (k = 0; k < 4; k++) bytestream2_get_bufferu(&ctx->gb, dst + i + k * stride, 4); break; case 0xFE: if (bytestream2_get_bytes_left(&ctx->gb) < 4) return AVERROR_INVALIDDATA; for (k = 0; k < 4; k++) memset(dst + i + k * stride, bytestream2_get_byteu(&ctx->gb), 4); break; case 0xFD: if (bytestream2_get_bytes_left(&ctx->gb) < 1) return AVERROR_INVALIDDATA; t = bytestream2_get_byteu(&ctx->gb); for (k = 0; k < 4; k++) memset(dst + i + k * stride, t, 4); break; default: if (compr == 4 && !code) { if (bytestream2_get_bytes_left(&ctx->gb) < 1) return AVERROR_INVALIDDATA; skip_run = bytestream2_get_byteu(&ctx->gb) + 1; i -= 4; } else { int mx, my; 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); } } } dst += stride * 4; prev += stride * 4; } } else { for (j = 0; j < height; j += 4) { for (i = 0; i < width; i += 4) { int code; if (skip_run) { skip_run--; copy_block4(dst + i, prev + i, stride, stride, 4); continue; } code = bytestream2_get_byte(&ctx->gb); if (code == 0xFF) { if (bytestream2_get_bytes_left(&ctx->gb) < 16) return AVERROR_INVALIDDATA; for (k = 0; k < 4; k++) bytestream2_get_bufferu(&ctx->gb, dst + i + k * stride, 4); } else if (compr == 4 && !code) { if (bytestream2_get_bytes_left(&ctx->gb) < 1) return AVERROR_INVALIDDATA; skip_run = bytestream2_get_byteu(&ctx->gb) + 1; i -= 4; } else { int mx, my; 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); } } dst += stride * 4; prev += stride * 4; } } break; default: av_log(ctx->avctx, AV_LOG_ERROR, "subcodec 37 compression %d not implemented\n", compr); return AVERROR_PATCHWELCOME; } return 0; }