From 37a558fe5154be9adaeed23dddf98f224e99cc32 Mon Sep 17 00:00:00 2001 From: Ivan Schreter Date: Mon, 9 Feb 2009 23:04:16 +0000 Subject: [PATCH] Add SEI recovery point frame counter to H264Context and use it when setting key_frame. Patch by Ivan Schreter schreter A gmx D net Originally committed as revision 17109 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/h264.c | 20 +++++++++++++++++++- libavcodec/h264.h | 9 +++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/libavcodec/h264.c b/libavcodec/h264.c index c5c8878..603e6f2 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -2208,6 +2208,7 @@ static av_cold int decode_init(AVCodecContext *avctx){ h->thread_context[0] = h; h->outputed_poc = INT_MIN; h->prev_poc_msb= 1<<16; + h->sei_recovery_frame_cnt = -1; return 0; } @@ -3141,6 +3142,7 @@ static void flush_dpb(AVCodecContext *avctx){ if(h->s.current_picture_ptr) h->s.current_picture_ptr->reference= 0; h->s.first_field= 0; + h->sei_recovery_frame_cnt = -1; ff_mpeg_flush(avctx); } @@ -6848,6 +6850,15 @@ static int decode_unregistered_user_data(H264Context *h, int size){ return 0; } +static int decode_recovery_point(H264Context *h){ + MpegEncContext * const s = &h->s; + + h->sei_recovery_frame_cnt = get_ue_golomb(&s->gb); + skip_bits(&s->gb, 4); /* 1b exact_match_flag, 1b broken_link_flag, 2b changing_slice_group_idc */ + + return 0; +} + static int decode_sei(H264Context *h){ MpegEncContext * const s = &h->s; @@ -6873,6 +6884,10 @@ static int decode_sei(H264Context *h){ if(decode_unregistered_user_data(h, size) < 0) return -1; break; + case SEI_TYPE_RECOVERY_POINT: + if(decode_recovery_point(h) < 0) + return -1; + break; default: skip_bits(&s->gb, 8*size); } @@ -7431,7 +7446,9 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size){ if((err = decode_slice_header(hx, h))) break; - s->current_picture_ptr->key_frame|= (hx->nal_unit_type == NAL_IDR_SLICE); + s->current_picture_ptr->key_frame |= + (hx->nal_unit_type == NAL_IDR_SLICE) || + (h->sei_recovery_frame_cnt >= 0); if(hx->redundant_pic_count==0 && hx->s.hurry_up < 5 && (avctx->skip_frame < AVDISCARD_NONREF || hx->nal_ref_idc) && (avctx->skip_frame < AVDISCARD_BIDIR || hx->slice_type_nos!=FF_B_TYPE) @@ -7668,6 +7685,7 @@ static int decode_frame(AVCodecContext *avctx, ff_er_frame_end(s); MPV_frame_end(s); + h->sei_recovery_frame_cnt = -1; 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 ed9e854..cd96053 100644 --- a/libavcodec/h264.h +++ b/libavcodec/h264.h @@ -500,6 +500,15 @@ typedef struct H264Context{ */ SEI_PicStructType sei_pic_struct; + /** + * recovery_frame_cnt from SEI message + * + * Set to -1 if no recovery point SEI message found or to number of frames + * before playback synchronizes. Frames having recovery point are key + * frames. + */ + int sei_recovery_frame_cnt; + int is_complex; int luma_weight_flag[2]; ///< 7.4.3.2 luma_weight_lX_flag -- 2.7.4