]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/h264_slice.c
h264: handle frame recovery in h264_field_start()
[ffmpeg] / libavcodec / h264_slice.c
index 244640fa59c9ecaf7f720864b0b90b51c59943e3..2b7e0885dba8cf78bf9b9daf0c3fa66e0fd34b70 100644 (file)
@@ -1335,6 +1335,24 @@ static int h264_field_start(H264Context *h, const H264SliceContext *sl,
 
     h->picture_idr = nal->type == H264_NAL_IDR_SLICE;
 
+    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);
+    }
+
+    h->cur_pic_ptr->f->key_frame |= (nal->type == H264_NAL_IDR_SLICE) ||
+                                    (h->sei.recovery_point.recovery_frame_cnt >= 0);
+
+    if (nal->type == H264_NAL_IDR_SLICE || h->recovery_frame == h->poc.frame_num) {
+        h->recovery_frame         = -1;
+        h->cur_pic_ptr->recovered = 1;
+    }
+    // If we have an IDR, all frames after it in decoded order are
+    // "recovered".
+    if (nal->type == H264_NAL_IDR_SLICE)
+        h->frame_recovered |= FRAME_RECOVERED_IDR;
+    h->cur_pic_ptr->recovered |= !!(h->frame_recovered & FRAME_RECOVERED_IDR);
+
     /* Set the frame properties/side data. Only done for the second field in
      * field coded frames, since some SEI information is present for each field
      * and is merged by the SEI parsing code. */
@@ -1344,6 +1362,12 @@ static int h264_field_start(H264Context *h, const H264SliceContext *sl,
             return ret;
     }
 
+    if (h->avctx->hwaccel) {
+        ret = h->avctx->hwaccel->start_frame(h->avctx, NULL, 0);
+        if (ret < 0)
+            return ret;
+    }
+
     return 0;
 }
 
@@ -1446,6 +1470,7 @@ static int h264_slice_header_parse(H264SliceContext *sl, const H2645NAL *nal,
             sl->delta_poc[1] = get_se_golomb(&sl->gb);
     }
 
+    sl->redundant_pic_count = 0;
     if (pps->redundant_pic_cnt_present)
         sl->redundant_pic_count = get_ue_golomb(&sl->gb);
 
@@ -1558,6 +1583,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 (!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)) {