ffmpeg | branch: master | Clément Bœsch <u...@pkh.me> | Wed Jul 27 16:11:02 2016 +0200| [78c7197ea0e5c53393849a32dd6f49e3b89f7815] | committer: Clément Bœsch
Merge commit '54dd9b1cdd9e54f1ee39ae25af0324f8aba2831b' * commit '54dd9b1cdd9e54f1ee39ae25af0324f8aba2831b': h264: set mb_aff_frame in frame_start() h264: move the block starting a new field out of slice_header_parse() Both commits are merged at the same time in order to prevent a regression with Ticket #4440 (see 38660128). Merged-by: Clément Bœsch <u...@pkh.me> > http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=78c7197ea0e5c53393849a32dd6f49e3b89f7815 --- libavcodec/h264_slice.c | 185 +++++++++++++++++++++++------------------------- 1 file changed, 90 insertions(+), 95 deletions(-) diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index ee7dedb..befea2a 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -385,6 +385,7 @@ int ff_h264_update_thread_context(AVCodecContext *dst, h->coded_picture_number = h1->coded_picture_number; h->first_field = h1->first_field; h->picture_structure = h1->picture_structure; + h->mb_aff_frame = h1->mb_aff_frame; h->droppable = h1->droppable; h->backup_width = h1->backup_width; h->backup_height = h1->backup_height; @@ -554,6 +555,8 @@ static int h264_frame_start(H264Context *h) h->postpone_filter = 0; + h->mb_aff_frame = h->ps.sps->mb_aff && (h->picture_structure == PICT_FRAME); + assert(h->cur_pic_ptr->long_ref == 0); return 0; @@ -1336,59 +1339,13 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl, unsigned int slice_type, tmp, i; int field_pic_flag, bottom_field_flag; int first_slice = sl == h->slice_ctx && !h->current_slice; - int frame_num, droppable, picture_structure; - int mb_aff_frame, last_mb_aff_frame; + int frame_num, picture_structure; if (first_slice) av_assert0(!h->setup_finished); sl->first_mb_addr = get_ue_golomb_long(&sl->gb); - if (sl->first_mb_addr == 0) { // FIXME better field boundary detection - if (h->current_slice) { - if (h->setup_finished) { - av_log(h->avctx, AV_LOG_ERROR, "Too many fields\n"); - return AVERROR_INVALIDDATA; - } - if (h->max_contexts > 1) { - if (!h->single_decode_warning) { - av_log(h->avctx, AV_LOG_WARNING, "Cannot decode multiple access units as slice threads\n"); - h->single_decode_warning = 1; - } - h->max_contexts = 1; - return SLICE_SINGLETHREAD; - } - - if (h->cur_pic_ptr && FIELD_PICTURE(h) && h->first_field) { - ret = ff_h264_field_end(h, h->slice_ctx, 1); - h->current_slice = 0; - if (ret < 0) - return ret; - } else if (h->cur_pic_ptr && !FIELD_PICTURE(h) && !h->first_field && h->nal_unit_type == NAL_IDR_SLICE) { - av_log(h, AV_LOG_WARNING, "Broken frame packetizing\n"); - ret = ff_h264_field_end(h, h->slice_ctx, 1); - h->current_slice = 0; - ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 0); - ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 1); - h->cur_pic_ptr = NULL; - if (ret < 0) - return ret; - } else - return AVERROR_INVALIDDATA; - } - - if (!h->first_field) { - if (h->cur_pic_ptr && !h->droppable) { - ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, - h->picture_structure == PICT_BOTTOM_FIELD); - } - h->cur_pic_ptr = NULL; - } - } - - if (!h->current_slice) - av_assert0(sl == h->slice_ctx); - slice_type = get_ue_golomb_31(&sl->gb); if (slice_type > 9) { av_log(h->avctx, AV_LOG_ERROR, @@ -1412,17 +1369,6 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl, return AVERROR_INVALIDDATA; } - if (h->current_slice == 0 && !h->first_field) { - if ( - (h->avctx->skip_frame >= AVDISCARD_NONREF && !h->nal_ref_idc) || - (h->avctx->skip_frame >= AVDISCARD_BIDIR && sl->slice_type_nos == AV_PICTURE_TYPE_B) || - (h->avctx->skip_frame >= AVDISCARD_NONINTRA && sl->slice_type_nos != AV_PICTURE_TYPE_I) || - (h->avctx->skip_frame >= AVDISCARD_NONKEY && h->nal_unit_type != NAL_IDR_SLICE && h->sei.recovery_point.recovery_frame_cnt < 0) || - h->avctx->skip_frame >= AVDISCARD_ALL) { - return SLICE_SKIPED; - } - } - sl->pps_id = get_ue_golomb(&sl->gb); if (sl->pps_id >= MAX_PPS_COUNT) { av_log(h->avctx, AV_LOG_ERROR, "pps_id %u out of range\n", sl->pps_id); @@ -1442,19 +1388,6 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl, "non-existing SPS %u referenced\n", pps->sps_id); return AVERROR_INVALIDDATA; } - if (!first_slice) { - if (h->ps.pps->sps_id != pps->sps_id || - h->ps.pps->transform_8x8_mode != pps->transform_8x8_mode /*|| - (h->setup_finished && h->ps.pps != pps)*/) { - av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n"); - return AVERROR_INVALIDDATA; - } - if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) { - av_log(h->avctx, AV_LOG_ERROR, - "SPS changed in the middle of the frame\n"); - return AVERROR_INVALIDDATA; - } - } sps = (const SPS*)h->ps.sps_list[pps->sps_id]->data; @@ -1471,10 +1404,7 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl, h->poc.frame_num = frame_num; sl->mb_mbaff = 0; - mb_aff_frame = 0; - last_mb_aff_frame = h->mb_aff_frame; - droppable = nal->ref_idc == 0; if (sps->frame_mbs_only_flag) { picture_structure = PICT_FRAME; } else { @@ -1489,29 +1419,9 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl, picture_structure = PICT_TOP_FIELD + bottom_field_flag; } else { picture_structure = PICT_FRAME; - mb_aff_frame = sps->mb_aff; - } - } - - if (h->current_slice) { - if (h->picture_structure != picture_structure || - h->droppable != droppable || - last_mb_aff_frame != mb_aff_frame) { - av_log(h->avctx, AV_LOG_ERROR, - "Changing field mode (%d -> %d) between slices is not allowed\n", - h->picture_structure, picture_structure); - return AVERROR_INVALIDDATA; - } else if (!h->cur_pic_ptr) { - av_log(h->avctx, AV_LOG_ERROR, - "unset cur_pic_ptr on slice %d\n", - h->current_slice + 1); - return AVERROR_INVALIDDATA; } } - if (!h->setup_finished) { - h->mb_aff_frame = mb_aff_frame; - } sl->picture_structure = picture_structure; sl->mb_field_decoding_flag = picture_structure != PICT_FRAME; @@ -1663,13 +1573,98 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl, int first_slice = sl == h->slice_ctx && !h->current_slice; ret = h264_slice_header_parse(h, sl, nal); - if (ret) // can not be ret<0 because of SLICE_SKIPED, SLICE_SINGLETHREAD, ... + if (ret < 0) return ret; + if (sl->first_mb_addr == 0) { // FIXME better field boundary detection + if (h->current_slice) { + if (h->setup_finished) { + av_log(h->avctx, AV_LOG_ERROR, "Too many fields\n"); + return AVERROR_INVALIDDATA; + } + if (h->max_contexts > 1) { + if (!h->single_decode_warning) { + av_log(h->avctx, AV_LOG_WARNING, "Cannot decode multiple access units as slice threads\n"); + h->single_decode_warning = 1; + } + h->max_contexts = 1; + return SLICE_SINGLETHREAD; + } + + if (h->cur_pic_ptr && FIELD_PICTURE(h) && h->first_field) { + ret = ff_h264_field_end(h, h->slice_ctx, 1); + h->current_slice = 0; + if (ret < 0) + return ret; + } else if (h->cur_pic_ptr && !FIELD_PICTURE(h) && !h->first_field && h->nal_unit_type == NAL_IDR_SLICE) { + av_log(h, AV_LOG_WARNING, "Broken frame packetizing\n"); + ret = ff_h264_field_end(h, h->slice_ctx, 1); + h->current_slice = 0; + ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 0); + ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 1); + h->cur_pic_ptr = NULL; + if (ret < 0) + return ret; + } else + return AVERROR_INVALIDDATA; + } + + if (!h->first_field) { + if (h->cur_pic_ptr && !h->droppable) { + ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, + h->picture_structure == PICT_BOTTOM_FIELD); + } + h->cur_pic_ptr = NULL; + } + } + + if (!h->current_slice) + av_assert0(sl == h->slice_ctx); + + if (h->current_slice == 0 && !h->first_field) { + if ( + (h->avctx->skip_frame >= AVDISCARD_NONREF && !h->nal_ref_idc) || + (h->avctx->skip_frame >= AVDISCARD_BIDIR && sl->slice_type_nos == AV_PICTURE_TYPE_B) || + (h->avctx->skip_frame >= AVDISCARD_NONINTRA && sl->slice_type_nos != AV_PICTURE_TYPE_I) || + (h->avctx->skip_frame >= AVDISCARD_NONKEY && h->nal_unit_type != NAL_IDR_SLICE && h->sei.recovery_point.recovery_frame_cnt < 0) || + h->avctx->skip_frame >= AVDISCARD_ALL) { + return SLICE_SKIPED; + } + } + + if (!first_slice) { + const PPS *pps = (const PPS*)h->ps.pps_list[sl->pps_id]->data; + + if (h->ps.pps->sps_id != pps->sps_id || + h->ps.pps->transform_8x8_mode != pps->transform_8x8_mode /*|| + (h->setup_finished && h->ps.pps != pps)*/) { + av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n"); + return AVERROR_INVALIDDATA; + } + if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) { + av_log(h->avctx, AV_LOG_ERROR, + "SPS changed in the middle of the frame\n"); + return AVERROR_INVALIDDATA; + } + } + if (h->current_slice == 0) { ret = h264_field_start(h, sl, nal, first_slice); if (ret < 0) return ret; + } else { + if (h->picture_structure != sl->picture_structure || + h->droppable != (nal->ref_idc == 0)) { + av_log(h->avctx, AV_LOG_ERROR, + "Changing field mode (%d -> %d) between slices is not allowed\n", + h->picture_structure, sl->picture_structure); + return AVERROR_INVALIDDATA; + } else if (!h->cur_pic_ptr) { + av_log(h->avctx, AV_LOG_ERROR, + "unset cur_pic_ptr on slice %d\n", + h->current_slice + 1); + return AVERROR_INVALIDDATA; + } } av_assert1(h->mb_num == h->mb_width * h->mb_height); ====================================================================== diff --cc libavcodec/h264_slice.c index ee7dedb,4b0adab..befea2a --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@@ -385,10 -377,8 +385,11 @@@ int ff_h264_update_thread_context(AVCod h->coded_picture_number = h1->coded_picture_number; h->first_field = h1->first_field; h->picture_structure = h1->picture_structure; + h->mb_aff_frame = h1->mb_aff_frame; h->droppable = h1->droppable; + h->backup_width = h1->backup_width; + h->backup_height = h1->backup_height; + h->backup_pix_fmt = h1->backup_pix_fmt; for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) { ff_h264_unref_picture(h, &h->DPB[i]); @@@ -1335,60 -1175,10 +1338,14 @@@ static int h264_slice_header_parse(H264 int ret; unsigned int slice_type, tmp, i; int field_pic_flag, bottom_field_flag; - int frame_num, droppable, picture_structure; + int first_slice = sl == h->slice_ctx && !h->current_slice; - int frame_num, droppable, picture_structure; - int mb_aff_frame, last_mb_aff_frame; ++ int frame_num, picture_structure; + + if (first_slice) + av_assert0(!h->setup_finished); - sl->first_mb_addr = get_ue_golomb(&sl->gb); + sl->first_mb_addr = get_ue_golomb_long(&sl->gb); - if (sl->first_mb_addr == 0) { // FIXME better field boundary detection - if (h->current_slice) { - if (h->setup_finished) { - av_log(h->avctx, AV_LOG_ERROR, "Too many fields\n"); - return AVERROR_INVALIDDATA; - } - if (h->max_contexts > 1) { - if (!h->single_decode_warning) { - av_log(h->avctx, AV_LOG_WARNING, "Cannot decode multiple access units as slice threads\n"); - h->single_decode_warning = 1; - } - h->max_contexts = 1; - return SLICE_SINGLETHREAD; - } - - if (h->cur_pic_ptr && FIELD_PICTURE(h) && h->first_field) { - ret = ff_h264_field_end(h, h->slice_ctx, 1); - h->current_slice = 0; - if (ret < 0) - return ret; - } else if (h->cur_pic_ptr && !FIELD_PICTURE(h) && !h->first_field && h->nal_unit_type == NAL_IDR_SLICE) { - av_log(h, AV_LOG_WARNING, "Broken frame packetizing\n"); - ret = ff_h264_field_end(h, h->slice_ctx, 1); - h->current_slice = 0; - ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 0); - ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 1); - h->cur_pic_ptr = NULL; - if (ret < 0) - return ret; - } else - return AVERROR_INVALIDDATA; - } - - if (!h->first_field) { - if (h->cur_pic_ptr && !h->droppable) { - ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, - h->picture_structure == PICT_BOTTOM_FIELD); - } - h->cur_pic_ptr = NULL; - } - } - - if (!h->current_slice) - av_assert0(sl == h->slice_ctx); - slice_type = get_ue_golomb_31(&sl->gb); if (slice_type > 9) { av_log(h->avctx, AV_LOG_ERROR, @@@ -1442,20 -1220,6 +1388,7 @@@ "non-existing SPS %u referenced\n", pps->sps_id); return AVERROR_INVALIDDATA; } - if (!first_slice) { - if (h->ps.pps->sps_id != pps->sps_id || - h->ps.pps->transform_8x8_mode != pps->transform_8x8_mode /*|| - (h->setup_finished && h->ps.pps != pps)*/) { - av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n"); - return AVERROR_INVALIDDATA; - } - if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) { - av_log(h->avctx, AV_LOG_ERROR, - "SPS changed in the middle of the frame\n"); - return AVERROR_INVALIDDATA; - } - } + sps = (const SPS*)h->ps.sps_list[pps->sps_id]->data; frame_num = get_bits(&sl->gb, sps->log2_max_frame_num); @@@ -1471,10 -1227,8 +1404,7 @@@ h->poc.frame_num = frame_num; sl->mb_mbaff = 0; - mb_aff_frame = 0; - last_mb_aff_frame = h->mb_aff_frame; -- droppable = nal->ref_idc == 0; if (sps->frame_mbs_only_flag) { picture_structure = PICT_FRAME; } else { @@@ -1489,29 -1238,8 +1419,9 @@@ picture_structure = PICT_TOP_FIELD + bottom_field_flag; } else { picture_structure = PICT_FRAME; - mb_aff_frame = sps->mb_aff; - } - } - - if (h->current_slice) { - if (h->picture_structure != picture_structure || - h->droppable != droppable || - last_mb_aff_frame != mb_aff_frame) { - av_log(h->avctx, AV_LOG_ERROR, - "Changing field mode (%d -> %d) between slices is not allowed\n", - h->picture_structure, picture_structure); - return AVERROR_INVALIDDATA; - } else if (!h->cur_pic_ptr) { - av_log(h->avctx, AV_LOG_ERROR, - "unset cur_pic_ptr on slice %d\n", - h->current_slice + 1); - return AVERROR_INVALIDDATA; } } + - if (!h->setup_finished) { - h->mb_aff_frame = mb_aff_frame; - } sl->picture_structure = picture_structure; sl->mb_field_decoding_flag = picture_structure != PICT_FRAME; @@@ -1660,19 -1388,51 +1570,104 @@@ int ff_h264_decode_slice_header(H264Con const H2645NAL *nal) { int i, j, ret = 0; + int first_slice = sl == h->slice_ctx && !h->current_slice; ret = h264_slice_header_parse(h, sl, nal); - if (ret) // can not be ret<0 because of SLICE_SKIPED, SLICE_SINGLETHREAD, ... + if (ret < 0) return ret; + if (sl->first_mb_addr == 0) { // FIXME better field boundary detection - if (h->current_slice && h->cur_pic_ptr && FIELD_PICTURE(h)) { - ff_h264_field_end(h, sl, 1); ++ if (h->current_slice) { ++ if (h->setup_finished) { ++ av_log(h->avctx, AV_LOG_ERROR, "Too many fields\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ if (h->max_contexts > 1) { ++ if (!h->single_decode_warning) { ++ av_log(h->avctx, AV_LOG_WARNING, "Cannot decode multiple access units as slice threads\n"); ++ h->single_decode_warning = 1; ++ } ++ h->max_contexts = 1; ++ return SLICE_SINGLETHREAD; ++ } ++ ++ if (h->cur_pic_ptr && FIELD_PICTURE(h) && h->first_field) { ++ ret = ff_h264_field_end(h, h->slice_ctx, 1); ++ h->current_slice = 0; ++ if (ret < 0) ++ return ret; ++ } else if (h->cur_pic_ptr && !FIELD_PICTURE(h) && !h->first_field && h->nal_unit_type == NAL_IDR_SLICE) { ++ av_log(h, AV_LOG_WARNING, "Broken frame packetizing\n"); ++ ret = ff_h264_field_end(h, h->slice_ctx, 1); ++ h->current_slice = 0; ++ ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 0); ++ ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 1); ++ h->cur_pic_ptr = NULL; ++ if (ret < 0) ++ return ret; ++ } else ++ return AVERROR_INVALIDDATA; + } + - h->current_slice = 0; + if (!h->first_field) { + if (h->cur_pic_ptr && !h->droppable) { + ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, + h->picture_structure == PICT_BOTTOM_FIELD); + } + h->cur_pic_ptr = NULL; + } + } + - if (h->current_slice == 0) { - ret = h264_field_start(h, sl, nal); - if (ret < 0) - return ret; - } else { - if (h->ps.pps != (const PPS*)h->ps.pps_list[sl->pps_id]->data) { ++ if (!h->current_slice) ++ av_assert0(sl == h->slice_ctx); ++ ++ if (h->current_slice == 0 && !h->first_field) { ++ if ( ++ (h->avctx->skip_frame >= AVDISCARD_NONREF && !h->nal_ref_idc) || ++ (h->avctx->skip_frame >= AVDISCARD_BIDIR && sl->slice_type_nos == AV_PICTURE_TYPE_B) || ++ (h->avctx->skip_frame >= AVDISCARD_NONINTRA && sl->slice_type_nos != AV_PICTURE_TYPE_I) || ++ (h->avctx->skip_frame >= AVDISCARD_NONKEY && h->nal_unit_type != NAL_IDR_SLICE && h->sei.recovery_point.recovery_frame_cnt < 0) || ++ h->avctx->skip_frame >= AVDISCARD_ALL) { ++ return SLICE_SKIPED; ++ } ++ } ++ ++ if (!first_slice) { ++ const PPS *pps = (const PPS*)h->ps.pps_list[sl->pps_id]->data; ++ ++ if (h->ps.pps->sps_id != pps->sps_id || ++ h->ps.pps->transform_8x8_mode != pps->transform_8x8_mode /*|| ++ (h->setup_finished && h->ps.pps != pps)*/) { + av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n"); + return AVERROR_INVALIDDATA; + } ++ if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) { ++ av_log(h->avctx, AV_LOG_ERROR, ++ "SPS changed in the middle of the frame\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ } + + if (h->current_slice == 0) { + ret = h264_field_start(h, sl, nal, first_slice); + if (ret < 0) + return ret; ++ } else { + if (h->picture_structure != sl->picture_structure || + h->droppable != (nal->ref_idc == 0)) { + av_log(h->avctx, AV_LOG_ERROR, + "Changing field mode (%d -> %d) between slices is not allowed\n", + h->picture_structure, sl->picture_structure); + return AVERROR_INVALIDDATA; + } else if (!h->cur_pic_ptr) { + av_log(h->avctx, AV_LOG_ERROR, + "unset cur_pic_ptr on slice %d\n", + h->current_slice + 1); + return AVERROR_INVALIDDATA; + } } - assert(h->mb_num == h->mb_width * h->mb_height); + av_assert1(h->mb_num == h->mb_width * h->mb_height); if (sl->first_mb_addr << FIELD_OR_MBAFF_PICTURE(h) >= h->mb_num || sl->first_mb_addr >= h->mb_num) { av_log(h->avctx, AV_LOG_ERROR, "first_mb_in_slice overflow\n"); _______________________________________________ ffmpeg-cvslog mailing list ffmpeg-cvslog@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-cvslog