[FFmpeg-devel] [PATCH] avcodec/nvenc: adapt to the new internal encode API
James Almer
jamrial at gmail.com
Wed Apr 8 20:58:36 EEST 2020
Signed-off-by: James Almer <jamrial at gmail.com>
---
This removes the encode2() implementation as it'll never be used if a
receive_packet() one exists, and the flush() implementation since according to
Anton Khirnov avcodec_flush_buffers() is not meant to be used with encoders,
where its behavior is undefined.
libavcodec/nvenc.c | 84 +++++++++++------------------------------
libavcodec/nvenc.h | 4 +-
libavcodec/nvenc_h264.c | 7 ----
libavcodec/nvenc_hevc.c | 5 ---
4 files changed, 25 insertions(+), 75 deletions(-)
diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
index 9a96bf2bba..6c0baf4d86 100644
--- a/libavcodec/nvenc.c
+++ b/libavcodec/nvenc.c
@@ -30,6 +30,7 @@
#include "libavutil/avassert.h"
#include "libavutil/mem.h"
#include "libavutil/pixdesc.h"
+#include "encode.h"
#include "internal.h"
#define CHECK_CU(x) FF_CUDA_CHECK_DL(avctx, dl_fn->cuda_dl, x)
@@ -1491,6 +1492,8 @@ av_cold int ff_nvenc_encode_close(AVCodecContext *avctx)
av_freep(&ctx->surfaces);
ctx->nb_surfaces = 0;
+ av_frame_free(&ctx->frame);
+
if (ctx->nvencoder) {
p_nvenc->nvEncDestroyEncoder(ctx->nvencoder);
@@ -1544,6 +1547,10 @@ av_cold int ff_nvenc_encode_init(AVCodecContext *avctx)
ctx->data_pix_fmt = avctx->pix_fmt;
}
+ ctx->frame = av_frame_alloc();
+ if (!ctx->frame)
+ return AVERROR(ENOMEM);
+
if ((ret = nvenc_load_libraries(avctx)) < 0)
return ret;
@@ -1881,9 +1888,7 @@ static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSur
goto error;
}
- res = pkt->data ?
- ff_alloc_packet2(avctx, pkt, lock_params.bitstreamSizeInBytes, lock_params.bitstreamSizeInBytes) :
- av_new_packet(pkt, lock_params.bitstreamSizeInBytes);
+ res = av_new_packet(pkt, lock_params.bitstreamSizeInBytes);
if (res < 0) {
p_nvenc->nvEncUnlockBitstream(ctx->nvencoder, tmpoutsurf->output_surface);
@@ -2075,7 +2080,7 @@ static void reconfig_encoder(AVCodecContext *avctx, const AVFrame *frame)
}
}
-int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
+int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
{
NVENCSTATUS nv_status;
NvencSurface *tmp_out_surf, *in_surf;
@@ -2087,27 +2092,24 @@ int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
+ AVFrame *frame = ctx->frame;
+
NV_ENC_PIC_PARAMS pic_params = { 0 };
pic_params.version = NV_ENC_PIC_PARAMS_VER;
if ((!ctx->cu_context && !ctx->d3d11_device) || !ctx->nvencoder)
return AVERROR(EINVAL);
- if (ctx->encoder_flushing) {
- if (avctx->internal->draining)
- return AVERROR_EOF;
-
- ctx->encoder_flushing = 0;
- ctx->first_packet_output = 0;
- ctx->initial_pts[0] = AV_NOPTS_VALUE;
- ctx->initial_pts[1] = AV_NOPTS_VALUE;
- av_fifo_reset(ctx->timestamp_list);
+ if (!frame->buf[0]) {
+ res = ff_encode_get_frame(avctx, frame);
+ if (res < 0 && res != AVERROR_EOF)
+ return res;
}
- if (frame) {
+ if (frame->buf[0]) {
in_surf = get_free_frame(ctx);
if (!in_surf)
- return AVERROR(EAGAIN);
+ goto output;
res = nvenc_push_context(avctx);
if (res < 0)
@@ -2164,7 +2166,6 @@ int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
nvenc_codec_specific_pic_params(avctx, &pic_params, sei_data);
} else {
pic_params.encodePicFlags = NV_ENC_PIC_FLAG_EOS;
- ctx->encoder_flushing = 1;
}
res = nvenc_push_context(avctx);
@@ -2182,7 +2183,7 @@ int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
nv_status != NV_ENC_ERR_NEED_MORE_INPUT)
return nvenc_print_error(avctx, nv_status, "EncodePicture failed!");
- if (frame) {
+ if (frame->buf[0]) {
av_fifo_generic_write(ctx->output_surface_queue, &in_surf, sizeof(in_surf), NULL);
timestamp_queue_enqueue(ctx->timestamp_list, frame->pts);
@@ -2190,6 +2191,8 @@ int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
ctx->initial_pts[0] = frame->pts;
else if (ctx->initial_pts[1] == AV_NOPTS_VALUE)
ctx->initial_pts[1] = frame->pts;
+
+ av_frame_unref(frame);
}
/* all the pending buffers are now ready for output */
@@ -2200,20 +2203,8 @@ int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
}
}
- return 0;
-}
-
-int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
-{
- NvencSurface *tmp_out_surf;
- int res, res2;
-
- NvencContext *ctx = avctx->priv_data;
-
- if ((!ctx->cu_context && !ctx->d3d11_device) || !ctx->nvencoder)
- return AVERROR(EINVAL);
-
- if (output_ready(avctx, ctx->encoder_flushing)) {
+output:
+ if (output_ready(avctx, avctx->internal->draining)) {
av_fifo_generic_read(ctx->output_surface_ready_queue, &tmp_out_surf, sizeof(tmp_out_surf), NULL);
res = nvenc_push_context(avctx);
@@ -2230,7 +2221,7 @@ int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
return res;
av_fifo_generic_write(ctx->unused_surface_queue, &tmp_out_surf, sizeof(tmp_out_surf), NULL);
- } else if (ctx->encoder_flushing) {
+ } else if (avctx->internal->draining) {
return AVERROR_EOF;
} else {
return AVERROR(EAGAIN);
@@ -2238,32 +2229,3 @@ int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
return 0;
}
-
-int ff_nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
- const AVFrame *frame, int *got_packet)
-{
- NvencContext *ctx = avctx->priv_data;
- int res;
-
- if (!ctx->encoder_flushing) {
- res = ff_nvenc_send_frame(avctx, frame);
- if (res < 0)
- return res;
- }
-
- res = ff_nvenc_receive_packet(avctx, pkt);
- if (res == AVERROR(EAGAIN) || res == AVERROR_EOF) {
- *got_packet = 0;
- } else if (res < 0) {
- return res;
- } else {
- *got_packet = 1;
- }
-
- return 0;
-}
-
-av_cold void ff_nvenc_encode_flush(AVCodecContext *avctx)
-{
- ff_nvenc_send_frame(avctx, NULL);
-}
diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h
index c44c81e675..6e0d418365 100644
--- a/libavcodec/nvenc.h
+++ b/libavcodec/nvenc.h
@@ -137,6 +137,8 @@ typedef struct NvencContext
CUstream cu_stream;
ID3D11Device *d3d11_device;
+ AVFrame *frame;
+
int nb_surfaces;
NvencSurface *surfaces;
@@ -145,8 +147,6 @@ typedef struct NvencContext
AVFifoBuffer *output_surface_ready_queue;
AVFifoBuffer *timestamp_list;
- int encoder_flushing;
-
struct {
void *ptr;
int ptr_index;
diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c
index 479155fe15..43ec48f89d 100644
--- a/libavcodec/nvenc_h264.c
+++ b/libavcodec/nvenc_h264.c
@@ -178,9 +178,7 @@ AVCodec ff_nvenc_encoder = {
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_H264,
.init = nvenc_old_init,
- .send_frame = ff_nvenc_send_frame,
.receive_packet = ff_nvenc_receive_packet,
- .encode2 = ff_nvenc_encode_frame,
.close = ff_nvenc_encode_close,
.priv_data_size = sizeof(NvencContext),
.priv_class = &nvenc_class,
@@ -207,9 +205,7 @@ AVCodec ff_nvenc_h264_encoder = {
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_H264,
.init = nvenc_old_init,
- .send_frame = ff_nvenc_send_frame,
.receive_packet = ff_nvenc_receive_packet,
- .encode2 = ff_nvenc_encode_frame,
.close = ff_nvenc_encode_close,
.priv_data_size = sizeof(NvencContext),
.priv_class = &nvenc_h264_class,
@@ -236,11 +232,8 @@ AVCodec ff_h264_nvenc_encoder = {
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_H264,
.init = ff_nvenc_encode_init,
- .send_frame = ff_nvenc_send_frame,
.receive_packet = ff_nvenc_receive_packet,
- .encode2 = ff_nvenc_encode_frame,
.close = ff_nvenc_encode_close,
- .flush = ff_nvenc_encode_flush,
.priv_data_size = sizeof(NvencContext),
.priv_class = &h264_nvenc_class,
.defaults = defaults,
diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c
index 7c9b3848f1..a575d64092 100644
--- a/libavcodec/nvenc_hevc.c
+++ b/libavcodec/nvenc_hevc.c
@@ -166,9 +166,7 @@ AVCodec ff_nvenc_hevc_encoder = {
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_HEVC,
.init = nvenc_old_init,
- .send_frame = ff_nvenc_send_frame,
.receive_packet = ff_nvenc_receive_packet,
- .encode2 = ff_nvenc_encode_frame,
.close = ff_nvenc_encode_close,
.priv_data_size = sizeof(NvencContext),
.priv_class = &nvenc_hevc_class,
@@ -194,11 +192,8 @@ AVCodec ff_hevc_nvenc_encoder = {
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_HEVC,
.init = ff_nvenc_encode_init,
- .send_frame = ff_nvenc_send_frame,
.receive_packet = ff_nvenc_receive_packet,
- .encode2 = ff_nvenc_encode_frame,
.close = ff_nvenc_encode_close,
- .flush = ff_nvenc_encode_flush,
.priv_data_size = sizeof(NvencContext),
.priv_class = &hevc_nvenc_class,
.defaults = defaults,
--
2.26.0
More information about the ffmpeg-devel
mailing list