Browse code

vaapi_encode: Support forcing IDR frames via AVFrame.pict_type

(cherry picked from commit a3c3a5eac20a51d402c332cdf5220fff40a7943f)

Mark Thompson authored on 2016/12/13 06:25:28
Showing 2 changed files
... ...
@@ -590,6 +590,10 @@ static int vaapi_encode_step(AVCodecContext *avctx,
590 590
     } else if (ctx->issue_mode == ISSUE_MODE_MAXIMISE_THROUGHPUT) {
591 591
         int activity;
592 592
 
593
+        // Run through the list of all available pictures repeatedly
594
+        // and issue the first one found which has all dependencies
595
+        // available (including previously-issued but not necessarily
596
+        // completed pictures).
593 597
         do {
594 598
             activity = 0;
595 599
             for (pic = ctx->pic_start; pic; pic = pic->next) {
... ...
@@ -605,9 +609,15 @@ static int vaapi_encode_step(AVCodecContext *avctx,
605 605
                 if (err < 0)
606 606
                     return err;
607 607
                 activity = 1;
608
+                // Start again from the beginning of the list,
609
+                // because issuing this picture may have satisfied
610
+                // forward dependencies of earlier ones.
611
+                break;
608 612
             }
609 613
         } while(activity);
610 614
 
615
+        // If we had a defined target for this step then it will
616
+        // always have been issued by now.
611 617
         if (target) {
612 618
             av_assert0(target->encode_issued && "broken dependencies?");
613 619
         }
... ...
@@ -639,8 +649,10 @@ static int vaapi_encode_get_next(AVCodecContext *avctx,
639 639
     if (!pic)
640 640
         return AVERROR(ENOMEM);
641 641
 
642
-    if (ctx->input_order == 0 || ctx->gop_counter >= avctx->gop_size) {
642
+    if (ctx->input_order == 0 || ctx->force_idr ||
643
+        ctx->gop_counter >= avctx->gop_size) {
643 644
         pic->type = PICTURE_TYPE_IDR;
645
+        ctx->force_idr = 0;
644 646
         ctx->gop_counter = 1;
645 647
         ctx->p_counter = 0;
646 648
     } else if (ctx->p_counter >= ctx->p_per_i) {
... ...
@@ -722,7 +734,7 @@ fail:
722 722
     return AVERROR(ENOMEM);
723 723
 }
724 724
 
725
-static int vaapi_encode_mangle_end(AVCodecContext *avctx)
725
+static int vaapi_encode_truncate_gop(AVCodecContext *avctx)
726 726
 {
727 727
     VAAPIEncodeContext *ctx = avctx->priv_data;
728 728
     VAAPIEncodePicture *pic, *last_pic, *next;
... ...
@@ -772,7 +784,7 @@ static int vaapi_encode_mangle_end(AVCodecContext *avctx)
772 772
         // mangle anything.
773 773
     }
774 774
 
775
-    av_log(avctx, AV_LOG_DEBUG, "Pictures at end of stream:");
775
+    av_log(avctx, AV_LOG_DEBUG, "Pictures ending truncated GOP:");
776 776
     for (pic = ctx->pic_start; pic; pic = pic->next) {
777 777
         av_log(avctx, AV_LOG_DEBUG, " %s (%"PRId64"/%"PRId64")",
778 778
                picture_type_name[pic->type],
... ...
@@ -826,6 +838,13 @@ int ff_vaapi_encode2(AVCodecContext *avctx, AVPacket *pkt,
826 826
         av_log(avctx, AV_LOG_DEBUG, "Encode frame: %ux%u (%"PRId64").\n",
827 827
                input_image->width, input_image->height, input_image->pts);
828 828
 
829
+        if (input_image->pict_type == AV_PICTURE_TYPE_I) {
830
+            err = vaapi_encode_truncate_gop(avctx);
831
+            if (err < 0)
832
+                goto fail;
833
+            ctx->force_idr = 1;
834
+        }
835
+
829 836
         err = vaapi_encode_get_next(avctx, &pic);
830 837
         if (err) {
831 838
             av_log(avctx, AV_LOG_ERROR, "Input setup failed: %d.\n", err);
... ...
@@ -854,7 +873,7 @@ int ff_vaapi_encode2(AVCodecContext *avctx, AVPacket *pkt,
854 854
 
855 855
     } else {
856 856
         if (!ctx->end_of_stream) {
857
-            err = vaapi_encode_mangle_end(avctx);
857
+            err = vaapi_encode_truncate_gop(avctx);
858 858
             if (err < 0)
859 859
                 goto fail;
860 860
             ctx->end_of_stream = 1;
... ...
@@ -192,6 +192,7 @@ typedef struct VAAPIEncodeContext {
192 192
     // Frame type decision.
193 193
     int p_per_i;
194 194
     int b_per_p;
195
+    int force_idr;
195 196
     int gop_counter;
196 197
     int p_counter;
197 198
     int end_of_stream;