From ee05c9bdee0ff6db7f3bc97fca1044f55b505daa Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 12 Jul 2022 11:25:09 +0200 Subject: lavc/amfenc: pass through frame durations to encoded packets --- libavcodec/amfenc.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index a033e1220e..af8d6f1e26 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -68,6 +68,11 @@ typedef struct FormatMap { enum AMF_SURFACE_FORMAT amf_format; } FormatMap; +typedef struct FrameTiming { + int64_t pts; + int64_t duration; +} FrameTiming; + static const FormatMap format_map[] = { { AV_PIX_FMT_NONE, AMF_SURFACE_UNKNOWN }, @@ -119,7 +124,7 @@ static int amf_load_library(AVCodecContext *avctx) return AVERROR(ENOMEM); } // hardcoded to current HW queue size - will auto-realloc if too small - ctx->timestamp_list = av_fifo_alloc2(avctx->max_b_frames + 16, sizeof(int64_t), + ctx->timestamp_list = av_fifo_alloc2(avctx->max_b_frames + 16, sizeof(FrameTiming), AV_FIFO_FLAG_AUTO_GROW); if (!ctx->timestamp_list) { return AVERROR(ENOMEM); @@ -439,8 +444,8 @@ static int amf_copy_buffer(AVCodecContext *avctx, AVPacket *pkt, AMFBuffer *buff AmfContext *ctx = avctx->priv_data; int ret; AMFVariantStruct var = {0}; - int64_t timestamp = AV_NOPTS_VALUE; int64_t size = buffer->pVtbl->GetSize(buffer); + FrameTiming timestamp; if ((ret = ff_get_encode_buffer(avctx, pkt, size, 0)) < 0) { return ret; @@ -474,18 +479,19 @@ static int amf_copy_buffer(AVCodecContext *avctx, AVPacket *pkt, AMFBuffer *buff // calc dts shift if max_b_frames > 0 if (avctx->max_b_frames > 0 && ctx->dts_delay == 0) { - int64_t timestamp_last = AV_NOPTS_VALUE; + FrameTiming timestamp_last; size_t can_read = av_fifo_can_read(ctx->timestamp_list); AMF_RETURN_IF_FALSE(ctx, can_read > 0, AVERROR_UNKNOWN, "timestamp_list is empty while max_b_frames = %d\n", avctx->max_b_frames); av_fifo_peek(ctx->timestamp_list, ×tamp_last, 1, can_read - 1); - if (timestamp < 0 || timestamp_last < AV_NOPTS_VALUE) { + if (timestamp.pts < 0 || timestamp_last.pts < AV_NOPTS_VALUE) { return AVERROR(ERANGE); } - ctx->dts_delay = timestamp_last - timestamp; + ctx->dts_delay = timestamp_last.pts - timestamp.pts; } - pkt->dts = timestamp - ctx->dts_delay; + pkt->dts = timestamp.pts - ctx->dts_delay; + pkt->duration = timestamp.duration; return 0; } @@ -691,12 +697,12 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) //store surface for later submission ctx->delayed_surface = surface; } else { - int64_t pts = frame->pts; + FrameTiming timing = { .pts = frame->pts, duration = frame->duration }; surface->pVtbl->Release(surface); AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "SubmitInput() failed with error %d\n", res); av_frame_unref(frame); - ret = av_fifo_write(ctx->timestamp_list, &pts, 1); + ret = av_fifo_write(ctx->timestamp_list, &timing, 1); if (ret < 0) return ret; } @@ -731,13 +737,13 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) if (ctx->delayed_surface != NULL) { // try to resubmit frame res = ctx->encoder->pVtbl->SubmitInput(ctx->encoder, (AMFData*)ctx->delayed_surface); if (res != AMF_INPUT_FULL) { - int64_t pts = ctx->delayed_surface->pVtbl->GetPts(ctx->delayed_surface); + FrameTiming timing = { .pts = ctx->delayed_surface->pVtbl->GetPts(ctx->delayed_surface) }; ctx->delayed_surface->pVtbl->Release(ctx->delayed_surface); ctx->delayed_surface = NULL; av_frame_unref(ctx->delayed_frame); AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Repeated SubmitInput() failed with error %d\n", res); - ret = av_fifo_write(ctx->timestamp_list, &pts, 1); + ret = av_fifo_write(ctx->timestamp_list, &timing, 1); if (ret < 0) return ret; } else { -- cgit v1.2.3