Skip to content

Commit 5f77951

Browse files
committed
avcodec/nvenc: only unregister input resources when absolutely needed
This reverts nvenc to old behaviour, which in some super rare edge cases performs better. The implication of this is that any potential API user who relies on nvenc cleaning up every frames device resources after it's done using them will now have to make a custom build of ffmpeg with the compile-time define NVENC_UNREGISTER_IMMEDIATELY set to 1. Pretty much nobody should need to set this, since the normal usage pattern of nvenc usually makes sure all frames are allocated from a common pool which reuses device resources as much as possible and holds on to them until the encode session ends.
1 parent 7c2ee8d commit 5f77951

File tree

2 files changed

+29
-10
lines changed

2 files changed

+29
-10
lines changed

libavcodec/nvenc.c

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,19 +1560,23 @@ static int nvenc_find_free_reg_resource(AVCodecContext *avctx)
15601560
NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
15611561
NVENCSTATUS nv_status;
15621562

1563-
int i;
1563+
int i, first_round;
15641564

15651565
if (ctx->nb_registered_frames == FF_ARRAY_ELEMS(ctx->registered_frames)) {
1566-
for (i = 0; i < ctx->nb_registered_frames; i++) {
1567-
if (!ctx->registered_frames[i].mapped) {
1568-
if (ctx->registered_frames[i].regptr) {
1569-
nv_status = p_nvenc->nvEncUnregisterResource(ctx->nvencoder, ctx->registered_frames[i].regptr);
1570-
if (nv_status != NV_ENC_SUCCESS)
1571-
return nvenc_print_error(avctx, nv_status, "Failed unregistering unused input resource");
1572-
ctx->registered_frames[i].ptr = NULL;
1573-
ctx->registered_frames[i].regptr = NULL;
1566+
for (first_round = 1; first_round >= 0; first_round--) {
1567+
for (i = 0; i < ctx->nb_registered_frames; i++) {
1568+
if (!ctx->registered_frames[i].mapped) {
1569+
if (ctx->registered_frames[i].regptr) {
1570+
if (first_round)
1571+
continue;
1572+
nv_status = p_nvenc->nvEncUnregisterResource(ctx->nvencoder, ctx->registered_frames[i].regptr);
1573+
if (nv_status != NV_ENC_SUCCESS)
1574+
return nvenc_print_error(avctx, nv_status, "Failed unregistering unused input resource");
1575+
ctx->registered_frames[i].ptr = NULL;
1576+
ctx->registered_frames[i].regptr = NULL;
1577+
}
1578+
return i;
15741579
}
1575-
return i;
15761580
}
15771581
}
15781582
} else {
@@ -1846,13 +1850,15 @@ static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSur
18461850
res = nvenc_print_error(avctx, nv_status, "Failed unmapping input resource");
18471851
goto error;
18481852
}
1853+
#if NVENC_UNREGISTER_IMMEDIATELY
18491854
nv_status = p_nvenc->nvEncUnregisterResource(ctx->nvencoder, ctx->registered_frames[tmpoutsurf->reg_idx].regptr);
18501855
if (nv_status != NV_ENC_SUCCESS) {
18511856
res = nvenc_print_error(avctx, nv_status, "Failed unregistering input resource");
18521857
goto error;
18531858
}
18541859
ctx->registered_frames[tmpoutsurf->reg_idx].ptr = NULL;
18551860
ctx->registered_frames[tmpoutsurf->reg_idx].regptr = NULL;
1861+
#endif
18561862
} else if (ctx->registered_frames[tmpoutsurf->reg_idx].mapped < 0) {
18571863
res = AVERROR_BUG;
18581864
goto error;

libavcodec/nvenc.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,19 @@ typedef void ID3D11Device;
5454
#define NVENC_HAVE_HEVC_BFRAME_REF_MODE
5555
#endif
5656

57+
/*
58+
* If this is set to 1 at compile time, nvenc will unregister every input frame
59+
* the moment it's no longer used. By default it will hold onto the device handle
60+
* until it runs out of internal space to buffer them, which increases frame throughput.
61+
*
62+
* This is here so a potential API user, who for some reason is unable to make sure each
63+
* and every pointer is available until nvenc is closed, can easily produce a custom
64+
* build restoring the more compatible but slower behaviour.
65+
*/
66+
#ifndef NVENC_UNREGISTER_IMMEDIATELY
67+
#define NVENC_UNREGISTER_IMMEDIATELY 0
68+
#endif
69+
5770
typedef struct NvencSurface
5871
{
5972
NV_ENC_INPUT_PTR input_surface;

0 commit comments

Comments
 (0)