diff options
author | Miroslav Slugeň <thunder.m@email.cz> | 2017-02-12 19:53:58 +0100 |
---|---|---|
committer | Timo Rothenpieler <timo@rothenpieler.org> | 2018-05-04 23:35:38 +0200 |
commit | 952421cd20ace9f0dccbf37e9ab9c165a68d17d0 (patch) | |
tree | ab0c72de87584263793dbbc15bda07d5afd94d5b /libavcodec/nvenc.c | |
parent | 7d4e1f7cfb667585514bfa0a4d0fee2f717a93ed (diff) | |
download | ffmpeg-952421cd20ace9f0dccbf37e9ab9c165a68d17d0.tar.gz |
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.c | 67 |
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, ¶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); |