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

Showing the changes to libavcodec/vaapi_encode.c (1 of 9 files). Show all

Unified · Split

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) {

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