From 2ea89d9274bf27419239c05182c23d30c402cb22 Mon Sep 17 00:00:00 2001 From: Ivan Schreter Date: Wed, 18 Feb 2009 23:33:30 +0000 Subject: [PATCH] Parse buffering period (H.264, D.1.1). Patch by Ivan Schreter, schreter gmx net Originally committed as revision 17441 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/h264.c | 38 ++++++++++++++++++++++++++++++++++++++ libavcodec/h264.h | 5 +++++ 2 files changed, 43 insertions(+) diff --git a/libavcodec/h264.c b/libavcodec/h264.c index b64a527677..5cbe139154 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -2211,6 +2211,7 @@ static av_cold int decode_init(AVCodecContext *avctx){ h->sei_recovery_frame_cnt = -1; h->sei_dpb_output_delay = 0; h->sei_cpb_removal_delay = -1; + h->sei_buffering_period_present = 0; return 0; } @@ -3148,6 +3149,7 @@ static void flush_dpb(AVCodecContext *avctx){ h->sei_recovery_frame_cnt = -1; h->sei_dpb_output_delay = 0; h->sei_cpb_removal_delay = -1; + h->sei_buffering_period_present = 0; ff_mpeg_flush(avctx); } @@ -6864,6 +6866,37 @@ static int decode_recovery_point(H264Context *h){ return 0; } +static int decode_buffering_period(H264Context *h){ + MpegEncContext * const s = &h->s; + unsigned int sps_id; + int sched_sel_idx; + SPS *sps; + + sps_id = get_ue_golomb_31(&s->gb); + if(sps_id > 31 || !h->sps_buffers[sps_id]) { + av_log(h->s.avctx, AV_LOG_ERROR, "non-existing SPS %d referenced in buffering period\n", sps_id); + return -1; + } + sps = h->sps_buffers[sps_id]; + + // NOTE: This is really so duplicated in the standard... See H.264, D.1.1 + if (sps->nal_hrd_parameters_present_flag) { + for (sched_sel_idx = 0; sched_sel_idx < sps->cpb_cnt; sched_sel_idx++) { + h->initial_cpb_removal_delay[sched_sel_idx] = get_bits(&s->gb, sps->initial_cpb_removal_delay_length); + skip_bits(&s->gb, sps->initial_cpb_removal_delay_length); // initial_cpb_removal_delay_offset + } + } + if (sps->vcl_hrd_parameters_present_flag) { + for (sched_sel_idx = 0; sched_sel_idx < sps->cpb_cnt; sched_sel_idx++) { + h->initial_cpb_removal_delay[sched_sel_idx] = get_bits(&s->gb, sps->initial_cpb_removal_delay_length); + skip_bits(&s->gb, sps->initial_cpb_removal_delay_length); // initial_cpb_removal_delay_offset + } + } + + h->sei_buffering_period_present = 1; + return 0; +} + static int decode_sei(H264Context *h){ MpegEncContext * const s = &h->s; @@ -6893,6 +6926,10 @@ static int decode_sei(H264Context *h){ if(decode_recovery_point(h) < 0) return -1; break; + case SEI_BUFFERING_PERIOD: + if(decode_buffering_period(h) < 0) + return -1; + break; default: skip_bits(&s->gb, 8*size); } @@ -7698,6 +7735,7 @@ static int decode_frame(AVCodecContext *avctx, h->sei_recovery_frame_cnt = -1; h->sei_dpb_output_delay = 0; h->sei_cpb_removal_delay = -1; + h->sei_buffering_period_present = 0; if (cur->field_poc[0]==INT_MAX || cur->field_poc[1]==INT_MAX) { /* Wait for second field. */ diff --git a/libavcodec/h264.h b/libavcodec/h264.h index 4a77d25d7d..9331e22358 100644 --- a/libavcodec/h264.h +++ b/libavcodec/h264.h @@ -115,6 +115,7 @@ enum { * SEI message types */ typedef enum { + SEI_BUFFERING_PERIOD = 0, ///< buffering period (H.264, D.1.1) SEI_TYPE_PIC_TIMING = 1, ///< picture timing SEI_TYPE_USER_DATA_UNREGISTERED = 5, ///< unregistered user data SEI_TYPE_RECOVERY_POINT = 6 ///< recovery point (frame # to decoder sync) @@ -525,6 +526,10 @@ typedef struct H264Context{ int luma_weight_flag[2]; ///< 7.4.3.2 luma_weight_lX_flag int chroma_weight_flag[2]; ///< 7.4.3.2 chroma_weight_lX_flag + + // Timestamp stuff + int sei_buffering_period_present; ///< Buffering period SEI flag + int initial_cpb_removal_delay[32]; ///< Initial timestamps for CPBs }H264Context; #endif /* AVCODEC_H264_H */