diff mbox

[FFmpeg-devel] avocdec/nvenc: Reconfigure bitrate on the fly

Message ID bf521666-0053-22e6-9485-da7bc961fef4@gmail.com
State Superseded
Headers show

Commit Message

pkv.stream May 2, 2018, 9:18 p.m. UTC
Hello,

The patch enables dynamic bitrate through ReconfigureEncoder method from 
nvenc API.
This is useful for live streaming in case of network congestion.

A similar patch for changing aspect ratio dynamically was previously 
submitted by Miroslav Slugen:

https://patchwork.ffmpeg.org/patch/2523/

but apparently was forgotten.

Thanks.
From d0bcca0829db32cc35eb42c858013163e3fa8357 Mon Sep 17 00:00:00 2001
From: pkviet <pkv.stream@gmail.com>
Date: Wed, 2 May 2018 22:59:02 +0200
Subject: [PATCH] avcodec/nvenc: Reconfigure bitrate on the fly

The patch enables dynamic bitrate through ReconfigureEncoder method
from nvenc API.
This is useful for live streaming in case of network congestion.

Signed-off-by: pkviet <pkv.stream@gmail.com>
---
 libavcodec/nvenc.c | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

Comments

Timo Rothenpieler May 2, 2018, 9:58 p.m. UTC | #1
Am 02.05.2018 um 23:18 schrieb pkv.stream:
> Hello,
> 
> The patch enables dynamic bitrate through ReconfigureEncoder method from 
> nvenc API.
> This is useful for live streaming in case of network congestion.
> 
> A similar patch for changing aspect ratio dynamically was previously 
> submitted by Miroslav Slugen:
> 
> https://patchwork.ffmpeg.org/patch/2523/
> 
> but apparently was forgotten.
> 
> Thanks.
> 

I indeed forgot that old patch. I will rebase and apply it first, so 
this patch will need some rebasing as well.

One note about the patch: doing the capability check on every single 
frame seems wasteful. I'm not sure how slow it is, but I'd expect it to 
be not free.

So doing that check once in the beginning with all the other cap checks 
and storing it somewhere would be better.
pkv.stream May 2, 2018, 10:09 p.m. UTC | #2
Le 02/05/2018 à 11:58 PM, Timo Rothenpieler a écrit :
> Am 02.05.2018 um 23:18 schrieb pkv.stream:
>> Hello,
>>
>> The patch enables dynamic bitrate through ReconfigureEncoder method 
>> from nvenc API.
>> This is useful for live streaming in case of network congestion.
>>
>> A similar patch for changing aspect ratio dynamically was previously 
>> submitted by Miroslav Slugen:
>>
>> https://patchwork.ffmpeg.org/patch/2523/
>>
>> but apparently was forgotten.
>>
>> Thanks.
>>
>
> I indeed forgot that old patch. I will rebase and apply it first, so 
> this patch will need some rebasing as well.
>
> One note about the patch: doing the capability check on every single 
> frame seems wasteful. I'm not sure how slow it is, but I'd expect it 
> to be not free.
>
> So doing that check once in the beginning with all the other cap 
> checks and storing it somewhere would be better.
Hi
thanks for your feedback.
I was not sure of whether to put the capability check with the others in 
nvenc_check_capabilities because if the cap is missing this would remove 
the encoder altogether:

ex: ln. 453 :     if ((ret = nvenc_check_capabilities(avctx)) < 0)
                         goto fail3;

I'll move it there then or if you think it's preferrable, I can move it 
to ff_nvenc_encode_init and store it.
Which option do you prefer ? I'll resubmit and rebase once the other 
patch is committed.

thanks

>
>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Timo Rothenpieler May 2, 2018, 10:14 p.m. UTC | #3
Am 02.05.2018 um 23:58 schrieb Timo Rothenpieler:
> Am 02.05.2018 um 23:18 schrieb pkv.stream:
>> Hello,
>>
>> The patch enables dynamic bitrate through ReconfigureEncoder method 
>> from nvenc API.
>> This is useful for live streaming in case of network congestion.
>>
>> A similar patch for changing aspect ratio dynamically was previously 
>> submitted by Miroslav Slugen:
>>
>> https://patchwork.ffmpeg.org/patch/2523/
>>
>> but apparently was forgotten.
>>
>> Thanks.
>>
> 
> I indeed forgot that old patch. I will rebase and apply it first, so 
> this patch will need some rebasing as well.
> 
> One note about the patch: doing the capability check on every single 
> frame seems wasteful. I'm not sure how slow it is, but I'd expect it to 
> be not free.
> 
> So doing that check once in the beginning with all the other cap checks 
> and storing it somewhere would be better.
> 

