1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-23 12:43:46 +02:00

Revert "lavc/nvenc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE"

The implementation is flawed in that the frame opaque data is not in
fact correctly reordered along with the packets, but is being output in
packet input order, just like the dts are.

This reverts commit 3553809703.
This commit is contained in:
Timo Rothenpieler 2023-06-16 20:23:26 +02:00
parent 73a2252f1d
commit 6c418ae25e
5 changed files with 23 additions and 104 deletions

View File

@ -28,7 +28,6 @@
#include "av1.h"
#endif
#include "libavutil/buffer.h"
#include "libavutil/hwcontext_cuda.h"
#include "libavutil/hwcontext.h"
#include "libavutil/cuda_check.h"
@ -168,27 +167,6 @@ static int nvenc_print_error(AVCodecContext *avctx, NVENCSTATUS err,
return ret;
}
typedef struct FrameData {
int64_t pts;
int64_t duration;
#if FF_API_REORDERED_OPAQUE
int64_t reordered_opaque;
#endif
void *frame_opaque;
AVBufferRef *frame_opaque_ref;
} FrameData;
static void reorder_queue_flush(AVFifo *queue)
{
FrameData fd;
av_assert0(queue);
while (av_fifo_read(queue, &fd, 1) >= 0)
av_buffer_unref(&fd.frame_opaque_ref);
}
typedef struct GUIDTuple {
const GUID guid;
int flags;
@ -1789,8 +1767,8 @@ static av_cold int nvenc_setup_surfaces(AVCodecContext *avctx)
if (!ctx->surfaces)
return AVERROR(ENOMEM);
ctx->reorder_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(FrameData), 0);
if (!ctx->reorder_queue)
ctx->timestamp_list = av_fifo_alloc2(ctx->nb_surfaces, sizeof(int64_t), 0);
if (!ctx->timestamp_list)
return AVERROR(ENOMEM);
ctx->unused_surface_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(NvencSurface*), 0);
@ -1874,11 +1852,7 @@ av_cold int ff_nvenc_encode_close(AVCodecContext *avctx)
p_nvenc->nvEncEncodePicture(ctx->nvencoder, &params);
}
if (ctx->reorder_queue) {
reorder_queue_flush(ctx->reorder_queue);
av_fifo_freep2(&ctx->reorder_queue);
}
av_fifo_freep2(&ctx->timestamp_list);
av_fifo_freep2(&ctx->output_surface_ready_queue);
av_fifo_freep2(&ctx->output_surface_queue);
av_fifo_freep2(&ctx->unused_surface_queue);
@ -2222,53 +2196,18 @@ static void nvenc_codec_specific_pic_params(AVCodecContext *avctx,
}
}
static void reorder_queue_enqueue(AVFifo *queue, const AVCodecContext *avctx,
const AVFrame *frame, AVBufferRef **opaque_ref)
static inline void timestamp_queue_enqueue(AVFifo *queue, int64_t timestamp)
{
FrameData fd;
fd.pts = frame->pts;
fd.duration = frame->duration;
#if FF_API_REORDERED_OPAQUE
FF_DISABLE_DEPRECATION_WARNINGS
fd.reordered_opaque = frame->reordered_opaque;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
fd.frame_opaque = frame->opaque;
fd.frame_opaque_ref = *opaque_ref;
*opaque_ref = NULL;
av_fifo_write(queue, &fd, 1);
av_fifo_write(queue, &timestamp, 1);
}
static int64_t reorder_queue_dequeue(AVFifo *queue, AVCodecContext *avctx,
AVPacket *pkt)
static inline int64_t timestamp_queue_dequeue(AVFifo *queue)
{
FrameData fd;
int64_t timestamp = AV_NOPTS_VALUE;
// The following call might fail if the queue is empty.
if (av_fifo_read(queue, &fd, 1) < 0)
return AV_NOPTS_VALUE;
av_fifo_read(queue, &timestamp, 1);
if (pkt) {
#if FF_API_REORDERED_OPAQUE
FF_DISABLE_DEPRECATION_WARNINGS
avctx->reordered_opaque = fd.reordered_opaque;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
pkt->duration = fd.duration;
if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
pkt->opaque = fd.frame_opaque;
pkt->opaque_ref = fd.frame_opaque_ref;
fd.frame_opaque_ref = NULL;
}
}
av_buffer_unref(&fd.frame_opaque_ref);
return fd.pts;
return timestamp;
}
static int nvenc_set_timestamp(AVCodecContext *avctx,
@ -2276,15 +2215,12 @@ static int nvenc_set_timestamp(AVCodecContext *avctx,
AVPacket *pkt)
{
NvencContext *ctx = avctx->priv_data;
int64_t dts;
pkt->pts = params->outputTimeStamp;
dts = reorder_queue_dequeue(ctx->reorder_queue, avctx, pkt);
if (avctx->codec_descriptor->props & AV_CODEC_PROP_REORDER) {
FF_DISABLE_DEPRECATION_WARNINGS
pkt->dts = dts -
pkt->dts = timestamp_queue_dequeue(ctx->timestamp_list) -
#if FF_API_TICKS_PER_FRAME
FFMAX(avctx->ticks_per_frame, 1) *
#endif
@ -2386,7 +2322,7 @@ static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSur
return 0;
error:
reorder_queue_dequeue(ctx->reorder_queue, avctx, NULL);
timestamp_queue_dequeue(ctx->timestamp_list);
error2:
return res;
@ -2616,8 +2552,6 @@ static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
int sei_count = 0;
int i;
AVBufferRef *opaque_ref = NULL;
NvencContext *ctx = avctx->priv_data;
NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
@ -2685,17 +2619,9 @@ static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
pic_params.encodePicFlags = NV_ENC_PIC_FLAG_EOS;
}
// make a reference for enqueing in the reorder queue here,
// so that reorder_queue_enqueue() cannot fail
if (frame && frame->opaque_ref && avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
opaque_ref = av_buffer_ref(frame->opaque_ref);
if (!opaque_ref)
return AVERROR(ENOMEM);
}
res = nvenc_push_context(avctx);
if (res < 0)
goto opaque_ref_fail;
return res;
nv_status = p_nvenc->nvEncEncodePicture(ctx->nvencoder, &pic_params);
@ -2704,17 +2630,17 @@ static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
res = nvenc_pop_context(avctx);
if (res < 0)
goto opaque_ref_fail;
return res;
if (nv_status != NV_ENC_SUCCESS &&
nv_status != NV_ENC_ERR_NEED_MORE_INPUT) {
res = nvenc_print_error(avctx, nv_status, "EncodePicture failed!");
goto opaque_ref_fail;
}
nv_status != NV_ENC_ERR_NEED_MORE_INPUT)
return nvenc_print_error(avctx, nv_status, "EncodePicture failed!");
if (frame && frame->buf[0]) {
av_fifo_write(ctx->output_surface_queue, &in_surf, 1);
reorder_queue_enqueue(ctx->reorder_queue, avctx, frame, &opaque_ref);
if (avctx->codec_descriptor->props & AV_CODEC_PROP_REORDER)
timestamp_queue_enqueue(ctx->timestamp_list, frame->pts);
}
/* all the pending buffers are now ready for output */
@ -2724,10 +2650,6 @@ static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
}
return 0;
opaque_ref_fail:
av_buffer_unref(&opaque_ref);
return res;
}
int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
@ -2786,5 +2708,5 @@ av_cold void ff_nvenc_encode_flush(AVCodecContext *avctx)
NvencContext *ctx = avctx->priv_data;
nvenc_send_frame(avctx, NULL);
reorder_queue_flush(ctx->reorder_queue);
av_fifo_reset2(ctx->timestamp_list);
}

