From d4b9974465baf893e90527a366e7a7411ded1ef8 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Wed, 24 Aug 2011 14:36:16 -0700 Subject: [PATCH 1/6] vc1: properly zero coded_block[] edges on new slice entry. Previously, we would leave the left edge uninitialized, which led to CBP prediction errors on slice edges, e.g. in SA10098.vc1. --- libavcodec/vc1dec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 8bf900c97d..4954d4fd75 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -3019,7 +3019,7 @@ static void vc1_decode_i_blocks_adv(VC1Context *v) s->mb_x = 0; ff_init_block_index(s); memset(&s->coded_block[s->block_index[0]-s->b8_stride], 0, - s->b8_stride * sizeof(*s->coded_block)); + (1 + s->b8_stride) * sizeof(*s->coded_block)); } for(; s->mb_y < s->end_mb_y; s->mb_y++) { s->mb_x = 0; From ad6c7c1b525c7ae365491b4fef7869d31ee88329 Mon Sep 17 00:00:00 2001 From: Alex Converse Date: Wed, 24 Aug 2011 16:59:30 -0700 Subject: [PATCH 2/6] mp4: Handle non-trivial ES Descriptors. --- libavformat/isom.c | 16 ++++++++++++++++ libavformat/isom.h | 1 + libavformat/mov.c | 3 +-- libavformat/mpegts.c | 3 +-- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/libavformat/isom.c b/libavformat/isom.c index eb17e25474..7d42e80070 100644 --- a/libavformat/isom.c +++ b/libavformat/isom.c @@ -372,6 +372,22 @@ int ff_mp4_read_descr(AVFormatContext *fc, AVIOContext *pb, int *tag) return len; } +void ff_mp4_parse_es_descr(AVIOContext *pb, int *es_id) +{ + int flags; + if (es_id) *es_id = avio_rb16(pb); + else avio_rb16(pb); + flags = avio_r8(pb); + if (flags & 0x80) //streamDependenceFlag + avio_rb16(pb); + if (flags & 0x40) { //URL_Flag + int len = avio_r8(pb); + avio_skip(pb, len); + } + if (flags & 0x20) //OCRstreamFlag + avio_rb16(pb); +} + static const AVCodecTag mp4_audio_types[] = { { CODEC_ID_MP3ON4, AOT_PS }, /* old mp3on4 draft */ { CODEC_ID_MP3ON4, AOT_L1 }, /* layer 1 */ diff --git a/libavformat/isom.h b/libavformat/isom.h index ef3fe1484f..838eb42f97 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -146,6 +146,7 @@ typedef struct MOVContext { int ff_mp4_read_descr_len(AVIOContext *pb); int ff_mp4_read_descr(AVFormatContext *fc, AVIOContext *pb, int *tag); int ff_mp4_read_dec_config_descr(AVFormatContext *fc, AVStream *st, AVIOContext *pb); +void ff_mp4_parse_es_descr(AVIOContext *pb, int *es_id); #define MP4IODescrTag 0x02 #define MP4ESDescrTag 0x03 diff --git a/libavformat/mov.c b/libavformat/mov.c index 92b1b14f15..35cd9a880b 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -473,8 +473,7 @@ int ff_mov_read_esds(AVFormatContext *fc, AVIOContext *pb, MOVAtom atom) avio_rb32(pb); /* version + flags */ ff_mp4_read_descr(fc, pb, &tag); if (tag == MP4ESDescrTag) { - avio_rb16(pb); /* ID */ - avio_r8(pb); /* priority */ + ff_mp4_parse_es_descr(pb, NULL); } else avio_rb16(pb); /* ID */ diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index fa5bd4c5a1..a72341865f 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -886,9 +886,8 @@ static int mp4_read_iods(AVFormatContext *s, const uint8_t *buf, unsigned size, avio_r8(&pb); len = ff_mp4_read_descr(s, &pb, &tag); if (tag == MP4ESDescrTag) { - *es_id = avio_rb16(&pb); /* ES_ID */ + ff_mp4_parse_es_descr(&pb, es_id); av_dlog(s, "ES_ID %#x\n", *es_id); - avio_r8(&pb); /* priority */ len = ff_mp4_read_descr(s, &pb, &tag); if (tag == MP4DecConfigDescrTag) { *dec_config_descr = av_malloc(len); From 1cf82cab0840d669198ea76ab0363aa661950647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Delm=C3=A1s?= Date: Thu, 25 Aug 2011 11:00:37 +0200 Subject: [PATCH 3/6] VC1: Fix first/last row checks with slices In some places 0/mb_height were used in place of start_mb_y/end_mb_y. Fixes SA00049, SA00058, SA10091, SA10097, SA10131, SA20021, SA30030 Improves PSNR in SA00054, SA00059, SA00060, SA10096, SA10098, SA20022, SA30031, SA30032, SA40012, SA40013 Signed-off-by: Ronald S. Bultje --- libavcodec/vc1dec.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 4954d4fd75..735d6c2e51 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -242,7 +242,7 @@ static void vc1_loop_filter_iblk(VC1Context *v, int pq) } v->vc1dsp.vc1_v_loop_filter16(s->dest[0] + 8*s->linesize, s->linesize, pq); - if (s->mb_y == s->mb_height-1) { + if (s->mb_y == s->end_mb_y-1) { if (s->mb_x) { v->vc1dsp.vc1_h_loop_filter16(s->dest[0], s->linesize, pq); v->vc1dsp.vc1_h_loop_filter8(s->dest[1], s->uvlinesize, pq); @@ -294,7 +294,7 @@ static void vc1_loop_filter_iblk_delayed(VC1Context *v, int pq) v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 8 * s->linesize, s->linesize, pq); } - if (s->mb_y == s->mb_height) { + if (s->mb_y == s->end_mb_y) { if (s->mb_x) { if (s->mb_x >= 2) v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize - 16, s->linesize, pq); @@ -2329,7 +2329,7 @@ static av_always_inline void vc1_apply_p_v_loop_filter(VC1Context *v, int block_ } else { dst = s->dest[0] + (block_num & 1) * 8 + ((block_num & 2) * 4 - 8) * linesize; } - if (s->mb_y != s->mb_height || block_num < 2) { + if (s->mb_y != s->end_mb_y || block_num < 2) { int16_t (*mv)[2]; int mv_stride; @@ -3095,7 +3095,7 @@ static void vc1_decode_i_blocks_adv(VC1Context *v) if(v->s.loop_filter) vc1_loop_filter_iblk_delayed(v, v->pq); } if (v->s.loop_filter) - ff_draw_horiz_band(s, (s->mb_height-1)*16, 16); + ff_draw_horiz_band(s, (s->end_mb_y-1)*16, 16); ff_er_add_slice(s, 0, s->start_mb_y, s->mb_width - 1, s->end_mb_y - 1, (AC_END|DC_END|MV_END)); } @@ -3218,7 +3218,7 @@ static void vc1_decode_b_blocks(VC1Context *v) s->first_slice_line = 0; } if (v->s.loop_filter) - ff_draw_horiz_band(s, (s->mb_height-1)*16, 16); + ff_draw_horiz_band(s, (s->end_mb_y-1)*16, 16); ff_er_add_slice(s, 0, s->start_mb_y, s->mb_width - 1, s->end_mb_y - 1, (AC_END|DC_END|MV_END)); } @@ -3226,9 +3226,9 @@ static void vc1_decode_skip_blocks(VC1Context *v) { MpegEncContext *s = &v->s; - ff_er_add_slice(s, 0, 0, s->mb_width - 1, s->mb_height - 1, (AC_END|DC_END|MV_END)); + ff_er_add_slice(s, 0, s->start_mb_y, s->mb_width - 1, s->end_mb_y - 1, (AC_END|DC_END|MV_END)); s->first_slice_line = 1; - for(s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) { + for(s->mb_y = s->start_mb_y; s->mb_y < s->end_mb_y; s->mb_y++) { s->mb_x = 0; ff_init_block_index(s); ff_update_block_index(s); From 0d802ac54e86aee587f5e9917a2eefbfecd73571 Mon Sep 17 00:00:00 2001 From: John Stebbins Date: Thu, 25 Aug 2011 12:36:13 -0700 Subject: [PATCH 4/6] vc1: fix VC-1 Pulldown handling. Pulldown flags are being set incorrectly and AVFrame->repeat_pict is not being set. Also, skipped frames exit header parsing too early and do not set pulldown flags appropriately. Ticks_per_frame needs to be set and time_base adjusted so player can extend frame duration by a field time. This fixes problems encountered when attempting to transcode HD-DVD EVOB files with HandBrake. Also makes these files play smoothly in avplay. Signed-off-by: Ronald S. Bultje --- libavcodec/vc1.c | 11 +++++++++-- libavcodec/vc1_parser.c | 15 +++++++++++++++ libavcodec/vc1dec.c | 12 ++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/libavcodec/vc1.c b/libavcodec/vc1.c index fe9781b5de..c3649ac383 100644 --- a/libavcodec/vc1.c +++ b/libavcodec/vc1.c @@ -501,6 +501,10 @@ static int decode_sequence_header_adv(VC1Context *v, GetBitContext *gb) v->s.avctx->time_base.den = ff_vc1_fps_nr[nr - 1] * 1000; } } + if(v->broadcast) { // Pulldown may be present + v->s.avctx->time_base.den *= 2; + v->s.avctx->ticks_per_frame = 2; + } } if(get_bits1(gb)){ @@ -818,7 +822,7 @@ int vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) case 4: v->s.pict_type = AV_PICTURE_TYPE_P; // skipped pic v->p_frame_skipped = 1; - return 0; + break; } if(v->tfcntrflag) skip_bits(gb, 8); @@ -827,13 +831,16 @@ int vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) v->rptfrm = get_bits(gb, 2); } else { v->tff = get_bits1(gb); - v->rptfrm = get_bits1(gb); + v->rff = get_bits1(gb); } } if(v->panscanflag) { av_log_missing_feature(v->s.avctx, "Pan-scan", 0); //... } + if(v->p_frame_skipped) { + return 0; + } v->rnd = get_bits1(gb); if(v->interlace) v->uvsamp = get_bits1(gb); diff --git a/libavcodec/vc1_parser.c b/libavcodec/vc1_parser.c index 27ff1bdaa3..c4c15b326d 100644 --- a/libavcodec/vc1_parser.c +++ b/libavcodec/vc1_parser.c @@ -45,6 +45,7 @@ static void vc1_extract_headers(AVCodecParserContext *s, AVCodecContext *avctx, vpc->v.s.avctx = avctx; vpc->v.parse_only = 1; next = buf; + s->repeat_pict = 0; for(start = buf, end = buf + buf_size; next < end; start = next){ int buf2_size, size; @@ -73,6 +74,20 @@ static void vc1_extract_headers(AVCodecParserContext *s, AVCodecContext *avctx, else s->pict_type = vpc->v.s.pict_type; + if (avctx->ticks_per_frame > 1){ + // process pulldown flags + s->repeat_pict = 1; + // Pulldown flags are only valid when 'broadcast' has been set. + // So ticks_per_frame will be 2 + if (vpc->v.rff){ + // repeat field + s->repeat_pict = 2; + }else if (vpc->v.rptfrm){ + // repeat frames + s->repeat_pict = vpc->v.rptfrm * 2 + 1; + } + } + break; } } diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 735d6c2e51..f4d6f997f8 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -3897,6 +3897,18 @@ static int vc1_decode_frame(AVCodecContext *avctx, goto err; } + // process pulldown flags + s->current_picture_ptr->f.repeat_pict = 0; + // Pulldown flags are only valid when 'broadcast' has been set. + // So ticks_per_frame will be 2 + if (v->rff){ + // repeat field + s->current_picture_ptr->f.repeat_pict = 1; + }else if (v->rptfrm){ + // repeat frames + s->current_picture_ptr->f.repeat_pict = v->rptfrm * 2; + } + // for skipping the frame s->current_picture.f.pict_type = s->pict_type; s->current_picture.f.key_frame = s->pict_type == AV_PICTURE_TYPE_I; From 09c274e067ee10271127f0278046b019dcd599cd Mon Sep 17 00:00:00 2001 From: Dustin Brody Date: Tue, 16 Aug 2011 11:35:04 -0400 Subject: [PATCH 5/6] mpeg12: propagate chunk decode errors and fix conditional indentation Signed-off-by: Ronald S. Bultje --- libavcodec/mpeg12.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index 91eb3f5ece..4b20610cab 100644 --- a/libavcodec/mpeg12.c +++ b/libavcodec/mpeg12.c @@ -1911,6 +1911,8 @@ static int slice_decode_thread(AVCodecContext *c, void *arg){ //av_log(c, AV_LOG_DEBUG, "ret:%d resync:%d/%d mb:%d/%d ts:%d/%d ec:%d\n", //ret, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, s->start_mb_y, s->end_mb_y, s->error_count); if(ret < 0){ + if (c->error_recognition >= FF_ER_EXPLODE) + return AVERROR_INVALIDDATA; if(s->resync_mb_x>=0 && s->resync_mb_y>=0) ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, AC_ERROR|DC_ERROR|MV_ERROR); }else{ @@ -2265,8 +2267,10 @@ static int mpeg_decode_frame(AVCodecContext *avctx, s->slice_count= 0; - if(avctx->extradata && !avctx->frame_number) - decode_chunks(avctx, picture, data_size, avctx->extradata, avctx->extradata_size); + if(avctx->extradata && !avctx->frame_number && + decode_chunks(avctx, picture, data_size, avctx->extradata, avctx->extradata_size) < 0 && + avctx->error_recognition >= FF_ER_EXPLODE) + return AVERROR_INVALIDDATA; return decode_chunks(avctx, picture, data_size, buf, buf_size); } @@ -2318,11 +2322,13 @@ static int decode_chunks(AVCodecContext *avctx, switch(start_code) { case SEQ_START_CODE: if(last_code == 0){ - mpeg1_decode_sequence(avctx, buf_ptr, - input_size); + mpeg1_decode_sequence(avctx, buf_ptr, + input_size); s->sync=1; }else{ av_log(avctx, AV_LOG_ERROR, "ignoring SEQ_START_CODE after %X\n", last_code); + if (avctx->error_recognition >= FF_ER_EXPLODE) + return AVERROR_INVALIDDATA; } break; @@ -2351,6 +2357,8 @@ static int decode_chunks(AVCodecContext *avctx, last_code= PICTURE_START_CODE; }else{ av_log(avctx, AV_LOG_ERROR, "ignoring pic after %X\n", last_code); + if (avctx->error_recognition >= FF_ER_EXPLODE) + return AVERROR_INVALIDDATA; } break; case EXT_START_CODE: @@ -2362,6 +2370,8 @@ static int decode_chunks(AVCodecContext *avctx, mpeg_decode_sequence_extension(s); }else{ av_log(avctx, AV_LOG_ERROR, "ignoring seq ext after %X\n", last_code); + if (avctx->error_recognition >= FF_ER_EXPLODE) + return AVERROR_INVALIDDATA; } break; case 0x2: @@ -2378,6 +2388,8 @@ static int decode_chunks(AVCodecContext *avctx, mpeg_decode_picture_coding_extension(s); }else{ av_log(avctx, AV_LOG_ERROR, "ignoring pic cod ext after %X\n", last_code); + if (avctx->error_recognition >= FF_ER_EXPLODE) + return AVERROR_INVALIDDATA; } break; } @@ -2394,6 +2406,8 @@ static int decode_chunks(AVCodecContext *avctx, s->sync=1; }else{ av_log(avctx, AV_LOG_ERROR, "ignoring GOP_START_CODE after %X\n", last_code); + if (avctx->error_recognition >= FF_ER_EXPLODE) + return AVERROR_INVALIDDATA; } break; default: @@ -2438,6 +2452,8 @@ static int decode_chunks(AVCodecContext *avctx, if(!s2->pict_type){ av_log(avctx, AV_LOG_ERROR, "Missing picture start code\n"); + if (avctx->error_recognition >= FF_ER_EXPLODE) + return AVERROR_INVALIDDATA; break; } @@ -2448,6 +2464,8 @@ static int decode_chunks(AVCodecContext *avctx, } if(!s2->current_picture_ptr){ av_log(avctx, AV_LOG_ERROR, "current_picture not initialized\n"); + if (avctx->error_recognition >= FF_ER_EXPLODE) + return AVERROR_INVALIDDATA; return -1; } @@ -2476,6 +2494,8 @@ static int decode_chunks(AVCodecContext *avctx, emms_c(); if(ret < 0){ + if (avctx->error_recognition >= FF_ER_EXPLODE) + return AVERROR_INVALIDDATA; if(s2->resync_mb_x>=0 && s2->resync_mb_y>=0) ff_er_add_slice(s2, s2->resync_mb_x, s2->resync_mb_y, s2->mb_x, s2->mb_y, AC_ERROR|DC_ERROR|MV_ERROR); }else{ From f913eeea43078b3b9052efd8d8d29e7b29b39208 Mon Sep 17 00:00:00 2001 From: Dustin Brody Date: Tue, 16 Aug 2011 16:46:34 -0400 Subject: [PATCH 6/6] vp6: partially propagate huffman tree building errors during coeff model parsing and fix misspelling Signed-off-by: Ronald S. Bultje --- libavcodec/vp6.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c index 33cd43a1fa..657a5da7aa 100644 --- a/libavcodec/vp6.c +++ b/libavcodec/vp6.c @@ -215,8 +215,8 @@ static int vp6_huff_cmp(const void *va, const void *vb) return (a->count - b->count)*16 + (b->sym - a->sym); } -static void vp6_build_huff_tree(VP56Context *s, uint8_t coeff_model[], - const uint8_t *map, unsigned size, VLC *vlc) +static int vp6_build_huff_tree(VP56Context *s, uint8_t coeff_model[], + const uint8_t *map, unsigned size, VLC *vlc) { Node nodes[2*VP6_MAX_HUFF_SIZE], *tmp = &nodes[size]; int a, b, i; @@ -231,9 +231,9 @@ static void vp6_build_huff_tree(VP56Context *s, uint8_t coeff_model[], } free_vlc(vlc); - /* then build the huffman tree accodring to probabilities */ - ff_huff_build_tree(s->avctx, vlc, size, nodes, vp6_huff_cmp, - FF_HUFFMAN_FLAG_HNODE_FIRST); + /* then build the huffman tree according to probabilities */ + return ff_huff_build_tree(s->avctx, vlc, size, nodes, vp6_huff_cmp, + FF_HUFFMAN_FLAG_HNODE_FIRST); } static void vp6_parse_coeff_models(VP56Context *s)