From 952421cd20ace9f0dccbf37e9ab9c165a68d17d0 Mon Sep 17 00:00:00 2001 From: Miroslav Slugeň Date: Sun, 12 Feb 2017 19:53:58 +0100 Subject: 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 --- libavcodec/nvenc.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 60 insertions(+), 7 deletions(-) (limited to 'libavcodec') 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, ¶ms); + 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); -- cgit v1.2.3