[FFmpeg-devel] [PATCH v2] avcodec/nvenc: adapt to the new internal encode API
James Almer
jamrial at gmail.com
Thu Apr 9 21:27:22 EEST 2020
Signed-off-by: James Almer <jamrial at gmail.com>
---
Version with the flush() callback left in place. But it will need the
changes i originally added to avcodec_flush_buffers() and then removed
for the latest iteration of this set, in some form or another.
libavcodec/nvenc.c | 78 ++++++++++++++++++-----------------------
libavcodec/nvenc.h | 9 ++---
libavcodec/nvenc_h264.c | 6 ----
libavcodec/nvenc_hevc.c | 4 ---
4 files changed, 36 insertions(+), 61 deletions(-)
diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
index 9a96bf2bba..700a9a7a97 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)
+static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
{
NVENCSTATUS nv_status;
NvencSurface *tmp_out_surf, *in_surf;
@@ -2093,18 +2098,7 @@ int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
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) {
+ if (frame && frame->buf[0]) {
in_surf = get_free_frame(ctx);
if (!in_surf)
return AVERROR(EAGAIN);
@@ -2164,7 +2158,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 +2175,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 && 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);
@@ -2210,10 +2203,25 @@ int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
NvencContext *ctx = avctx->priv_data;
+ AVFrame *frame = ctx->frame;
+
if ((!ctx->cu_context && !ctx->d3d11_device) || !ctx->nvencoder)
return AVERROR(EINVAL);
- if (output_ready(avctx, ctx->encoder_flushing)) {
+ if (!frame->buf[0]) {
+ res = ff_encode_get_frame(avctx, frame);
+ if (res < 0 && res != AVERROR_EOF)
+ return res;
+ }
+
+ res = nvenc_send_frame(avctx, frame);
+ if (res < 0) {
+ if (res != AVERROR(EAGAIN))
+ return res;
+ } else
+ av_frame_unref(frame);
+
+ 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 +2238,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);
@@ -2239,31 +2247,13 @@ 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)
+av_cold void ff_nvenc_encode_flush(AVCodecContext *avctx)
{
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);
+ nvenc_send_frame(avctx, NULL);
+ 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);
}
diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h
index c44c81e675..48dcfae05c 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;
@@ -207,13 +207,8 @@ int ff_nvenc_encode_init(AVCodecContext *avctx);
int ff_nvenc_encode_close(AVCodecContext *avctx);
-int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame);
-
int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt);
-int ff_nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
- const AVFrame *frame, int *got_packet);
-
void ff_nvenc_encode_flush(AVCodecContext *avctx);
extern const enum AVPixelFormat ff_nvenc_pix_fmts[];
diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c
index 479155fe15..bdb1423bb1 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,9 +232,7 @@ 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),
diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c
index 7c9b3848f1..449ecc85ea 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,9 +192,7 @@ 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),
--
2.26.0
More information about the ffmpeg-devel
mailing list