Skip to content

Commit 8503c64

Browse files
cgutmanHotactioncop
authored andcommitted
avcodec/amfenc: add support for QueryOutput wait
Enable waiting in QueryOutput() based on driver support to reduce unnecessary delays. Fix for issue #10622 Co-authored-by: Araz Iusubov <[email protected]>
1 parent eedcf93 commit 8503c64

File tree

5 files changed

+36
-3
lines changed

5 files changed

+36
-3
lines changed

libavcodec/amfenc.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,8 @@ static int amf_init_encoder(AVCodecContext *avctx)
426426
res = ctx->factory->pVtbl->CreateComponent(ctx->factory, ctx->context, codec_id, &ctx->encoder);
427427
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_ENCODER_NOT_FOUND, "CreateComponent(%ls) failed with error %d\n", codec_id, res);
428428

429+
ctx->submitted_frame = 0;
430+
429431
return 0;
430432
}
431433

@@ -541,7 +543,6 @@ static int amf_copy_buffer(AVCodecContext *avctx, AVPacket *pkt, AMFBuffer *buff
541543
if ((ctx->max_b_frames > 0 || ((ctx->pa_adaptive_mini_gop == 1) ? true : false)) && ctx->dts_delay == 0) {
542544
int64_t timestamp_last = AV_NOPTS_VALUE;
543545
size_t can_read = av_fifo_can_read(ctx->timestamp_list);
544-
545546
AMF_RETURN_IF_FALSE(ctx, can_read > 0, AVERROR_UNKNOWN,
546547
"timestamp_list is empty while max_b_frames = %d\n", avctx->max_b_frames);
547548
av_fifo_peek(ctx->timestamp_list, &timestamp_last, 1, can_read - 1);
@@ -826,6 +827,13 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
826827

827828
av_frame_unref(frame);
828829
ret = av_fifo_write(ctx->timestamp_list, &pts, 1);
830+
831+
if (ctx->submitted_frame == 0)
832+
{
833+
ctx->use_b_frame = (ctx->max_b_frames > 0 || ((ctx->pa_adaptive_mini_gop == 1) ? true : false));
834+
}
835+
ctx->submitted_frame++;
836+
829837
if (ret < 0)
830838
return ret;
831839
}
@@ -835,7 +843,7 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
835843
do {
836844
block_and_wait = 0;
837845
// poll data
838-
if (!avpkt->data && !avpkt->buf) {
846+
if (!avpkt->data && !avpkt->buf && (ctx->use_b_frame ? (ctx->submitted_frame >= 2) : true) ) {
839847
res_query = ctx->encoder->pVtbl->QueryOutput(ctx->encoder, &data);
840848
if (data) {
841849
// copy data to packet
@@ -845,6 +853,7 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
845853
data->pVtbl->QueryInterface(data, &guid, (void**)&buffer); // query for buffer interface
846854
ret = amf_copy_buffer(avctx, avpkt, buffer);
847855

856+
ctx->submitted_frame++;
848857
buffer->pVtbl->Release(buffer);
849858

850859
if (data->pVtbl->HasProperty(data, L"av_frame_ref")) {
@@ -884,6 +893,7 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
884893
av_frame_unref(ctx->delayed_frame);
885894
AMF_RETURN_IF_FALSE(ctx, res_resubmit == AMF_OK, AVERROR_UNKNOWN, "Repeated SubmitInput() failed with error %d\n", res_resubmit);
886895

896+
ctx->submitted_frame++;
887897
ret = av_fifo_write(ctx->timestamp_list, &pts, 1);
888898
if (ret < 0)
889899
return ret;
@@ -902,7 +912,12 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
902912
if (query_output_data_flag == 0) {
903913
if (res_resubmit == AMF_INPUT_FULL || ctx->delayed_drain || (ctx->eof && res_query != AMF_EOF) || (ctx->hwsurfaces_in_queue >= ctx->hwsurfaces_in_queue_max)) {
904914
block_and_wait = 1;
905-
av_usleep(1000);
915+
916+
// Only sleep if the driver doesn't support waiting in QueryOutput()
917+
// or if we already have output data so we will skip calling it.
918+
if (!ctx->query_timeout_supported || avpkt->data || avpkt->buf) {
919+
av_usleep(1000);
920+
}
906921
}
907922
}
908923
} while (block_and_wait);

libavcodec/amfenc.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ typedef struct AmfContext {
6868

6969
int hwsurfaces_in_queue;
7070
int hwsurfaces_in_queue_max;
71+
int query_timeout_supported;
7172

7273
// helpers to handle async calls
7374
int delayed_drain;
@@ -77,6 +78,8 @@ typedef struct AmfContext {
7778
// shift dts back by max_b_frames in timing
7879
AVFifo *timestamp_list;
7980
int64_t dts_delay;
81+
int submitted_frame;
82+
amf_bool use_b_frame;
8083

8184
// common encoder option options
8285

libavcodec/amfenc_av1.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,11 @@ FF_ENABLE_DEPRECATION_WARNINGS
463463
}
464464
}
465465

466+
// Wait inside QueryOutput() if supported by the driver
467+
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_QUERY_TIMEOUT, 1);
468+
res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_AV1_QUERY_TIMEOUT, &var);
469+
ctx->query_timeout_supported = res == AMF_OK && var.int64Value;
470+
466471
// init encoder
467472
res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height);
468473
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res);

libavcodec/amfenc_h264.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,11 @@ FF_ENABLE_DEPRECATION_WARNINGS
483483
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_REF_B_PIC_DELTA_QP, ctx->ref_b_frame_delta_qp);
484484
}
485485

486+
// Wait inside QueryOutput() if supported by the driver
487+
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QUERY_TIMEOUT, 1);
488+
res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_QUERY_TIMEOUT, &var);
489+
ctx->query_timeout_supported = res == AMF_OK && var.int64Value;
490+
486491
// Initialize Encoder
487492
res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height);
488493
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res);

libavcodec/amfenc_hevc.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,11 @@ FF_ENABLE_DEPRECATION_WARNINGS
425425
}
426426
}
427427

428+
// Wait inside QueryOutput() if supported by the driver
429+
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QUERY_TIMEOUT, 1);
430+
res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QUERY_TIMEOUT, &var);
431+
ctx->query_timeout_supported = res == AMF_OK && var.int64Value;
432+
428433
// init encoder
429434
res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height);
430435
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res);

0 commit comments

Comments
 (0)