summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Niedermayer <michael@niedermayer.cc>2015-07-24 17:24:57 +0200
committerMichael Niedermayer <michael@niedermayer.cc>2015-07-24 17:36:00 +0200
commitdaf6bce71be9534628a72baa5d1f1f0db281f5e5 (patch)
treee1b434631474577b566ca379c66a9c638d3e4a93
parent3cb8eee6f7bff275081e640b7529f90c52fb3224 (diff)
downloadffmpeg-daf6bce71be9534628a72baa5d1f1f0db281f5e5.tar.gz
avcodec/dvdec: Retry decoding seemingly damaged MBs while skiping likely damaged parts
Improves decoding of Ticket1589 Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
-rw-r--r--libavcodec/dvdec.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/libavcodec/dvdec.c b/libavcodec/dvdec.c
index fbd6bf504b..656110e60a 100644
--- a/libavcodec/dvdec.c
+++ b/libavcodec/dvdec.c
@@ -291,10 +291,15 @@ static int dv_decode_video_segment(AVCodecContext *avctx, void *arg)
LOCAL_ALIGNED_16(uint8_t, vs_bit_buffer, [80 * 5 + FF_INPUT_BUFFER_PADDING_SIZE]); /* allow some slack */
const int log2_blocksize = 3-s->avctx->lowres;
int is_field_mode[5];
+ int vs_bit_buffer_damaged = 0;
+ int mb_bit_buffer_damaged[5] = {0};
+ int retried = 0;
av_assert1((((int) mb_bit_buffer) & 7) == 0);
av_assert1((((int) vs_bit_buffer) & 7) == 0);
+retry:
+
memset(sblock, 0, 5 * DV_MAX_BPM * sizeof(*sblock));
/* pass 1: read DC and AC coefficients in blocks */
@@ -349,11 +354,16 @@ static int dv_decode_video_segment(AVCodecContext *avctx, void *arg)
* block is finished */
if (mb->pos >= 64)
bit_copy(&pb, &gb);
+ if (mb->pos >= 64 && mb->pos < 127)
+ vs_bit_buffer_damaged = mb_bit_buffer_damaged[mb_index] = 1;
block += 64;
mb++;
}
+ if (mb_bit_buffer_damaged[mb_index] > 0)
+ continue;
+
/* pass 2: we can do it just after */
ff_dlog(avctx, "***pass 2 size=%d MB#=%d\n", put_bits_count(&pb), mb_index);
block = block1;
@@ -367,6 +377,8 @@ static int dv_decode_video_segment(AVCodecContext *avctx, void *arg)
/* if still not finished, no need to parse other blocks */
if (mb->pos < 64)
break;
+ if (mb->pos < 127)
+ vs_bit_buffer_damaged = mb_bit_buffer_damaged[mb_index] = 1;
}
}
/* all blocks are finished, so the extra bytes can be used at
@@ -384,17 +396,25 @@ static int dv_decode_video_segment(AVCodecContext *avctx, void *arg)
flush_put_bits(&vs_pb);
for (mb_index = 0; mb_index < 5; mb_index++) {
for (j = 0; j < s->sys->bpm; j++) {
- if (mb->pos < 64 && get_bits_left(&gb) > 0) {
+ if (mb->pos < 64 && get_bits_left(&gb) > 0 && !vs_bit_buffer_damaged) {
ff_dlog(avctx, "start %d:%d\n", mb_index, j);
dv_decode_ac(&gb, mb, block);
}
- if (mb->pos >= 64 && mb->pos < 127)
+
+ if (mb->pos >= 64 && mb->pos < 127) {
av_log(avctx, AV_LOG_ERROR,
"AC EOB marker is absent pos=%d\n", mb->pos);
+ vs_bit_buffer_damaged = 1;
+ }
block += 64;
mb++;
}
}
+ if (vs_bit_buffer_damaged && !retried) {
+ av_log(avctx, AV_LOG_ERROR, "Concealing bitstream errors\n");
+ retried = 1;
+ goto retry;
+ }
/* compute idct and place blocks */
block = &sblock[0][0];