ffmpeg | branch: master | Timothy Gu <timothyg...@gmail.com> | Wed Aug 3 19:46:06 2016 -0700| [de625312862a99500ce7aa1703b5d783ae66d704] | committer: Timothy Gu
Merge commit 'e26c64148be8a20ace7512d96503172fb5e9753b' * commit 'e26c64148be8a20ace7512d96503172fb5e9753b': h264: discard slices of redundant pictures right after parsing the slice header Conflicts: libavcodec/h264_slice.c libavcodec/h264dec.c TODO: fix indentation Merged-by: Timothy Gu <timothyg...@gmail.com> > http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=de625312862a99500ce7aa1703b5d783ae66d704 --- libavcodec/h264_slice.c | 4 ++++ libavcodec/h264dec.c | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index c2490cb..c6f40e5 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -1738,6 +1738,10 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl, if (ret < 0) return ret; + // discard redundant pictures + if (sl->redundant_pic_count > 0) + return 0; + if (sl->first_mb_addr == 0 || !h->current_slice) { if (h->setup_finished) { av_log(h->avctx, AV_LOG_ERROR, "Too many fields\n"); diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index 9779774..c72a7fc 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -799,6 +799,9 @@ again: if ((err = ff_h264_decode_slice_header(h, sl, nal))) break; + if (sl->redundant_pic_count > 0) + break; + if (h->sei.recovery_point.recovery_frame_cnt >= 0) { const int sei_recovery_frame_cnt = h->sei.recovery_point.recovery_frame_cnt; @@ -845,7 +848,6 @@ again: #endif } - if (sl->redundant_pic_count == 0) { if (avctx->hwaccel) { ret = avctx->hwaccel->decode_slice(avctx, nal->raw_data, @@ -864,7 +866,6 @@ again: #endif } else context_count++; - } break; case H264_NAL_DPA: case H264_NAL_DPB: ====================================================================== diff --cc libavcodec/h264_slice.c index c2490cb,4910396..c6f40e5 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@@ -1738,62 -1565,30 +1738,66 @@@ int ff_h264_decode_slice_header(H264Con if (ret < 0) return ret; + // discard redundant pictures + if (sl->redundant_pic_count > 0) + return 0; + - if (!h->setup_finished) { - 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 (sl->first_mb_addr == 0 || !h->current_slice) { + if (h->setup_finished) { + av_log(h->avctx, AV_LOG_ERROR, "Too many fields\n"); + 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); + if (sl->first_mb_addr == 0) { // FIXME better field boundary detection + if (h->current_slice) { + 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 == H264_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 == 0) { - ret = h264_field_start(h, sl, nal); - if (ret < 0) - return ret; + 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 != H264_NAL_IDR_SLICE && h->sei.recovery_point.recovery_frame_cnt < 0) || + h->avctx->skip_frame >= AVDISCARD_ALL) { + return SLICE_SKIPED; } } diff --cc libavcodec/h264dec.c index 9779774,38ecc94..c72a7fc --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@@ -799,25 -701,18 +799,28 @@@ again if ((err = ff_h264_decode_slice_header(h, sl, nal))) break; + if (sl->redundant_pic_count > 0) + break; + - if (h->sei.recovery_point.recovery_frame_cnt >= 0 && h->recovery_frame < 0) { - h->recovery_frame = (h->poc.frame_num + h->sei.recovery_point.recovery_frame_cnt) & - ((1 << h->ps.sps->log2_max_frame_num) - 1); + if (h->sei.recovery_point.recovery_frame_cnt >= 0) { + const int sei_recovery_frame_cnt = h->sei.recovery_point.recovery_frame_cnt; + + if (h->poc.frame_num != sei_recovery_frame_cnt || sl->slice_type_nos != AV_PICTURE_TYPE_I) + h->valid_recovery_point = 1; + + if ( h->recovery_frame < 0 + || av_mod_uintp2(h->recovery_frame - h->poc.frame_num, h->ps.sps->log2_max_frame_num) > sei_recovery_frame_cnt) { + h->recovery_frame = av_mod_uintp2(h->poc.frame_num + sei_recovery_frame_cnt, h->ps.sps->log2_max_frame_num); + + if (!h->valid_recovery_point) + h->recovery_frame = h->poc.frame_num; + } } - h->cur_pic_ptr->f->key_frame |= - (nal->type == H264_NAL_IDR_SLICE) || (h->sei.recovery_point.recovery_frame_cnt >= 0); + h->cur_pic_ptr->f->key_frame |= (nal->type == H264_NAL_IDR_SLICE); - if (nal->type == H264_NAL_IDR_SLICE || h->recovery_frame == h->poc.frame_num) { + if (nal->type == H264_NAL_IDR_SLICE || + (h->recovery_frame == h->poc.frame_num && nal->ref_idc)) { h->recovery_frame = -1; h->cur_pic_ptr->recovered = 1; } @@@ -834,37 -725,21 +837,35 @@@ if (h->current_slice == 1) { if (!(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS)) decode_postinit(h, i >= nals_needed); + + if (h->avctx->hwaccel && + (ret = h->avctx->hwaccel->start_frame(h->avctx, buf, buf_size)) < 0) + goto end; +#if FF_API_CAP_VDPAU + if (CONFIG_H264_VDPAU_DECODER && + h->avctx->codec->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU) + ff_vdpau_h264_picture_start(h); +#endif } - if (sl->redundant_pic_count == 0) { - if ((avctx->skip_frame < AVDISCARD_NONREF || nal->ref_idc) && - (avctx->skip_frame < AVDISCARD_BIDIR || - sl->slice_type_nos != AV_PICTURE_TYPE_B) && - (avctx->skip_frame < AVDISCARD_NONKEY || - h->cur_pic_ptr->f->key_frame) && - avctx->skip_frame < AVDISCARD_ALL) { if (avctx->hwaccel) { - ret = avctx->hwaccel->decode_slice(avctx, nal->raw_data, nal->raw_size); + ret = avctx->hwaccel->decode_slice(avctx, + nal->raw_data, + nal->raw_size); if (ret < 0) - return ret; + goto end; +#if FF_API_CAP_VDPAU + } else if (CONFIG_H264_VDPAU_DECODER && + h->avctx->codec->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU) { + ff_vdpau_add_data_chunk(h->cur_pic_ptr->f->data[0], + start_code, + sizeof(start_code)); + ff_vdpau_add_data_chunk(h->cur_pic_ptr->f->data[0], + nal->raw_data, + nal->raw_size); +#endif } else context_count++; -- } break; case H264_NAL_DPA: case H264_NAL_DPB: _______________________________________________ ffmpeg-cvslog mailing list ffmpeg-cvslog@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-cvslog