Also, the bitrate changes seem a bit static and don't match up with any 
of the rc modes, setting all the bitrate settings to the same 
avctx->bit_rate. Ideally this would use the same rate-control logic the 
main init uses.
pkv.stream May 2, 2018, 10:18 p.m. UTC | #4
Le 03/05/2018 à 12:14 AM, Timo Rothenpieler a écrit :
> Am 02.05.2018 um 23:58 schrieb Timo Rothenpieler:
>> Am 02.05.2018 um 23:18 schrieb pkv.stream:
>>> Hello,
>>>
>>> The patch enables dynamic bitrate through ReconfigureEncoder method 
>>> from nvenc API.
>>> This is useful for live streaming in case of network congestion.
>>>
>>> A similar patch for changing aspect ratio dynamically was previously 
>>> submitted by Miroslav Slugen:
>>>
>>> https://patchwork.ffmpeg.org/patch/2523/
>>>
>>> but apparently was forgotten.
>>>
>>> Thanks.
>>>
>>
>> I indeed forgot that old patch. I will rebase and apply it first, so 
>> this patch will need some rebasing as well.
>>
>> One note about the patch: doing the capability check on every single 
>> frame seems wasteful. I'm not sure how slow it is, but I'd expect it 
>> to be not free.
>>
>> So doing that check once in the beginning with all the other cap 
>> checks and storing it somewhere would be better.
>>
>
> Also, the bitrate changes seem a bit static and don't match up with 
> any of the rc modes, setting all the bitrate settings to the same 
> avctx->bit_rate. Ideally this would use the same rate-control logic 
> the main init uses.
>
sure will fix that
Thanks again

>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Timo Rothenpieler May 2, 2018, 10:21 p.m. UTC | #5
> Hi
> thanks for your feedback.
> I was not sure of whether to put the capability check with the others in 
> nvenc_check_capabilities because if the cap is missing this would remove 
> the encoder altogether:
> 
> ex: ln. 453 :     if ((ret = nvenc_check_capabilities(avctx)) < 0)
>                          goto fail3;
> 
> I'll move it there then or if you think it's preferrable, I can move it 
> to ff_nvenc_encode_init and store it.
> Which option do you prefer ? I'll resubmit and rebase once the other 
> patch is committed.

Just add a new field to the struct NvencContext.
And there is no need to fail on this check, store its result and go on, 
unless it's < 0, which indicates an actual error.

There's also no need to check for a changed bitrate outside of the call 
to reconfig_encoder, when making the same check inside of it again.
diff mbox

Patch

diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
index c14112c366..ed5974f307 100644
--- a/libavcodec/nvenc.c
+++ b/libavcodec/nvenc.c
@@ -1920,6 +1920,35 @@  static int output_ready(AVCodecContext *avctx, int flush)
     return (nb_ready > 0) && (nb_ready + nb_pending >= ctx->async_depth);
 }
 
+static void reconfig_encoder(AVCodecContext *avctx, const AVFrame *frame)
+{
+    NvencContext *ctx = avctx->priv_data;
+    NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
+    NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &(dl_fn->nvenc_funcs);
+    NV_ENC_RECONFIGURE_PARAMS rec= { 0 };
+    NVENCSTATUS nv_status;
+    BOOL bitrateChanged;
+
+    bitrateChanged = ctx->encode_config.rcParams.averageBitRate != avctx->bit_rate;
+
+    if (bitrateChanged) {
+        rec.version = NV_ENC_RECONFIGURE_PARAMS_VER;
+        rec.resetEncoder = 1;
+        rec.forceIDR = 1;
+        rec.reInitEncodeParams = ctx->init_encode_params;
+        rec.reInitEncodeParams.encodeConfig->rcParams.averageBitRate = avctx->bit_rate;
+        rec.reInitEncodeParams.encodeConfig->rcParams.maxBitRate = avctx->bit_rate;
+        rec.reInitEncodeParams.encodeConfig->rcParams.vbvBufferSize = avctx->bit_rate;
+        rec.reInitEncodeParams.encodeConfig->rcParams.vbvInitialDelay = avctx->bit_rate;
+        nv_status = p_nvenc->nvEncReconfigureEncoder(ctx->nvencoder, &rec);
+        if (nv_status != NV_ENC_SUCCESS) {
+            av_log(avctx, AV_LOG_INFO, "ReconfigureEncoder failed\n");
+        } else {
+            av_log(avctx, AV_LOG_INFO, "ReconfigureEncoder succeeded\n");
+        }
+    }
+}
+
 int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
 {
     NVENCSTATUS nv_status;
@@ -1940,6 +1969,15 @@  int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
         return AVERROR_EOF;
 
     if (frame) {
+        res = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_DYN_BITRATE_CHANGE);
+        if (res > 0) {
+            if (ctx->encode_config.rcParams.averageBitRate != avctx->bit_rate) {
+                av_log(avctx, AV_LOG_INFO, "Switching NVenc bitrate\n");
+                reconfig_encoder(avctx, frame);
+            }
+        } else {
+            av_log(avctx, AV_LOG_INFO, "Dynamic Encode bitrate change not supported\n");
+        }
         in_surf = get_free_frame(ctx);
         if (!in_surf)
             return AVERROR(EAGAIN);