View File

@ -176,7 +176,7 @@ typedef struct NvencContext
AVFifo *unused_surface_queue;
AVFifo *output_surface_queue;
AVFifo *output_surface_ready_queue;
AVFifo *reorder_queue;
AVFifo *timestamp_list;
NV_ENC_SEI_PAYLOAD *sei_data;
int sei_data_size;

View File

@ -181,8 +181,7 @@ const FFCodec ff_av1_nvenc_encoder = {
.defaults = defaults,
.p.pix_fmts = ff_nvenc_pix_fmts,
.p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1 |
AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1,
.caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
FF_CODEC_CAP_INIT_CLEANUP,
.p.wrapper_name = "nvenc",

View File

@ -244,8 +244,7 @@ const FFCodec ff_h264_nvenc_encoder = {
.p.priv_class = &h264_nvenc_class,
.defaults = defaults,
.p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1 |
AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1,
.caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
FF_CODEC_CAP_INIT_CLEANUP,
.p.pix_fmts = ff_nvenc_pix_fmts,

View File

@ -226,8 +226,7 @@ const FFCodec ff_hevc_nvenc_encoder = {
.defaults = defaults,
.p.pix_fmts = ff_nvenc_pix_fmts,
.p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1 |
AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1,
.caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
FF_CODEC_CAP_INIT_CLEANUP,
.p.wrapper_name = "nvenc",