summaryrefslogtreecommitdiff
path: root/libavcodec/nvenc.c
diff options
context:
space:
mode:
authorMiroslav Slugeň <thunder.m@email.cz>2017-02-12 19:53:58 +0100
committerTimo Rothenpieler <timo@rothenpieler.org>2018-05-04 23:35:38 +0200
commit952421cd20ace9f0dccbf37e9ab9c165a68d17d0 (patch)
treeab0c72de87584263793dbbc15bda07d5afd94d5b /libavcodec/nvenc.c
parent7d4e1f7cfb667585514bfa0a4d0fee2f717a93ed (diff)
avcodec/nvenc: support dynamic aspect ratio change
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. Signed-off-by: Timo Rothenpieler <timo@rothenpieler.org>
Diffstat (limited to 'libavcodec/nvenc.c')
-rw-r--r--libavcodec/nvenc.c67
1 files changed, 60 insertions, 7 deletions
diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
index 5018d074a1..7daf8b3bc0 100644
--- a/libavcodec/nvenc.c
+++ b/libavcodec/nvenc.c
@@ -1112,6 +1112,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;
@@ -1148,13 +1162,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;
@@ -1927,6 +1935,49 @@ 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)
+{
+ NvencContext *ctx = avctx->priv_data;
+ NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs;
+ NVENCSTATUS ret;
+
+ NV_ENC_RECONFIGURE_PARAMS params = { 0 };
+ int needs_reconfig = 0;
+ int needs_encode_config = 0;
+ int dw, dh;
+
+ params.version = NV_ENC_RECONFIGURE_PARAMS_VER;
+ params.reInitEncodeParams = ctx->init_encode_params;
+
+ 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.reInitEncodeParams.darHeight = dh;
+ params.reInitEncodeParams.darWidth = dw;
+
+ needs_reconfig = 1;
+ }
+
+ if (!needs_encode_config)
+ params.reInitEncodeParams.encodeConfig = NULL;
+
+ if (needs_reconfig) {
+ ret = p_nvenc->nvEncReconfigureEncoder(ctx->nvencoder, &params);
+ if (ret != NV_ENC_SUCCESS) {
+ nvenc_print_error(avctx, ret, "failed to reconfigure nvenc");
+ } else {
+ ctx->init_encode_params.darHeight = dh;
+ ctx->init_encode_params.darWidth = dw;
+ }
+ }
+
+ return 0;
+}
+
int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
{
NVENCSTATUS nv_status;
@@ -1947,6 +1998,8 @@ int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
return AVERROR_EOF;
if (frame) {
+ reconfig_encoder(avctx, frame);
+
in_surf = get_free_frame(ctx);
if (!in_surf)
return AVERROR(EAGAIN);