summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Ross <pross@xvid.org>2022-11-01 09:24:29 +1100
committerPeter Ross <pross@xvid.org>2022-11-01 10:14:31 +1100
commit16af424bf983409e00a84af1c98bbe7171ddd79f (patch)
tree261d4ba21235a5352f2aa161ae03fe400c5c96ec
parent6fe8556a19c4494d4312f81c2fb7d4402b31b2eb (diff)
avcodec/svq1dec: detect buggy FFmpeg encoder and apply correction to interframe mean symbols
The FFmpeg encoder does not increment the temporal reference field, so use that knowledge plus the extradata field to detect buggy versions of the encoder.
-rw-r--r--libavcodec/svq1dec.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/libavcodec/svq1dec.c b/libavcodec/svq1dec.c
index 828b38b93d..c7269456e2 100644
--- a/libavcodec/svq1dec.c
+++ b/libavcodec/svq1dec.c
@@ -73,6 +73,8 @@ typedef struct SVQ1Context {
int height;
int frame_code;
int nonref; // 1 if the current frame won't be referenced
+
+ int last_tempref;
} SVQ1Context;
static const uint8_t string_table[256] = {
@@ -229,7 +231,7 @@ static int svq1_decode_block_intra(GetBitContext *bitbuf, uint8_t *pixels,
}
static int svq1_decode_block_non_intra(GetBitContext *bitbuf, uint8_t *pixels,
- ptrdiff_t pitch)
+ ptrdiff_t pitch, int buggy)
{
uint32_t bit_cache;
uint8_t *list[63];
@@ -270,6 +272,13 @@ static int svq1_decode_block_non_intra(GetBitContext *bitbuf, uint8_t *pixels,
mean = get_vlc2(bitbuf, svq1_inter_mean.table, 9, 3) - 256;
+ if (buggy) {
+ if (mean == -128)
+ mean = 128;
+ else if (mean == 128)
+ mean = -128;
+ }
+
SVQ1_CALC_CODEBOOK_ENTRIES(ff_svq1_inter_codebooks);
for (y = 0; y < height; y++) {
@@ -455,7 +464,7 @@ static int svq1_decode_delta_block(AVCodecContext *avctx, HpelDSPContext *hdsp,
GetBitContext *bitbuf,
uint8_t *current, uint8_t *previous,
ptrdiff_t pitch, svq1_pmv *motion, int x, int y,
- int width, int height)
+ int width, int height, int buggy)
{
uint32_t block_type;
int result = 0;
@@ -487,7 +496,7 @@ static int svq1_decode_delta_block(AVCodecContext *avctx, HpelDSPContext *hdsp,
ff_dlog(avctx, "Error in svq1_motion_inter_block %i\n", result);
break;
}
- result = svq1_decode_block_non_intra(bitbuf, current, pitch);
+ result = svq1_decode_block_non_intra(bitbuf, current, pitch, buggy);
break;
case SVQ1_BLOCK_INTER_4V:
@@ -498,7 +507,7 @@ static int svq1_decode_delta_block(AVCodecContext *avctx, HpelDSPContext *hdsp,
ff_dlog(avctx, "Error in svq1_motion_inter_4v_block %i\n", result);
break;
}
- result = svq1_decode_block_non_intra(bitbuf, current, pitch);
+ result = svq1_decode_block_non_intra(bitbuf, current, pitch, buggy);
break;
case SVQ1_BLOCK_INTRA:
@@ -524,15 +533,18 @@ static void svq1_parse_string(GetBitContext *bitbuf, uint8_t out[257])
out[i] = 0;
}
-static int svq1_decode_frame_header(AVCodecContext *avctx, AVFrame *frame)
+static int svq1_decode_frame_header(AVCodecContext *avctx, AVFrame *frame, int * buggy)
{
SVQ1Context *s = avctx->priv_data;
GetBitContext *bitbuf = &s->gb;
int frame_size_code;
int width = s->width;
int height = s->height;
+ int tempref;
- skip_bits(bitbuf, 8); /* temporal_reference */
+ tempref = get_bits(bitbuf, 8); /* temporal_reference */
+ *buggy = tempref == 0 && s->last_tempref == 0 && avctx->extradata_size == 0;
+ s->last_tempref = tempref;
/* frame type */
s->nonref = 0;
@@ -624,7 +636,7 @@ static int svq1_decode_frame(AVCodecContext *avctx, AVFrame *cur,
int buf_size = avpkt->size;
SVQ1Context *s = avctx->priv_data;
uint8_t *current;
- int result, i, x, y, width, height;
+ int result, i, x, y, width, height, buggy;
int ret;
/* initialize bit buffer */
@@ -664,7 +676,7 @@ static int svq1_decode_frame(AVCodecContext *avctx, AVFrame *cur,
src[i] = ((src[i] << 16) | (src[i] >> 16)) ^ src[7 - i];
}
- result = svq1_decode_frame_header(avctx, cur);
+ result = svq1_decode_frame_header(avctx, cur, &buggy);
if (result != 0) {
ff_dlog(avctx, "Error in svq1_decode_frame_header %i\n", result);
return result;
@@ -734,7 +746,7 @@ static int svq1_decode_frame(AVCodecContext *avctx, AVFrame *cur,
result = svq1_decode_delta_block(avctx, &s->hdsp,
&s->gb, &current[x],
previous, linesize,
- s->pmv, x, y, width, height);
+ s->pmv, x, y, width, height, buggy);
if (result != 0) {
ff_dlog(avctx,
"Error in svq1_decode_delta_block %i\n",
@@ -820,6 +832,8 @@ static av_cold int svq1_decode_init(AVCodecContext *avctx)
ff_thread_once(&init_static_once, svq1_static_init);
+ s->last_tempref = 0xFF;
+
return 0;
}