Add SEI recovery point frame counter to H264Context and use it when
authorIvan Schreter <schreter@gmx.net>
Mon, 9 Feb 2009 23:04:16 +0000 (23:04 +0000)
committerCarl Eugen Hoyos <cehoyos@rainbow.studorg.tuwien.ac.at>
Mon, 9 Feb 2009 23:04:16 +0000 (23:04 +0000)
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
libavcodec/h264.h

index c5c88787442209accef665e0ab96c8f31c4c864d..603e6f2505603b09b3f983f6c23ccdcca9a63751 100644 (file)
@@ -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. */
index ed9e854bd55218c87ff0dd690592c772b5d1b3b0..cd960531c54c1a16039a61f230a5303c62a09578 100644 (file)
@@ -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