diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 17608b455a..c43a0beca0 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -1177,21 +1177,6 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl, sl->first_mb_addr = get_ue_golomb(&sl->gb); - 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); - } - - 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; - } - } - slice_type = get_ue_golomb_31(&sl->gb); if (slice_type > 9) { av_log(h->avctx, AV_LOG_ERROR, @@ -1226,11 +1211,6 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl, sl->pps_id); return AVERROR_INVALIDDATA; } - if (h->current_slice > 0 && - h->ps.pps != (const PPS*)h->ps.pps_list[sl->pps_id]->data) { - av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n"); - return AVERROR_INVALIDDATA; - } pps = (const PPS*)h->ps.pps_list[sl->pps_id]->data; if (!h->ps.sps_list[pps->sps_id]) { @@ -1265,21 +1245,6 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl, sl->picture_structure = picture_structure; sl->mb_field_decoding_flag = picture_structure != PICT_FRAME; - if (h->current_slice != 0) { - if (h->picture_structure != picture_structure || - h->droppable != droppable) { - 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 (picture_structure == PICT_FRAME) { h->curr_pic_num = h->poc.frame_num; h->max_pic_num = 1 << sps->log2_max_frame_num; @@ -1430,10 +1395,43 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl, 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); + } + + 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) { + av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n"); + return AVERROR_INVALIDDATA; + } + + 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);