From patchwork Wed Mar 6 14:57:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Collyer X-Patchwork-Id: 12219 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 44D714464D9 for ; Wed, 6 Mar 2019 16:57:38 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 2287B68A4CB; Wed, 6 Mar 2019 16:57:38 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from st43p00im-zteg10073401.me.com (st43p00im-zteg10073401.me.com [17.58.63.181]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id CF1826806D1 for ; Wed, 6 Mar 2019 16:57:31 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mac.com; s=04042017; t=1551884249; bh=OMa0qEUFf7fjqW72u8IXmNmFHQO3WwniPhnXJTHQq14=; h=From:Content-Type:Mime-Version:Subject:Message-Id:Date:To; b=gwCKpyKxAbnS9YeCdTm/A1EMlWATsAo/ZkE2ab0fh1GeG+ObJalZreOS/BHHDzH8D TUATMNFth/HMiTHzjbhLpcHXTdZ2sAf5KrBcNUdlKFyWON9DHoAoie0iufuCrDncc8 v2s4/HMpeISjLBrlqdp5kMIT7TFsaZFfe7Hsq28AW7TRoehHLj88uzVCv+vzvKq1BZ RAuubf3Difa6eXlDVFjubIC6uaf9OibSQo/D10etiAw2XmaLXHRZHTLdS3iTyZWHT+ sdgxYiSCpCb+yblhD76IB8nJGV8W7EyTAp9KBHdpjVHN3bpOBeiC3w7nb52xP/MIcB Ah58lnBCYfZ+A== Received: from [192.168.0.116] (unknown [82.163.117.68]) by st43p00im-zteg10073401.me.com (Postfix) with ESMTPSA id 34A115E01BC for ; Wed, 6 Mar 2019 14:57:29 +0000 (UTC) From: Oliver Collyer Mime-Version: 1.0 (Mac OS X Mail 12.2 \(3445.102.3\)) Message-Id: <15484CA6-B6B2-479C-BED0-5950A97D3E91@mac.com> Date: Wed, 6 Mar 2019 14:57:25 +0000 To: FFmpeg development discussions and patches X-Mailer: Apple Mail (2.3445.102.3) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-06_10:, , signatures=0 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 suspectscore=0 malwarescore=0 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 mlxscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1812120000 definitions=main-1903060104 X-Content-Filtered-By: Mailman/MimeDel 2.1.20 Subject: [FFmpeg-devel] [PATCH] avcodec/nvenc: Reconfigure resolution on-the-fly X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Hi I needed the dynamic resolution changing feature of NVENC to be accessible through the ffmpeg libraries for a hobby project, so I added support and here is a patch. I will format this as a proper patch after any changes necessary following feedback. To use this feature you would need to: 1. Specify max_width and max_height before opening the encoder 2. Change the encoder context width/height during encoding Note that it is the caller's responsibility to scale the input frames to match the new encoder size after changing it! In my test I just use sws_scale where needed. Here is a link to a file that switches resolution a few times between 1920x1080 and 1280x720, that was generated using this patch. This plays correctly in VLC. https://www.dropbox.com/s/rvt94ai3jx5lbi9/test_switching_2.ts?dl=0 Regards Oliver diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 0ce22ec4fa..7087f82ce1 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -3357,6 +3357,12 @@ typedef struct AVCodecContext { * - encoding: unused */ int discard_damaged_percentage; + + /* + * Video encoding only. Sets the maximum picture size for encoders that + * support adjusting the picture size dynamically during encoding. + */ + int max_width, max_height; } AVCodecContext; #if FF_API_CODEC_GET_SET diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 304a684e0c..414707dcfd 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -384,6 +384,7 @@ static int nvenc_check_capabilities(AVCodecContext *avctx) #endif ctx->support_dyn_bitrate = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_DYN_BITRATE_CHANGE); + ctx->support_dyn_res = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_DYN_RES_CHANGE); return 0; } @@ -1121,6 +1122,8 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx) ctx->init_encode_params.encodeHeight = avctx->height; ctx->init_encode_params.encodeWidth = avctx->width; + ctx->init_encode_params.maxEncodeHeight = avctx->max_height; + ctx->init_encode_params.maxEncodeWidth = avctx->max_width; ctx->init_encode_params.encodeConfig = &ctx->encode_config; @@ -1276,8 +1279,8 @@ static av_cold int nvenc_alloc_surface(AVCodecContext *avctx, int idx) } allocSurf.version = NV_ENC_CREATE_INPUT_BUFFER_VER; - allocSurf.width = avctx->width; - allocSurf.height = avctx->height; + allocSurf.width = FFMAX(avctx->max_width, avctx->width); + allocSurf.height = FFMAX(avctx->max_height, avctx->height); allocSurf.bufferFmt = ctx->surfaces[idx].format; nv_status = p_nvenc->nvEncCreateInputBuffer(ctx->nvencoder, &allocSurf); @@ -1926,7 +1929,7 @@ static void reconfig_encoder(AVCodecContext *avctx, const AVFrame *frame) NV_ENC_RECONFIGURE_PARAMS params = { 0 }; int needs_reconfig = 0; int needs_encode_config = 0; - int reconfig_bitrate = 0, reconfig_dar = 0; + int reconfig_bitrate = 0, reconfig_dar = 0, reconfig_res = 0; int dw, dh; params.version = NV_ENC_RECONFIGURE_PARAMS_VER; @@ -1986,6 +1989,24 @@ static void reconfig_encoder(AVCodecContext *avctx, const AVFrame *frame) } } + if (ctx->support_dyn_res && ctx->init_encode_params.maxEncodeWidth && ctx->init_encode_params.maxEncodeHeight) { + if (params.reInitEncodeParams.encodeWidth != avctx->width || params.reInitEncodeParams.encodeHeight != avctx->height) { + av_log(avctx, AV_LOG_VERBOSE, + "resolution change: %d x %d -> %d x %d\n", + params.reInitEncodeParams.encodeWidth, + params.reInitEncodeParams.encodeHeight, + (uint32_t)avctx->width, + (uint32_t)avctx->height); + + params.reInitEncodeParams.encodeWidth = avctx->width; + params.reInitEncodeParams.encodeHeight = avctx->height; + params.forceIDR = 1; + + needs_reconfig = 1; + reconfig_res = 1; + } + } + if (!needs_encode_config) params.reInitEncodeParams.encodeConfig = NULL; @@ -2005,6 +2026,10 @@ static void reconfig_encoder(AVCodecContext *avctx, const AVFrame *frame) ctx->encode_config.rcParams.vbvBufferSize = params.reInitEncodeParams.encodeConfig->rcParams.vbvBufferSize; } + if (reconfig_res) { + ctx->init_encode_params.encodeWidth = params.reInitEncodeParams.encodeWidth; + ctx->init_encode_params.encodeHeight = params.reInitEncodeParams.encodeHeight; + } } } } diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index ddd6168409..f3b959b31a 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -158,6 +158,7 @@ typedef struct NvencContext int first_packet_output; int support_dyn_bitrate; + int support_dyn_res; void *nvencoder; diff --git a/libavcodec/version.h b/libavcodec/version.h index 309e4111cb..a217283b03 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 58 #define LIBAVCODEC_VERSION_MINOR 47 -#define LIBAVCODEC_VERSION_MICRO 103 +#define LIBAVCODEC_VERSION_MICRO 104 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \