[FFmpeg-devel] nvenc: support dynamic aspect ratio change

Submitted by Miroslav Slugeň on Feb. 12, 2017, 6:53 p.m.

Details

Message ID 58A0AF46.5080107@email.cz
State New
Headers show

Commit Message

Miroslav Slugeň Feb. 12, 2017, 6:53 p.m.
If there is input like DVB-T streams it can change aspect ratio 
on-the-fly, so nvenc should respect this change and change aspect ratio 
in encoder.

Comments

Timo Rothenpieler Feb. 12, 2017, 7:27 p.m.
On 2/12/2017 7:53 PM, Miroslav Slugeň wrote:
> If there is input like DVB-T streams it can change aspect ratio
> on-the-fly, so nvenc should respect this change and change aspect ratio
> in encoder.

Haven't tested yet, but seems like a good idea. Are there other
parameters that would make sense to support reconfiguration for?
Can think of stuff like bitrate and the like, but there is no proper
interface to support changing them at runtime.
Miroslav Slugeň Feb. 12, 2017, 7:40 p.m.
Dne 12.2.2017 v 20:27 Timo Rothenpieler napsal(a):
> On 2/12/2017 7:53 PM, Miroslav Slugeň wrote:
>> If there is input like DVB-T streams it can change aspect ratio
>> on-the-fly, so nvenc should respect this change and change aspect ratio
>> in encoder.
> Haven't tested yet, but seems like a good idea. Are there other
> parameters that would make sense to support reconfiguration for?
> Can think of stuff like bitrate and the like, but there is no proper
> interface to support changing them at runtime.
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
In realtime only aspect ratio was most common, but inputs can change 
resolution and frame_rate, both could be also dynamicaly changed in encoder.

For example for resolution there is n MaxWidth & MaxHeight which could 
differ from actual encoding width and height, but i think this is not 
supported in current ffmpeg.

M.

Patch hide | download patch | download mbox

From d836780d56fb7d7a63d91a2af87a0f84743d95d6 Mon Sep 17 00:00:00 2001
From: Miroslav Slugen <thunder.m@email.cz>
Date: Sun, 12 Feb 2017 19:51:57 +0100
Subject: [PATCH 1/1] nvenc: support dynamic aspect ratio change

---
 libavcodec/nvenc.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 50 insertions(+), 7 deletions(-)

diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
index 7005465..dea9a1c 100644
--- a/libavcodec/nvenc.c
+++ b/libavcodec/nvenc.c
@@ -913,6 +913,20 @@  static av_cold int nvenc_setup_codec_config(AVCodecContext *avctx)
     return 0;
 }
 
+static void compute_dar(AVCodecContext *avctx, int *dw, int *dh) {
+    int sw, sh;
+
+    sw = avctx->width;
+    sh = avctx->height;
+
+    if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0) {
+        sw*= avctx->sample_aspect_ratio.num;
+        sh*= avctx->sample_aspect_ratio.den;
+    }
+
+    av_reduce(dw, dh, sw, sh, 1024 * 1024);
+}
+
 static av_cold int nvenc_setup_encoder(AVCodecContext *avctx)
 {
     NvencContext *ctx = avctx->priv_data;
@@ -949,13 +963,7 @@  static av_cold int nvenc_setup_encoder(AVCodecContext *avctx)
 
     ctx->encode_config.version = NV_ENC_CONFIG_VER;
 
-    dw = avctx->width;
-    dh = avctx->height;
-    if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0) {
-        dw*= avctx->sample_aspect_ratio.num;
-        dh*= avctx->sample_aspect_ratio.den;
-    }
-    av_reduce(&dw, &dh, dw, dh, 1024 * 1024);
+    compute_dar(avctx, &dw, &dh);
     ctx->init_encode_params.darHeight = dh;
     ctx->init_encode_params.darWidth = dw;
 
@@ -1644,6 +1652,39 @@  static int output_ready(AVCodecContext *avctx, int flush)
     return (nb_ready > 0) && (nb_ready + nb_pending >= ctx->async_depth);
 }
 
+static int reconfig_encoder(AVCodecContext *avctx, const AVFrame *frame)
+{
+    NV_ENC_RECONFIGURE_PARAMS params = { 0 };
+    NvencContext *ctx = avctx->priv_data;
+    NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs;
+    NVENCSTATUS ret;
+    int dw, dh;
+
+    compute_dar(avctx, &dw, &dh);
+    if (dw != ctx->init_encode_params.darWidth ||
+        dh != ctx->init_encode_params.darHeight) {
+        av_log(avctx, AV_LOG_VERBOSE,
+               "Aspect ratio change (DAR): %d:%d -> %d:%d\n",
+               ctx->init_encode_params.darWidth,
+               ctx->init_encode_params.darHeight, dw, dh);
+
+        params.version = NV_ENC_RECONFIGURE_PARAMS_VER;
+        params.reInitEncodeParams = ctx->init_encode_params;
+        params.reInitEncodeParams.darHeight = dh;
+        params.reInitEncodeParams.darWidth = dw;
+
+        ret = p_nvenc->nvEncReconfigureEncoder(ctx->nvencoder, &params);
+        if (ret != NV_ENC_SUCCESS) {
+            nvenc_print_error(avctx, ret, "Failed to reconfigure nvenc on aspect ratio change");
+        } else {
+            ctx->init_encode_params.darHeight = dh;
+            ctx->init_encode_params.darWidth = dw;
+        }
+    }
+
+    return 0;
+}
+
 int ff_nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
                           const AVFrame *frame, int *got_packet)
 {
@@ -1659,6 +1700,8 @@  int ff_nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     pic_params.version = NV_ENC_PIC_PARAMS_VER;
 
     if (frame) {
+        reconfig_encoder(avctx, frame);
+
         inSurf = get_free_frame(ctx);
         if (!inSurf) {
             av_log(avctx, AV_LOG_ERROR, "No free surfaces\n");
-- 
2.1.4