History

vaapi_encode: Convert to send/receive API

This attaches the logic of picking the mode of for the next picture to the output, which simplifies some choices by removing the concept of the picture for which input is not yet available. At the same time, we allow more complex reference structures and track more reference metadata (particularly the contents of the DPB) for use in the codec-specific code. It also adds flags to explicitly track the available features of the different codecs. The new structure also allows open-GOP support, so that is now available for codecs which can do it.

Mark Thompson committed 7 years ago

Commit 5fdcf851 parent 26ce3a49 files · +433 −331Browse files

Unified · Split

9 files
  1. doc/encoders.texi +14 −5
  2. libavcodec/vaapi_encode.c +334 −301
  3. libavcodec/vaapi_encode.h +59 −15
  4. libavcodec/vaapi_encode_h264.c +5 −2
  5. libavcodec/vaapi_encode_h265.c +5 −2
  6. libavcodec/vaapi_encode_mjpeg.c +6 −3
  7. libavcodec/vaapi_encode_mpeg2.c +4 −1
  8. libavcodec/vaapi_encode_vp8.c +2 −1
  9. libavcodec/vaapi_encode_vp9.c +4 −1
doc/encoders.texi+14−5
@@ -2807,15 +2807,24 @@ Size / quality tradeoff: higher values are smaller / worse quality. · 2806 unmodified lines
28072807 @end itemize
28082808
28092809 All encoders support the following options:
2810−@itemize
2811−@item
2812−@option{low_power}
2813−
2810+@table @option
2811+@item low_power
28142812 Some drivers/platforms offer a second encoder for some codecs intended to use
28152813 less power than the default encoder; setting this option will attempt to use
28162814 that encoder. Note that it may support a reduced feature set, so some other
28172815 options may not be available in this mode.
2818−@end itemize
2816+
2817+@item idr_interval
2818+Set the number of normal intra frames between full-refresh (IDR) frames in
2819+open-GOP mode. The intra frames are still IRAPs, but will not include global
2820+headers and may have non-decodable leading pictures.
2821+
2822+@item b_depth
2823+Set the B-frame reference depth. When set to one (the default), all B-frames
2824+will refer only to P- or I-frames. When set to greater values multiple layers
2825+of B-frames will be present, frames in each layer only referring to frames in
2826+higher layers.
2827+@end table
28192828
28202829 Each encoder also has its own specific options:
28212830 @table @option
libavcodec/vaapi_encode.c+334−301
@@ -158,16 +158,10 @@ static int vaapi_encode_issue(AVCodecContext *avctx, · 157 unmodified lines
158158 av_log(avctx, AV_LOG_DEBUG, ".\n");
159159 }
160160
161− av_assert0(pic->input_available && !pic->encode_issued);
161+ av_assert0(!pic->encode_issued);
162162 for (i = 0; i < pic->nb_refs; i++) {
163163 av_assert0(pic->refs[i]);
164− // If we are serialised then the references must have already
165− // completed. If not, they must have been issued but need not
166− // have completed yet.
167− if (ctx->issue_mode == ISSUE_MODE_SERIALISE_EVERYTHING)
168− av_assert0(pic->refs[i]->encode_complete);
169− else
170− av_assert0(pic->refs[i]->encode_issued);
164+ av_assert0(pic->refs[i]->encode_issued);
171165 }
172166
173167 av_log(avctx, AV_LOG_DEBUG, "Input surface is %#x.\n", pic->input_surface);
@@ -466,10 +460,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, · 292 unmodified lines
466460
467461 pic->encode_issued = 1;
468462
469− if (ctx->issue_mode == ISSUE_MODE_SERIALISE_EVERYTHING)
470− return vaapi_encode_wait(avctx, pic);
471− else
472− return 0;
463+ return 0;
473464
474465 fail_with_picture:
475466 vaEndPicture(ctx->hwctx->display, ctx->va_context);
@@ -626,315 +617,330 @@ static int vaapi_encode_free(AVCodecContext *avctx, · 150 unmodified lines
626617 return 0;
627618 }
628619
629−static int vaapi_encode_step(AVCodecContext *avctx,
630− VAAPIEncodePicture *target)
620+static void vaapi_encode_add_ref(AVCodecContext *avctx,
621+ VAAPIEncodePicture *pic,
622+ VAAPIEncodePicture *target,
623+ int is_ref, int in_dpb, int prev)
631624 {
632− VAAPIEncodeContext *ctx = avctx->priv_data;
633− VAAPIEncodePicture *pic;
634− int i, err;
625+ int refs = 0;
635626
636− if (ctx->issue_mode == ISSUE_MODE_SERIALISE_EVERYTHING ||
637− ctx->issue_mode == ISSUE_MODE_MINIMISE_LATENCY) {
638− // These two modes are equivalent, except that we wait for
639− // immediate completion on each operation if serialised.
640−
641− if (!target) {
642− // No target, nothing to do yet.
643− return 0;
644− }
645−
646− if (target->encode_complete) {
647− // Already done.
648− return 0;
649− }
650−
651− pic = target;
652− for (i = 0; i < pic->nb_refs; i++) {
653− if (!pic->refs[i]->encode_complete) {
654− err = vaapi_encode_step(avctx, pic->refs[i]);
655− if (err < 0)
656− return err;
657− }
658− }
659−
660− err = vaapi_encode_issue(avctx, pic);
661− if (err < 0)
662− return err;
663−
664− } else if (ctx->issue_mode == ISSUE_MODE_MAXIMISE_THROUGHPUT) {
665− int activity;
666−
667− // Run through the list of all available pictures repeatedly
668− // and issue the first one found which has all dependencies
669− // available (including previously-issued but not necessarily
670− // completed pictures).
671− do {
672− activity = 0;
673− for (pic = ctx->pic_start; pic; pic = pic->next) {
674− if (!pic->input_available || pic->encode_issued)
675− continue;
676− for (i = 0; i < pic->nb_refs; i++) {
677− if (!pic->refs[i]->encode_issued)
678− break;
679− }
680− if (i < pic->nb_refs)
681− continue;
682− err = vaapi_encode_issue(avctx, pic);
683− if (err < 0)
684− return err;
685− activity = 1;
686− // Start again from the beginning of the list,
687− // because issuing this picture may have satisfied
688− // forward dependencies of earlier ones.
689− break;
690− }
691− } while(activity);
627+ if (is_ref) {
628+ av_assert0(pic != target);
629+ av_assert0(pic->nb_refs < MAX_PICTURE_REFERENCES);
630+ pic->refs[pic->nb_refs++] = target;
631+ ++refs;
632+ }
692633
693− // If we had a defined target for this step then it will
694− // always have been issued by now.
695− if (target) {
696− av_assert0(target->encode_issued && "broken dependencies?");
697− }
634+ if (in_dpb) {
635+ av_assert0(pic->nb_dpb_pics < MAX_DPB_SIZE);
636+ pic->dpb[pic->nb_dpb_pics++] = target;
637+ ++refs;
638+ }
698639
699− } else {
700− av_assert0(0);
640+ if (prev) {
641+ av_assert0(!pic->prev);
642+ pic->prev = target;
643+ ++refs;
701644 }
702645
703− return 0;
646+ target->ref_count[0] += refs;
647+ target->ref_count[1] += refs;
704648 }
705649
706−static int vaapi_encode_get_next(AVCodecContext *avctx,
707− VAAPIEncodePicture **pic_out)
650+static void vaapi_encode_remove_refs(AVCodecContext *avctx,
651+ VAAPIEncodePicture *pic,
652+ int level)
708653 {
709− VAAPIEncodeContext *ctx = avctx->priv_data;
710− VAAPIEncodePicture *start, *end, *pic;
711654 int i;
712655
713− for (pic = ctx->pic_start; pic; pic = pic->next) {
714− if (pic->next)
715− av_assert0(pic->display_order + 1 == pic->next->display_order);
716− if (pic->display_order == ctx->input_order) {
717− *pic_out = pic;
718− return 0;
719− }
656+ if (pic->ref_removed[level])
657+ return;
658+
659+ for (i = 0; i < pic->nb_refs; i++) {
660+ av_assert0(pic->refs[i]);
661+ --pic->refs[i]->ref_count[level];
662+ av_assert0(pic->refs[i]->ref_count[level] >= 0);
720663 }
721664
722− pic = vaapi_encode_alloc(avctx);
723− if (!pic)
724− return AVERROR(ENOMEM);
665+ for (i = 0; i < pic->nb_dpb_pics; i++) {
666+ av_assert0(pic->dpb[i]);
667+ --pic->dpb[i]->ref_count[level];
668+ av_assert0(pic->dpb[i]->ref_count[level] >= 0);
669+ }
725670
726− if (ctx->input_order == 0 || ctx->force_idr ||
727− ctx->gop_counter >= ctx->gop_size) {
728− pic->type = PICTURE_TYPE_IDR;
729− ctx->force_idr = 0;
730− ctx->gop_counter = 1;
731− ctx->p_counter = 0;
732− } else if (ctx->p_counter >= ctx->p_per_i) {
733− pic->type = PICTURE_TYPE_I;
734− ++ctx->gop_counter;
735− ctx->p_counter = 0;
736− } else {
737− pic->type = PICTURE_TYPE_P;
738− pic->refs[0] = ctx->pic_end;
739− pic->nb_refs = 1;
740− ++ctx->gop_counter;
741− ++ctx->p_counter;
671+ av_assert0(pic->prev || pic->type == PICTURE_TYPE_IDR);
672+ if (pic->prev) {
673+ --pic->prev->ref_count[level];
674+ av_assert0(pic->prev->ref_count[level] >= 0);
742675 }
743− start = end = pic;
744676
745− if (pic->type != PICTURE_TYPE_IDR) {
746− // If that was not an IDR frame, add B-frames display-before and
747− // encode-after it, but not exceeding the GOP size.
677+ pic->ref_removed[level] = 1;
678+}
748679
749− for (i = 0; i < ctx->b_per_p &&
750− ctx->gop_counter < ctx->gop_size; i++) {
751− pic = vaapi_encode_alloc(avctx);
752− if (!pic)
753− goto fail;
680+static void vaapi_encode_set_b_pictures(AVCodecContext *avctx,
681+ VAAPIEncodePicture *start,
682+ VAAPIEncodePicture *end,
683+ VAAPIEncodePicture *prev,
684+ int current_depth,
685+ VAAPIEncodePicture **last)
686+{
687+ VAAPIEncodeContext *ctx = avctx->priv_data;
688+ VAAPIEncodePicture *pic, *next, *ref;
689+ int i, len;
754690
755− pic->type = PICTURE_TYPE_B;
756− pic->refs[0] = ctx->pic_end;
757− pic->refs[1] = end;
758− pic->nb_refs = 2;
691+ av_assert0(start && end && start != end && start->next != end);
759692
760− pic->next = start;
761− pic->display_order = ctx->input_order + ctx->b_per_p - i - 1;
762− pic->encode_order = pic->display_order + 1;
763− start = pic;
693+ // If we are at the maximum depth then encode all pictures as
694+ // non-referenced B-pictures. Also do this if there is exactly one
695+ // picture left, since there will be nothing to reference it.
696+ if (current_depth == ctx->max_b_depth || start->next->next == end) {
697+ for (pic = start->next; pic; pic = pic->next) {
698+ if (pic == end)
699+ break;
700+ pic->type = PICTURE_TYPE_B;
701+ pic->b_depth = current_depth;
702+
703+ vaapi_encode_add_ref(avctx, pic, start, 1, 1, 0);
704+ vaapi_encode_add_ref(avctx, pic, end, 1, 1, 0);
705+ vaapi_encode_add_ref(avctx, pic, prev, 0, 0, 1);
764706
765− ++ctx->gop_counter;
707+ for (ref = end->refs[1]; ref; ref = ref->refs[1])
708+ vaapi_encode_add_ref(avctx, pic, ref, 0, 1, 0);
766709 }
767− }
710+ *last = prev;
768711
769− if (ctx->input_order == 0) {
770− pic->display_order = 0;
771− pic->encode_order = 0;
712+ } else {
713+ // Split the current list at the midpoint with a referenced
714+ // B-picture, then descend into each side separately.
715+ len = 0;
716+ for (pic = start->next; pic != end; pic = pic->next)
717+ ++len;
718+ for (pic = start->next, i = 1; 2 * i < len; pic = pic->next, i++);
772719
773− ctx->pic_start = ctx->pic_end = pic;
720+ pic->type = PICTURE_TYPE_B;
721+ pic->b_depth = current_depth;
774722
775− } else {
776− for (i = 0, pic = start; pic; i++, pic = pic->next) {
777− pic->display_order = ctx->input_order + i;
778− if (end->type == PICTURE_TYPE_IDR)
779− pic->encode_order = ctx->input_order + i;
780− else if (pic == end)
781− pic->encode_order = ctx->input_order;
782− else
783− pic->encode_order = ctx->input_order + i + 1;
784− }
723+ pic->is_reference = 1;
785724
786− av_assert0(ctx->pic_end);
787− ctx->pic_end->next = start;
788− ctx->pic_end = end;
789− }
790− *pic_out = start;
725+ vaapi_encode_add_ref(avctx, pic, pic, 0, 1, 0);
726+ vaapi_encode_add_ref(avctx, pic, start, 1, 1, 0);
727+ vaapi_encode_add_ref(avctx, pic, end, 1, 1, 0);
728+ vaapi_encode_add_ref(avctx, pic, prev, 0, 0, 1);
791729
792− av_log(avctx, AV_LOG_DEBUG, "Pictures:");
793− for (pic = ctx->pic_start; pic; pic = pic->next) {
794− av_log(avctx, AV_LOG_DEBUG, " %s (%"PRId64"/%"PRId64")",
795− picture_type_name[pic->type],
796− pic->display_order, pic->encode_order);
797− }
798− av_log(avctx, AV_LOG_DEBUG, "\n");
730+ for (ref = end->refs[1]; ref; ref = ref->refs[1])
731+ vaapi_encode_add_ref(avctx, pic, ref, 0, 1, 0);
799732
800− return 0;
733+ if (i > 1)
734+ vaapi_encode_set_b_pictures(avctx, start, pic, pic,
735+ current_depth + 1, &next);
736+ else
737+ next = pic;
801738
802−fail:
803− while (start) {
804− pic = start->next;
805− vaapi_encode_free(avctx, start);
806− start = pic;
739+ vaapi_encode_set_b_pictures(avctx, pic, end, next,
740+ current_depth + 1, last);
807741 }
808− return AVERROR(ENOMEM);
809742 }
810743
811−static int vaapi_encode_truncate_gop(AVCodecContext *avctx)
744+static int vaapi_encode_pick_next(AVCodecContext *avctx,
745+ VAAPIEncodePicture **pic_out)
812746 {
813747 VAAPIEncodeContext *ctx = avctx->priv_data;
814− VAAPIEncodePicture *pic, *last_pic, *next;
748+ VAAPIEncodePicture *pic = NULL, *next, *start;
749+ int i, b_counter, closed_gop_end;
815750
816− av_assert0(!ctx->pic_start || ctx->pic_start->input_available);
817−
818− // Find the last picture we actually have input for.
751+ // If there are any B-frames already queued, the next one to encode
752+ // is the earliest not-yet-issued frame for which all references are
753+ // available.
819754 for (pic = ctx->pic_start; pic; pic = pic->next) {
820− if (!pic->input_available)
755+ if (pic->encode_issued)
756+ continue;
757+ if (pic->type != PICTURE_TYPE_B)
758+ continue;
759+ for (i = 0; i < pic->nb_refs; i++) {
760+ if (!pic->refs[i]->encode_issued)
761+ break;
762+ }
763+ if (i == pic->nb_refs)
821764 break;
822− last_pic = pic;
823765 }
824766
825767 if (pic) {
826− if (last_pic->type == PICTURE_TYPE_B) {
827− // Some fixing up is required. Change the type of this
828− // picture to P, then modify preceding B references which
829− // point beyond it to point at it instead.
830−
831− last_pic->type = PICTURE_TYPE_P;
832− last_pic->encode_order = last_pic->refs[1]->encode_order;
833−
834− for (pic = ctx->pic_start; pic != last_pic; pic = pic->next) {
835− if (pic->type == PICTURE_TYPE_B &&
836− pic->refs[1] == last_pic->refs[1])
837− pic->refs[1] = last_pic;
838− }
768+ av_log(avctx, AV_LOG_DEBUG, "Pick B-picture at depth %d to "
769+ "encode next.\n", pic->b_depth);
770+ *pic_out = pic;
771+ return 0;
772+ }
839773
840− last_pic->nb_refs = 1;
841− last_pic->refs[1] = NULL;
842− } else {
843− // We can use the current structure (no references point
844− // beyond the end), but there are unused pics to discard.
774+ // Find the B-per-Pth available picture to become the next picture
775+ // on the top layer.
776+ start = NULL;
777+ b_counter = 0;
778+ closed_gop_end = ctx->closed_gop ||
779+ ctx->idr_counter == ctx->gop_per_idr;
780+ for (pic = ctx->pic_start; pic; pic = next) {
781+ next = pic->next;
782+ if (pic->encode_issued) {
783+ start = pic;
784+ continue;
845785 }
786+ // If the next available picture is force-IDR, encode it to start
787+ // a new GOP immediately.
788+ if (pic->force_idr)
789+ break;
790+ if (b_counter == ctx->b_per_p)
791+ break;
792+ // If this picture ends a closed GOP or starts a new GOP then it
793+ // needs to be in the top layer.
794+ if (ctx->gop_counter + b_counter + closed_gop_end >= ctx->gop_size)
795+ break;
796+ // If the picture after this one is force-IDR, we need to encode
797+ // this one in the top layer.
798+ if (next && next->force_idr)
799+ break;
800+ ++b_counter;
801+ }
846802
847− // Discard all following pics, they will never be used.
848− for (pic = last_pic->next; pic; pic = next) {
849− next = pic->next;
850− vaapi_encode_free(avctx, pic);
851− }
803+ // At the end of the stream the last picture must be in the top layer.
804+ if (!pic && ctx->end_of_stream) {
805+ --b_counter;
806+ pic = ctx->pic_end;
807+ if (pic->encode_issued)
808+ return AVERROR_EOF;
809+ }
852810
853− last_pic->next = NULL;
854− ctx->pic_end = last_pic;
811+ if (!pic) {
812+ av_log(avctx, AV_LOG_DEBUG, "Pick nothing to encode next - "
813+ "need more input for reference pictures.\n");
814+ return AVERROR(EAGAIN);
815+ }
816+ if (ctx->input_order <= ctx->decode_delay && !ctx->end_of_stream) {
817+ av_log(avctx, AV_LOG_DEBUG, "Pick nothing to encode next - "
818+ "need more input for timestamps.\n");
819+ return AVERROR(EAGAIN);
820+ }
821+
822+ if (pic->force_idr) {
823+ av_log(avctx, AV_LOG_DEBUG, "Pick forced IDR-picture to "
824+ "encode next.\n");
825+ pic->type = PICTURE_TYPE_IDR;
826+ ctx->idr_counter = 1;
827+ ctx->gop_counter = 1;
828+
829+ } else if (ctx->gop_counter + b_counter >= ctx->gop_size) {
830+ if (ctx->idr_counter == ctx->gop_per_idr) {
831+ av_log(avctx, AV_LOG_DEBUG, "Pick new-GOP IDR-picture to "
832+ "encode next.\n");
833+ pic->type = PICTURE_TYPE_IDR;
834+ ctx->idr_counter = 1;
835+ } else {
836+ av_log(avctx, AV_LOG_DEBUG, "Pick new-GOP I-picture to "
837+ "encode next.\n");
838+ pic->type = PICTURE_TYPE_I;
839+ ++ctx->idr_counter;
840+ }
841+ ctx->gop_counter = 1;
855842
856843 } else {
857− // Input is available for all pictures, so we don't need to
858− // mangle anything.
844+ if (ctx->gop_counter + b_counter + closed_gop_end == ctx->gop_size) {
845+ av_log(avctx, AV_LOG_DEBUG, "Pick group-end P-picture to "
846+ "encode next.\n");
847+ } else {
848+ av_log(avctx, AV_LOG_DEBUG, "Pick normal P-picture to "
849+ "encode next.\n");
850+ }
851+ pic->type = PICTURE_TYPE_P;
852+ av_assert0(start);
853+ ctx->gop_counter += 1 + b_counter;
859854 }
855+ pic->is_reference = 1;
856+ *pic_out = pic;
860857
861− av_log(avctx, AV_LOG_DEBUG, "Pictures ending truncated GOP:");
862− for (pic = ctx->pic_start; pic; pic = pic->next) {
863− av_log(avctx, AV_LOG_DEBUG, " %s (%"PRId64"/%"PRId64")",
864− picture_type_name[pic->type],
865− pic->display_order, pic->encode_order);
858+ vaapi_encode_add_ref(avctx, pic, pic, 0, 1, 0);
859+ if (pic->type != PICTURE_TYPE_IDR) {
860+ vaapi_encode_add_ref(avctx, pic, start,
861+ pic->type == PICTURE_TYPE_P,
862+ b_counter > 0, 0);
863+ vaapi_encode_add_ref(avctx, pic, ctx->next_prev, 0, 0, 1);
866864 }
867− av_log(avctx, AV_LOG_DEBUG, "\n");
865+ if (ctx->next_prev)
866+ --ctx->next_prev->ref_count[0];
868867
868+ if (b_counter > 0) {
869+ vaapi_encode_set_b_pictures(avctx, start, pic, pic, 1,
870+ &ctx->next_prev);
871+ } else {
872+ ctx->next_prev = pic;
873+ }
874+ ++ctx->next_prev->ref_count[0];
869875 return 0;
870876 }
871877
872878 static int vaapi_encode_clear_old(AVCodecContext *avctx)
873879 {
874880 VAAPIEncodeContext *ctx = avctx->priv_data;
875− VAAPIEncodePicture *pic, *old;
876− int i;
881+ VAAPIEncodePicture *pic, *prev, *next;
877882
878− while (ctx->pic_start != ctx->pic_end) {
879− old = ctx->pic_start;
880− if (old->encode_order > ctx->output_order)
881− break;
883+ av_assert0(ctx->pic_start);
882884
883− for (pic = old->next; pic; pic = pic->next) {
884− if (pic->encode_complete)
885− continue;
886− for (i = 0; i < pic->nb_refs; i++) {
887− if (pic->refs[i] == old) {
888− // We still need this picture because it's referred to
889− // directly by a later one, so it and all following
890− // pictures have to stay.
891− return 0;
892− }
893− }
894− }
885+ // Remove direct references once each picture is complete.
886+ for (pic = ctx->pic_start; pic; pic = pic->next) {
887+ if (pic->encode_complete && pic->next)
888+ vaapi_encode_remove_refs(avctx, pic, 0);
889+ }
895890
896− pic = ctx->pic_start;
897− ctx->pic_start = pic->next;
898− vaapi_encode_free(avctx, pic);
891+ // Remove indirect references once a picture has no direct references.
892+ for (pic = ctx->pic_start; pic; pic = pic->next) {
893+ if (pic->encode_complete && pic->ref_count[0] == 0)
894+ vaapi_encode_remove_refs(avctx, pic, 1);
895+ }
896+
897+ // Clear out all complete pictures with no remaining references.
898+ prev = NULL;
899+ for (pic = ctx->pic_start; pic; pic = next) {
900+ next = pic->next;
901+ if (pic->encode_complete && pic->ref_count[1] == 0) {
902+ av_assert0(pic->ref_removed[0] && pic->ref_removed[1]);
903+ if (prev)
904+ prev->next = next;
905+ else
906+ ctx->pic_start = next;
907+ vaapi_encode_free(avctx, pic);
908+ } else {
909+ prev = pic;
910+ }
899911 }
900912
901913 return 0;
902914 }
903915
904−int ff_vaapi_encode2(AVCodecContext *avctx, AVPacket *pkt,
905− const AVFrame *input_image, int *got_packet)
916+int ff_vaapi_encode_send_frame(AVCodecContext *avctx, const AVFrame *frame)
906917 {
907918 VAAPIEncodeContext *ctx = avctx->priv_data;
908919 VAAPIEncodePicture *pic;
909920 int err;
910921
911− if (input_image) {
912− av_log(avctx, AV_LOG_DEBUG, "Encode frame: %ux%u (%"PRId64").\n",
913− input_image->width, input_image->height, input_image->pts);
922+ if (frame) {
923+ av_log(avctx, AV_LOG_DEBUG, "Input frame: %ux%u (%"PRId64").\n",
924+ frame->width, frame->height, frame->pts);
914925
915− if (input_image->pict_type == AV_PICTURE_TYPE_I) {
916− err = vaapi_encode_truncate_gop(avctx);
917− if (err < 0)
918− goto fail;
919− ctx->force_idr = 1;
920− }
921−
922− err = vaapi_encode_get_next(avctx, &pic);
923− if (err) {
924− av_log(avctx, AV_LOG_ERROR, "Input setup failed: %d.\n", err);
925− return err;
926− }
926+ pic = vaapi_encode_alloc(avctx);
927+ if (!pic)
928+ return AVERROR(ENOMEM);
927929
928930 pic->input_image = av_frame_alloc();
929931 if (!pic->input_image) {
930932 err = AVERROR(ENOMEM);
931933 goto fail;
932934 }
933− err = av_frame_ref(pic->input_image, input_image);
935+ err = av_frame_ref(pic->input_image, frame);
934936 if (err < 0)
935937 goto fail;
936− pic->input_surface = (VASurfaceID)(uintptr_t)input_image->data[3];
937− pic->pts = input_image->pts;
938+
939+ if (ctx->input_order == 0)
940+ pic->force_idr = 1;
941+
942+ pic->input_surface = (VASurfaceID)(uintptr_t)frame->data[3];
943+ pic->pts = frame->pts;
938944
939945 if (ctx->input_order == 0)
940946 ctx->first_pts = pic->pts;
@@ -943,72 +949,89 @@ int ff_vaapi_encode2(AVCodecContext *avctx, AVPacket *pkt, · 2 unmodified lines
943949 if (ctx->output_delay > 0)
944950 ctx->ts_ring[ctx->input_order % (3 * ctx->output_delay)] = pic->pts;
945951
946− pic->input_available = 1;
952+ pic->display_order = ctx->input_order;
953+ ++ctx->input_order;
947954
948− } else {
949− if (!ctx->end_of_stream) {
950− err = vaapi_encode_truncate_gop(avctx);
951− if (err < 0)
952− goto fail;
953− ctx->end_of_stream = 1;
955+ if (ctx->pic_start) {
956+ ctx->pic_end->next = pic;
957+ ctx->pic_end = pic;
958+ } else {
959+ ctx->pic_start = pic;
960+ ctx->pic_end = pic;
954961 }
962+
963+ } else {
964+ ctx->end_of_stream = 1;
965+
966+ // Fix timestamps if we hit end-of-stream before the initial decode
967+ // delay has elapsed.
968+ if (ctx->input_order < ctx->decode_delay)
969+ ctx->dts_pts_diff = ctx->pic_end->pts - ctx->first_pts;
955970 }
956971
957− ++ctx->input_order;
958− ++ctx->output_order;
959− av_assert0(ctx->output_order + ctx->output_delay + 1 == ctx->input_order);
972+ return 0;
960973
961− for (pic = ctx->pic_start; pic; pic = pic->next)
962− if (pic->encode_order == ctx->output_order)
963− break;
974+fail:
975+ return err;
976+}
964977
965− // pic can be null here if we don't have a specific target in this
966− // iteration. We might still issue encodes if things can be overlapped,
967− // even though we don't intend to output anything.
978+int ff_vaapi_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
979+{
980+ VAAPIEncodeContext *ctx = avctx->priv_data;
981+ VAAPIEncodePicture *pic;
982+ int err;
968983
969− err = vaapi_encode_step(avctx, pic);
970− if (err < 0) {
971− av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err);
972− goto fail;
984+ if (!ctx->pic_start) {
985+ if (ctx->end_of_stream)
986+ return AVERROR_EOF;
987+ else
988+ return AVERROR(EAGAIN);
973989 }
974990
975− if (!pic) {
976− *got_packet = 0;
977− } else {
978− err = vaapi_encode_output(avctx, pic, pkt);
979− if (err < 0) {
980− av_log(avctx, AV_LOG_ERROR, "Output failed: %d.\n", err);
981− goto fail;
982− }
991+ pic = NULL;
992+ err = vaapi_encode_pick_next(avctx, &pic);
993+ if (err < 0)
994+ return err;
995+ av_assert0(pic);
983996
984− if (ctx->output_delay == 0) {
985− pkt->dts = pkt->pts;
986− } else if (ctx->output_order < ctx->decode_delay) {
987− if (ctx->ts_ring[ctx->output_order] < INT64_MIN + ctx->dts_pts_diff)
988− pkt->dts = INT64_MIN;
989− else
990− pkt->dts = ctx->ts_ring[ctx->output_order] - ctx->dts_pts_diff;
991− } else {
992− pkt->dts = ctx->ts_ring[(ctx->output_order - ctx->decode_delay) %
993− (3 * ctx->output_delay)];
994− }
997+ pic->encode_order = ctx->encode_order++;
995998
996− *got_packet = 1;
999+ err = vaapi_encode_issue(avctx, pic);
1000+ if (err < 0) {
1001+ av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err);
1002+ return err;
9971003 }
9981004
999− err = vaapi_encode_clear_old(avctx);
1005+ err = vaapi_encode_output(avctx, pic, pkt);
10001006 if (err < 0) {
1001− av_log(avctx, AV_LOG_ERROR, "List clearing failed: %d.\n", err);
1002− goto fail;
1007+ av_log(avctx, AV_LOG_ERROR, "Output failed: %d.\n", err);
1008+ return err;
10031009 }
10041010
1011+ if (ctx->output_delay == 0) {
1012+ pkt->dts = pkt->pts;
1013+ } else if (pic->encode_order < ctx->decode_delay) {
1014+ if (ctx->ts_ring[pic->encode_order] < INT64_MIN + ctx->dts_pts_diff)
1015+ pkt->dts = INT64_MIN;
1016+ else
1017+ pkt->dts = ctx->ts_ring[pic->encode_order] - ctx->dts_pts_diff;
1018+ } else {
1019+ pkt->dts = ctx->ts_ring[(pic->encode_order - ctx->decode_delay) %
1020+ (3 * ctx->output_delay)];
1021+ }
1022+ av_log(avctx, AV_LOG_DEBUG, "Output packet: pts %"PRId64" dts %"PRId64".\n",
1023+ pkt->pts, pkt->dts);
1024+
1025+ ctx->output_order = pic->encode_order;
1026+ vaapi_encode_clear_old(avctx);
1027+
10051028 return 0;
1029+}
10061030
1007−fail:
1008− // Unclear what to clean up on failure. There are probably some things we
1009− // could do usefully clean up here, but for now just leave them for uninit()
1010− // to do instead.
1011− return err;
1031+int ff_vaapi_encode2(AVCodecContext *avctx, AVPacket *pkt,
1032+ const AVFrame *input_image, int *got_packet)
1033+{
1034+ return AVERROR(ENOSYS);
10121035 }
10131036
10141037 static av_cold void vaapi_encode_add_global_param(AVCodecContext *avctx,
@@ -1475,14 +1498,16 @@ static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx) · 460 unmodified lines
14751498 ref_l1 = attr.value >> 16 & 0xffff;
14761499 }
14771500
1478− if (avctx->gop_size <= 1) {
1501+ if (ctx->codec->flags & FLAG_INTRA_ONLY ||
1502+ avctx->gop_size <= 1) {
14791503 av_log(avctx, AV_LOG_VERBOSE, "Using intra frames only.\n");
14801504 ctx->gop_size = 1;
14811505 } else if (ref_l0 < 1) {
14821506 av_log(avctx, AV_LOG_ERROR, "Driver does not support any "
14831507 "reference frames.\n");
14841508 return AVERROR(EINVAL);
1485− } else if (ref_l1 < 1 || avctx->max_b_frames < 1) {
1509+ } else if (!(ctx->codec->flags & FLAG_B_PICTURES) ||
1510+ ref_l1 < 1 || avctx->max_b_frames < 1) {
14861511 av_log(avctx, AV_LOG_VERBOSE, "Using intra and P-frames "
14871512 "(supported references: %d / %d).\n", ref_l0, ref_l1);
14881513 ctx->gop_size = avctx->gop_size;
@@ -1494,6 +1519,20 @@ static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx) · 5 unmodified lines
14941519 ctx->gop_size = avctx->gop_size;
14951520 ctx->p_per_i = INT_MAX;
14961521 ctx->b_per_p = avctx->max_b_frames;
1522+ if (ctx->codec->flags & FLAG_B_PICTURE_REFERENCES) {
1523+ ctx->max_b_depth = FFMIN(ctx->desired_b_depth,
1524+ av_log2(ctx->b_per_p) + 1);
1525+ } else {
1526+ ctx->max_b_depth = 1;
1527+ }
1528+ }
1529+
1530+ if (ctx->codec->flags & FLAG_NON_IDR_KEY_PICTURES) {
1531+ ctx->closed_gop = !!(avctx->flags & AV_CODEC_FLAG_CLOSED_GOP);
1532+ ctx->gop_per_idr = ctx->idr_interval + 1;
1533+ } else {
1534+ ctx->closed_gop = 1;
1535+ ctx->gop_per_idr = 1;
14971536 }
14981537
14991538 return 0;
@@ -1946,10 +1985,8 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) · 446 unmodified lines
19461985 goto fail;
19471986 }
19481987
1949− ctx->input_order = 0;
19501988 ctx->output_delay = ctx->b_per_p;
1951− ctx->decode_delay = 1;
1952− ctx->output_order = - ctx->output_delay - 1;
1989+ ctx->decode_delay = ctx->max_b_depth;
19531990
19541991 if (ctx->codec->sequence_params_size > 0) {
19551992 ctx->codec_sequence_params =
@@ -1977,10 +2014,6 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) · 21 unmodified lines
19772014 }
19782015 }
19792016
1980− // This should be configurable somehow. (Needs testing on a machine
1981− // where it actually overlaps properly, though.)
1982− ctx->issue_mode = ISSUE_MODE_MAXIMISE_THROUGHPUT;
1983−
19842017 if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE &&
19852018 ctx->codec->write_sequence_header &&
19862019 avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
libavcodec/vaapi_encode.h+59−15
@@ -38,6 +38,7 @@ struct VAAPIEncodePicture; · 37 unmodified lines
3838 enum {
3939 MAX_CONFIG_ATTRIBUTES = 4,
4040 MAX_GLOBAL_PARAMS = 4,
41+ MAX_DPB_SIZE = 16,
4142 MAX_PICTURE_REFERENCES = 2,
4243 MAX_REORDER_DELAY = 16,
4344 MAX_PARAM_BUFFER_SIZE = 1024,
@@ -66,9 +67,10 @@ typedef struct VAAPIEncodePicture { · 22 unmodified lines
6667 int64_t display_order;
6768 int64_t encode_order;
6869 int64_t pts;
70+ int force_idr;
6971
7072 int type;
71− int input_available;
73+ int b_depth;
7274 int encode_issued;
7375 int encode_complete;
7476
@@ -87,8 +89,26 @@ typedef struct VAAPIEncodePicture { · 12 unmodified lines
8789 void *priv_data;
8890 void *codec_picture_params;
8991
90− int nb_refs;
92+ // Whether this picture is a reference picture.
93+ int is_reference;
94+
95+ // The contents of the DPB after this picture has been decoded.
96+ // This will contain the picture itself if it is a reference picture,
97+ // but not if it isn't.
98+ int nb_dpb_pics;
99+ struct VAAPIEncodePicture *dpb[MAX_DPB_SIZE];
100+ // The reference pictures used in decoding this picture. If they are
101+ // used by later pictures they will also appear in the DPB.
102+ int nb_refs;
91103 struct VAAPIEncodePicture *refs[MAX_PICTURE_REFERENCES];
104+ // The previous reference picture in encode order. Must be in at least
105+ // one of the reference list and DPB list.
106+ struct VAAPIEncodePicture *prev;
107+ // Reference count for other pictures referring to this one through
108+ // the above pointers, directly from incomplete pictures and indirectly
109+ // through completed pictures.
110+ int ref_count[2];
111+ int ref_removed[2];
92112
93113 int nb_slices;
94114 VAAPIEncodeSlice *slices;
@@ -120,6 +140,12 @@ typedef struct VAAPIEncodeContext { · 25 unmodified lines
120140 // Use low power encoding mode.
121141 int low_power;
122142
143+ // Number of I frames between IDR frames.
144+ int idr_interval;
145+
146+ // Desired B frame reference depth.
147+ int desired_b_depth;
148+
123149 // Desired packed headers.
124150 unsigned int desired_packed_headers;
125151
@@ -207,26 +233,21 @@ typedef struct VAAPIEncodeContext { · 81 unmodified lines
207233
208234 // Current encoding window, in display (input) order.
209235 VAAPIEncodePicture *pic_start, *pic_end;
236+ // The next picture to use as the previous reference picture in
237+ // encoding order.
238+ VAAPIEncodePicture *next_prev;
210239
211240 // Next input order index (display order).
212241 int64_t input_order;
213242 // Number of frames that output is behind input.
214243 int64_t output_delay;
244+ // Next encode order index.
245+ int64_t encode_order;
215246 // Number of frames decode output will need to be delayed.
216247 int64_t decode_delay;
217− // Next output order index (encode order).
248+ // Next output order index (in encode order).
218249 int64_t output_order;
219250
220− enum {
221− // All encode operations are done independently (synchronise
222− // immediately after every operation).
223− ISSUE_MODE_SERIALISE_EVERYTHING = 0,
224− // Overlap as many operations as possible.
225− ISSUE_MODE_MAXIMISE_THROUGHPUT,
226− // Overlap operations only when satisfying parallel dependencies.
227− ISSUE_MODE_MINIMISE_LATENCY,
228− } issue_mode;
229−
230251 // Timestamp handling.
231252 int64_t first_pts;
232253 int64_t dts_pts_diff;
@@ -240,11 +261,14 @@ typedef struct VAAPIEncodeContext { · 7 unmodified lines
240261
241262 // Frame type decision.
242263 int gop_size;
264+ int closed_gop;
265+ int gop_per_idr;
243266 int p_per_i;
267+ int max_b_depth;
244268 int b_per_p;
245269 int force_idr;
270+ int idr_counter;
246271 int gop_counter;
247− int p_counter;
248272 int end_of_stream;
249273 } VAAPIEncodeContext;
250274
@@ -253,6 +277,15 @@ enum { · 2 unmodified lines
253277 FLAG_SLICE_CONTROL = 1 << 0,
254278 // Codec only supports constant quality (no rate control).
255279 FLAG_CONSTANT_QUALITY_ONLY = 1 << 1,
280+ // Codec is intra-only.
281+ FLAG_INTRA_ONLY = 1 << 2,
282+ // Codec supports B-pictures.
283+ FLAG_B_PICTURES = 1 << 3,
284+ // Codec supports referencing B-pictures.
285+ FLAG_B_PICTURE_REFERENCES = 1 << 4,
286+ // Codec supports non-IDR key pictures (that is, key pictures do
287+ // not necessarily empty the DPB).
288+ FLAG_NON_IDR_KEY_PICTURES = 1 << 5,
256289 };
257290
258291 typedef struct VAAPIEncodeType {
@@ -327,6 +360,9 @@ typedef struct VAAPIEncodeType { · 68 unmodified lines
327360 int ff_vaapi_encode2(AVCodecContext *avctx, AVPacket *pkt,
328361 const AVFrame *input_image, int *got_packet);
329362
363+int ff_vaapi_encode_send_frame(AVCodecContext *avctx, const AVFrame *frame);
364+int ff_vaapi_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt);
365+
330366 int ff_vaapi_encode_init(AVCodecContext *avctx);
331367 int ff_vaapi_encode_close(AVCodecContext *avctx);
332368
@@ -336,7 +372,15 @@ int ff_vaapi_encode_close(AVCodecContext *avctx); · 3 unmodified lines
336372 "Use low-power encoding mode (only available on some platforms; " \
337373 "may not support all encoding features)", \
338374 OFFSET(common.low_power), AV_OPT_TYPE_BOOL, \
339− { .i64 = 0 }, 0, 1, FLAGS }
375+ { .i64 = 0 }, 0, 1, FLAGS }, \
376+ { "idr_interval", \
377+ "Distance (in I-frames) between IDR frames", \
378+ OFFSET(common.idr_interval), AV_OPT_TYPE_INT, \
379+ { .i64 = 0 }, 0, INT_MAX, FLAGS }, \
380+ { "b_depth", \
381+ "Maximum B-frame reference depth", \
382+ OFFSET(common.desired_b_depth), AV_OPT_TYPE_INT, \
383+ { .i64 = 1 }, 1, INT_MAX, FLAGS }
340384
341385
342386 #endif /* AVCODEC_VAAPI_ENCODE_H */
libavcodec/vaapi_encode_h264.c+5−2
@@ -902,7 +902,9 @@ static const VAAPIEncodeProfile vaapi_encode_h264_profiles[] = { · 901 unmodified lines
902902 static const VAAPIEncodeType vaapi_encode_type_h264 = {
903903 .profiles = vaapi_encode_h264_profiles,
904904
905− .flags = FLAG_SLICE_CONTROL,
905+ .flags = FLAG_SLICE_CONTROL |
906+ FLAG_B_PICTURES |
907+ FLAG_NON_IDR_KEY_PICTURES,
906908
907909 .configure = &vaapi_encode_h264_configure,
908910
@@ -1095,7 +1097,8 @@ AVCodec ff_h264_vaapi_encoder = { · 186 unmodified lines
10951097 .id = AV_CODEC_ID_H264,
10961098 .priv_data_size = sizeof(VAAPIEncodeH264Context),
10971099 .init = &vaapi_encode_h264_init,
1098− .encode2 = &ff_vaapi_encode2,
1100+ .send_frame = &ff_vaapi_encode_send_frame,
1101+ .receive_packet = &ff_vaapi_encode_receive_packet,
10991102 .close = &vaapi_encode_h264_close,
11001103 .priv_class = &vaapi_encode_h264_class,
11011104 .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE,
libavcodec/vaapi_encode_h265.c+5−2
@@ -1082,7 +1082,9 @@ static const VAAPIEncodeProfile vaapi_encode_h265_profiles[] = { · 1081 unmodified lines
10821082 static const VAAPIEncodeType vaapi_encode_type_h265 = {
10831083 .profiles = vaapi_encode_h265_profiles,
10841084
1085− .flags = FLAG_SLICE_CONTROL,
1085+ .flags = FLAG_SLICE_CONTROL |
1086+ FLAG_B_PICTURES |
1087+ FLAG_NON_IDR_KEY_PICTURES,
10861088
10871089 .configure = &vaapi_encode_h265_configure,
10881090
@@ -1237,7 +1239,8 @@ AVCodec ff_hevc_vaapi_encoder = { · 148 unmodified lines
12371239 .id = AV_CODEC_ID_HEVC,
12381240 .priv_data_size = sizeof(VAAPIEncodeH265Context),
12391241 .init = &vaapi_encode_h265_init,
1240− .encode2 = &ff_vaapi_encode2,
1242+ .send_frame = &ff_vaapi_encode_send_frame,
1243+ .receive_packet = &ff_vaapi_encode_receive_packet,
12411244 .close = &vaapi_encode_h265_close,
12421245 .priv_class = &vaapi_encode_h265_class,
12431246 .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE,
libavcodec/vaapi_encode_mjpeg.c+6−3
@@ -230,6 +230,8 @@ static int vaapi_encode_mjpeg_init_picture_params(AVCodecContext *avctx, · 229 unmodified lines
230230 const uint8_t *components;
231231 int t, i, quant_scale, len;
232232
233+ av_assert0(pic->type == PICTURE_TYPE_IDR);
234+
233235 desc = av_pix_fmt_desc_get(priv->common.input_frames->sw_format);
234236 av_assert0(desc);
235237 if (desc->flags & AV_PIX_FMT_FLAG_RGB)
@@ -476,7 +478,8 @@ static const VAAPIEncodeProfile vaapi_encode_mjpeg_profiles[] = { · 240 unmodified lines
476478 static const VAAPIEncodeType vaapi_encode_type_mjpeg = {
477479 .profiles = vaapi_encode_mjpeg_profiles,
478480
479− .flags = FLAG_CONSTANT_QUALITY_ONLY,
481+ .flags = FLAG_CONSTANT_QUALITY_ONLY |
482+ FLAG_INTRA_ONLY,
480483
481484 .configure = &vaapi_encode_mjpeg_configure,
482485
@@ -535,7 +538,6 @@ static const AVOption vaapi_encode_mjpeg_options[] = { · 52 unmodified lines
535538 static const AVCodecDefault vaapi_encode_mjpeg_defaults[] = {
536539 { "global_quality", "80" },
537540 { "b", "0" },
538− { "g", "1" },
539541 { NULL },
540542 };
541543
@@ -553,7 +555,8 @@ AVCodec ff_mjpeg_vaapi_encoder = { · 11 unmodified lines
553555 .id = AV_CODEC_ID_MJPEG,
554556 .priv_data_size = sizeof(VAAPIEncodeMJPEGContext),
555557 .init = &vaapi_encode_mjpeg_init,
556− .encode2 = &ff_vaapi_encode2,
558+ .send_frame = &ff_vaapi_encode_send_frame,
559+ .receive_packet = &ff_vaapi_encode_receive_packet,
557560 .close = &vaapi_encode_mjpeg_close,
558561 .priv_class = &vaapi_encode_mjpeg_class,
559562 .capabilities = AV_CODEC_CAP_HARDWARE |
libavcodec/vaapi_encode_mpeg2.c+4−1
@@ -563,6 +563,8 @@ static const VAAPIEncodeProfile vaapi_encode_mpeg2_profiles[] = { · 562 unmodified lines
563563 static const VAAPIEncodeType vaapi_encode_type_mpeg2 = {
564564 .profiles = vaapi_encode_mpeg2_profiles,
565565
566+ .flags = FLAG_B_PICTURES,
567+
566568 .configure = &vaapi_encode_mpeg2_configure,
567569
568570 .sequence_params_size = sizeof(VAEncSequenceParameterBufferMPEG2),
@@ -689,7 +691,8 @@ AVCodec ff_mpeg2_vaapi_encoder = { · 120 unmodified lines
689691 .id = AV_CODEC_ID_MPEG2VIDEO,
690692 .priv_data_size = sizeof(VAAPIEncodeMPEG2Context),
691693 .init = &vaapi_encode_mpeg2_init,
692− .encode2 = &ff_vaapi_encode2,
694+ .send_frame = &ff_vaapi_encode_send_frame,
695+ .receive_packet = &ff_vaapi_encode_receive_packet,
693696 .close = &vaapi_encode_mpeg2_close,
694697 .priv_class = &vaapi_encode_mpeg2_class,
695698 .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE,
libavcodec/vaapi_encode_vp8.c+2−1
@@ -246,7 +246,8 @@ AVCodec ff_vp8_vaapi_encoder = { · 245 unmodified lines
246246 .id = AV_CODEC_ID_VP8,
247247 .priv_data_size = sizeof(VAAPIEncodeVP8Context),
248248 .init = &vaapi_encode_vp8_init,
249− .encode2 = &ff_vaapi_encode2,
249+ .send_frame = &ff_vaapi_encode_send_frame,
250+ .receive_packet = &ff_vaapi_encode_receive_packet,
250251 .close = &ff_vaapi_encode_close,
251252 .priv_class = &vaapi_encode_vp8_class,
252253 .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE,
libavcodec/vaapi_encode_vp9.c+4−1
@@ -213,6 +213,8 @@ static const VAAPIEncodeProfile vaapi_encode_vp9_profiles[] = { · 212 unmodified lines
213213 static const VAAPIEncodeType vaapi_encode_type_vp9 = {
214214 .profiles = vaapi_encode_vp9_profiles,
215215
216+ .flags = FLAG_B_PICTURES,
217+
216218 .configure = &vaapi_encode_vp9_configure,
217219
218220 .sequence_params_size = sizeof(VAEncSequenceParameterBufferVP9),
@@ -275,7 +277,8 @@ AVCodec ff_vp9_vaapi_encoder = { · 56 unmodified lines
275277 .id = AV_CODEC_ID_VP9,
276278 .priv_data_size = sizeof(VAAPIEncodeVP9Context),
277279 .init = &vaapi_encode_vp9_init,
278− .encode2 = &ff_vaapi_encode2,
280+ .send_frame = &ff_vaapi_encode_send_frame,
281+ .receive_packet = &ff_vaapi_encode_receive_packet,
279282 .close = &ff_vaapi_encode_close,
280283 .priv_class = &vaapi_encode_vp9_class,
281284 .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE,

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t