From a8cbe5a0ccebf60a8a8b0aba5d5716dd54c1595c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 2 Jul 2016 16:48:26 +0200 Subject: h264_ps: export actual height in MBs as SPS.mb_height Currently, SPS.mb_height is actually what the spec calls PicHeightInMapUnits, which is half the frame height when interlacing is allowed. Calling this 'mb_height' is quite confusing, and there are at least two associated bugs where this field is treated as the actual frame height - in the h264 parser and in the code computing maximum reordering buffer size for a given level. Fix those issues (and avoid possible future ones) by exporting the real frame height in this field. --- libavcodec/h264_ps.c | 10 +++++++++- libavcodec/h264_ps.h | 3 ++- libavcodec/h264_slice.c | 4 ++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/libavcodec/h264_ps.c b/libavcodec/h264_ps.c index 4a56c738bf..d1b4280713 100644 --- a/libavcodec/h264_ps.c +++ b/libavcodec/h264_ps.c @@ -439,6 +439,15 @@ int ff_h264_decode_seq_parameter_set(GetBitContext *gb, AVCodecContext *avctx, sps->gaps_in_frame_num_allowed_flag = get_bits1(gb); sps->mb_width = get_ue_golomb(gb) + 1; sps->mb_height = get_ue_golomb(gb) + 1; + + sps->frame_mbs_only_flag = get_bits1(gb); + + if (sps->mb_height >= INT_MAX / 2) { + av_log(avctx, AV_LOG_ERROR, "height overflow\n"); + goto fail; + } + sps->mb_height *= 2 - sps->frame_mbs_only_flag; + if ((unsigned)sps->mb_width >= INT_MAX / 16 || (unsigned)sps->mb_height >= INT_MAX / 16 || av_image_check_size(16 * sps->mb_width, @@ -447,7 +456,6 @@ int ff_h264_decode_seq_parameter_set(GetBitContext *gb, AVCodecContext *avctx, goto fail; } - sps->frame_mbs_only_flag = get_bits1(gb); if (!sps->frame_mbs_only_flag) sps->mb_aff = get_bits1(gb); else diff --git a/libavcodec/h264_ps.h b/libavcodec/h264_ps.h index 2835b870ca..9a32d932f7 100644 --- a/libavcodec/h264_ps.h +++ b/libavcodec/h264_ps.h @@ -56,7 +56,8 @@ typedef struct SPS { int ref_frame_count; ///< num_ref_frames int gaps_in_frame_num_allowed_flag; int mb_width; ///< pic_width_in_mbs_minus1 + 1 - int mb_height; ///< pic_height_in_map_units_minus1 + 1 + ///< (pic_height_in_map_units_minus1 + 1) * (2 - frame_mbs_only_flag) + int mb_height; int frame_mbs_only_flag; int mb_aff; ///< mb_adaptive_frame_field_flag int direct_8x8_inference_flag; diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index aa53570185..ce8df50834 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -926,11 +926,11 @@ static int h264_init_ps(H264Context *h, const H264SliceContext *sl) h->avctx->refs = sps->ref_frame_count; if (h->mb_width != sps->mb_width || - h->mb_height != sps->mb_height * (2 - sps->frame_mbs_only_flag)) + h->mb_height != sps->mb_height) needs_reinit = 1; h->mb_width = sps->mb_width; - h->mb_height = sps->mb_height * (2 - sps->frame_mbs_only_flag); + h->mb_height = sps->mb_height; h->mb_num = h->mb_width * h->mb_height; h->mb_stride = h->mb_width + 1; -- cgit v1.2.3