diff options
author | Scott <[email protected]> | 2018-06-29 19:48:26 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2018-06-29 19:48:26 +0100 |
commit | dbf898635dc12608b78c33916137465ce08937bf (patch) | |
tree | 2449891c1f1275e43673b9aa276b8e8905374b55 | |
parent | ac390b630498163ff37bea491202c0872bb679ec (diff) |
Add NVEnc encoder. (Round 3) (#1437)
Adding the Nvidia NVEnc H.264 and H.265 encoders.
Based on Initial work by sgothel
--enable-nvenc is the new compile time configure option to enable for builds.
-rw-r--r-- | contrib/ffmpeg/module.defs | 12 | ||||
-rw-r--r-- | contrib/nvenc/module.defs | 12 | ||||
-rw-r--r-- | contrib/nvenc/module.rules | 2 | ||||
-rw-r--r-- | libhb/common.c | 81 | ||||
-rw-r--r-- | libhb/common.h | 8 | ||||
-rw-r--r-- | libhb/encavcodec.c | 109 | ||||
-rw-r--r-- | libhb/hbffmpeg.h | 5 | ||||
-rw-r--r-- | libhb/module.defs | 4 | ||||
-rw-r--r-- | libhb/muxavformat.c | 2 | ||||
-rw-r--r-- | libhb/nvenc_common.c | 57 | ||||
-rw-r--r-- | libhb/nvenc_common.h | 11 | ||||
-rw-r--r-- | libhb/work.c | 15 | ||||
-rw-r--r-- | make/configure.py | 5 | ||||
-rw-r--r-- | make/include/main.defs | 4 | ||||
-rw-r--r-- | test/module.defs | 4 | ||||
-rw-r--r-- | win/CS/HandBrake.Interop/Interop/HbLib/HbFunctions.cs | 6 | ||||
-rw-r--r-- | win/CS/HandBrake.Interop/Interop/Model/Encoding/VideoEncoder.cs | 10 | ||||
-rw-r--r-- | win/CS/HandBrake.Interop/Utilities/SystemInfo.cs | 50 | ||||
-rw-r--r-- | win/CS/HandBrakeWPF/Converters/Video/VideoEncoderConverter.cs | 10 | ||||
-rw-r--r-- | win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs | 27 |
20 files changed, 383 insertions, 51 deletions
diff --git a/contrib/ffmpeg/module.defs b/contrib/ffmpeg/module.defs index 63924ad96..e24a897b9 100644 --- a/contrib/ffmpeg/module.defs +++ b/contrib/ffmpeg/module.defs @@ -5,6 +5,9 @@ endif ifeq (1,$(FEATURE.vce)) __deps__ += AMF endif +ifeq (1,$(FEATURE.nvenc)) +__deps__ += NVENC +endif $(eval $(call import.MODULE.defs,FFMPEG,ffmpeg,$(__deps__))) $(eval $(call import.CONTRIB.defs,FFMPEG)) @@ -107,7 +110,14 @@ ifeq (1,$(FEATURE.qsv)) endif ifeq (1,$(FEATURE.vce)) - FFMPEG.CONFIGURE.extra += --enable-amf --enable-encoder=h264_amf --enable-encoder=hevc_amf + FFMPEG.CONFIGURE.extra += --enable-amf --enable-encoder=h264_amf --enable-encoder=hevc_amf +endif + +ifeq (1,$(FEATURE.nvenc)) +FFMPEG.CONFIGURE.extra += \ + --enable-nvenc \ + --enable-encoder=h264_nvenc \ + --enable-encoder=hevc_nvenc endif ## enable compile verbosity diff --git a/contrib/nvenc/module.defs b/contrib/nvenc/module.defs new file mode 100644 index 000000000..e040b9ade --- /dev/null +++ b/contrib/nvenc/module.defs @@ -0,0 +1,12 @@ +$(eval $(call import.MODULE.defs,NVENC,nvenc)) +$(eval $(call import.CONTRIB.defs,NVENC)) + +NVENC.FETCH.url = https://download.handbrake.fr/contrib/nv-codec-headers-8.1.24.2.tar.gz +NVENC.FETCH.url += https://github.com/FFmpeg/nv-codec-headers/releases/download/n8.1.24.2/nv-codec-headers-8.1.24.2.tar.gz +NVENC.FETCH.sha256 = 2b339b2493f5b63b285dd660be05102af7d4ff2de9fcf3af94e48b5f91a3ca57 +NVENC.EXTRACT.tarbase = nv-codec-headers-n8.1.24.2 + +NVENC.CONFIGURE = $(TOUCH.exe) $@ +NVENC.BUILD.extra = PREFIX="$(NVENC.CONFIGURE.prefix)" +NVENC.INSTALL.extra = PREFIX="$(NVENC.CONFIGURE.prefix)" +NVENC.UNINSTALL.extra = PREFIX="$(NVENC.CONFIGURE.prefix)" diff --git a/contrib/nvenc/module.rules b/contrib/nvenc/module.rules new file mode 100644 index 000000000..976986a57 --- /dev/null +++ b/contrib/nvenc/module.rules @@ -0,0 +1,2 @@ +$(eval $(call import.MODULE.rules,NVENC)) +$(eval $(call import.CONTRIB.rules,NVENC)) diff --git a/libhb/common.c b/libhb/common.c index a4c84198f..e8a1dee9f 100644 --- a/libhb/common.c +++ b/libhb/common.c @@ -31,6 +31,10 @@ #include <windows.h> #endif +#ifdef USE_QSV +#include "nvenc_common.h" +#endif + static int mixdown_get_opus_coupled_stream_count(int mixdown); /********************************************************************** @@ -228,27 +232,29 @@ hb_encoder_t *hb_video_encoders_last_item = NULL; hb_encoder_internal_t hb_video_encoders[] = { // legacy encoders, back to HB 0.9.4 whenever possible (disabled) - { { "FFmpeg", "ffmpeg", NULL, HB_VCODEC_FFMPEG_MPEG4, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 0, HB_GID_VCODEC_MPEG4, }, - { { "MPEG-4 (FFmpeg)", "ffmpeg4", NULL, HB_VCODEC_FFMPEG_MPEG4, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 0, HB_GID_VCODEC_MPEG4, }, - { { "MPEG-2 (FFmpeg)", "ffmpeg2", NULL, HB_VCODEC_FFMPEG_MPEG2, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 0, HB_GID_VCODEC_MPEG2, }, + { { "FFmpeg", "ffmpeg", NULL, HB_VCODEC_FFMPEG_MPEG4, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 0, HB_GID_VCODEC_MPEG4, }, + { { "MPEG-4 (FFmpeg)", "ffmpeg4", NULL, HB_VCODEC_FFMPEG_MPEG4, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 0, HB_GID_VCODEC_MPEG4, }, + { { "MPEG-2 (FFmpeg)", "ffmpeg2", NULL, HB_VCODEC_FFMPEG_MPEG2, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 0, HB_GID_VCODEC_MPEG2, }, { { "VP3 (Theora)", "libtheora", NULL, HB_VCODEC_THEORA, HB_MUX_MASK_MKV, }, NULL, 0, HB_GID_VCODEC_THEORA, }, // actual encoders { { "H.264 (x264)", "x264", "H.264 (libx264)", HB_VCODEC_X264_8BIT, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_H264, }, - { { "H.264 10-bit (x264)", "x264_10bit", "H.264 10-bit (libx264)", HB_VCODEC_X264_10BIT, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_H264, }, - { { "H.264 (Intel QSV)", "qsv_h264", "H.264 (Intel Media SDK)", HB_VCODEC_QSV_H264, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_H264, }, - { { "H.264 (AMD VCE)", "vce_h264", "H.264 (libavcodec)", HB_VCODEC_FFMPEG_VCE_H264, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_H264, }, - { { "H.265 (x265)", "x265", "H.265 (libx265)", HB_VCODEC_X265_8BIT, HB_MUX_AV_MP4|HB_MUX_AV_MKV, }, NULL, 1, HB_GID_VCODEC_H265, }, - { { "H.265 10-bit (x265)", "x265_10bit", "H.265 10-bit (libx265)", HB_VCODEC_X265_10BIT, HB_MUX_AV_MP4|HB_MUX_AV_MKV, }, NULL, 1, HB_GID_VCODEC_H265, }, - { { "H.265 12-bit (x265)", "x265_12bit", "H.265 12-bit (libx265)", HB_VCODEC_X265_12BIT, HB_MUX_AV_MP4|HB_MUX_AV_MKV, }, NULL, 1, HB_GID_VCODEC_H265, }, - { { "H.265 16-bit (x265)", "x265_16bit", "H.265 16-bit (libx265)", HB_VCODEC_X265_16BIT, HB_MUX_AV_MP4|HB_MUX_AV_MKV, }, NULL, 1, HB_GID_VCODEC_H265, }, - { { "H.265 (Intel QSV)", "qsv_h265", "H.265 (Intel Media SDK)", HB_VCODEC_QSV_H265, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_H265, }, - { { "H.265 10-bit (Intel QSV)", "qsv_h265_10bit", "H.265 10-bit (Intel Media SDK)", HB_VCODEC_QSV_H265_10BIT, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_H265, }, - { { "H.265 (AMD VCE)", "vce_h265", "H.265 (libavcodec)", HB_VCODEC_FFMPEG_VCE_H265, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_H264, }, - { { "MPEG-4", "mpeg4", "MPEG-4 (libavcodec)", HB_VCODEC_FFMPEG_MPEG4, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_MPEG4, }, - { { "MPEG-2", "mpeg2", "MPEG-2 (libavcodec)", HB_VCODEC_FFMPEG_MPEG2, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_MPEG2, }, - { { "VP8", "VP8", "VP8 (libvpx)", HB_VCODEC_FFMPEG_VP8, HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_VP8, }, - { { "VP9", "VP9", "VP9 (libvpx)", HB_VCODEC_FFMPEG_VP9, HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_VP9, }, - { { "Theora", "theora", "Theora (libtheora)", HB_VCODEC_THEORA, HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_THEORA, }, + { { "H.264 10-bit (x264)", "x264_10bit", "H.264 10-bit (libx264)", HB_VCODEC_X264_10BIT, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_H264, }, + { { "H.264 (Intel QSV)", "qsv_h264", "H.264 (Intel Media SDK)", HB_VCODEC_QSV_H264, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_H264, }, + { { "H.264 (AMD VCE)", "vce_h264", "H.264 (libavcodec)", HB_VCODEC_FFMPEG_VCE_H264, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_H264, }, + { { "H.264 (NVEnc)", "nvenc_h264", "H.264 (libavcodec)", HB_VCODEC_FFMPEG_NVENC_H264, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_H264, }, + { { "H.265 (x265)", "x265", "H.265 (libx265)", HB_VCODEC_X265_8BIT, HB_MUX_AV_MP4|HB_MUX_AV_MKV, }, NULL, 1, HB_GID_VCODEC_H265, }, + { { "H.265 10-bit (x265)", "x265_10bit", "H.265 10-bit (libx265)", HB_VCODEC_X265_10BIT, HB_MUX_AV_MP4|HB_MUX_AV_MKV, }, NULL, 1, HB_GID_VCODEC_H265, }, + { { "H.265 12-bit (x265)", "x265_12bit", "H.265 12-bit (libx265)", HB_VCODEC_X265_12BIT, HB_MUX_AV_MP4|HB_MUX_AV_MKV, }, NULL, 1, HB_GID_VCODEC_H265, }, + { { "H.265 16-bit (x265)", "x265_16bit", "H.265 16-bit (libx265)", HB_VCODEC_X265_16BIT, HB_MUX_AV_MP4|HB_MUX_AV_MKV, }, NULL, 1, HB_GID_VCODEC_H265, }, + { { "H.265 (Intel QSV)", "qsv_h265", "H.265 (Intel Media SDK)", HB_VCODEC_QSV_H265, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_H265, }, + { { "H.265 10-bit (Intel QSV)","qsv_h265_10bit", "H.265 10-bit (Intel Media SDK)", HB_VCODEC_QSV_H265_10BIT, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_H265, }, + { { "H.265 (AMD VCE)", "vce_h265", "H.265 (libavcodec)", HB_VCODEC_FFMPEG_VCE_H265, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_H265, }, + { { "H.265 (NVEnc)", "nvenc_h265", "H.265 (libavcodec)", HB_VCODEC_FFMPEG_NVENC_H265, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_H265, }, + { { "MPEG-4", "mpeg4", "MPEG-4 (libavcodec)", HB_VCODEC_FFMPEG_MPEG4, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_MPEG4, }, + { { "MPEG-2", "mpeg2", "MPEG-2 (libavcodec)", HB_VCODEC_FFMPEG_MPEG2, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_MPEG2, }, + { { "VP8", "VP8", "VP8 (libvpx)", HB_VCODEC_FFMPEG_VP8, HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_VP8, }, + { { "VP9", "VP9", "VP9 (libvpx)", HB_VCODEC_FFMPEG_VP9, HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_VP9, }, + { { "Theora", "theora", "Theora (libtheora)", HB_VCODEC_THEORA, HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_THEORA, }, }; int hb_video_encoders_count = sizeof(hb_video_encoders) / sizeof(hb_video_encoders[0]); static int hb_video_encoder_is_enabled(int encoder) @@ -275,6 +281,13 @@ static int hb_video_encoder_is_enabled(int encoder) return 1; #endif +#ifdef USE_NVENC + case HB_VCODEC_FFMPEG_NVENC_H264: + return hb_nvenc_h264_available(); + case HB_VCODEC_FFMPEG_NVENC_H265: + return hb_nvenc_h265_available(); +#endif + #ifdef USE_X265 case HB_VCODEC_X265_8BIT: case HB_VCODEC_X265_10BIT: @@ -1305,6 +1318,8 @@ void hb_video_quality_get_limits(uint32_t codec, float *low, float *high, */ case HB_VCODEC_X264_8BIT: case HB_VCODEC_X265_8BIT: + case HB_VCODEC_FFMPEG_NVENC_H264: + case HB_VCODEC_FFMPEG_NVENC_H265: *direction = 1; *granularity = 0.1; *low = 0.; @@ -1377,6 +1392,8 @@ const char* hb_video_quality_get_name(uint32_t codec) case HB_VCODEC_FFMPEG_VP8: case HB_VCODEC_FFMPEG_VP9: + case HB_VCODEC_FFMPEG_NVENC_H264: + case HB_VCODEC_FFMPEG_NVENC_H265: return "CQ"; default: @@ -1484,7 +1501,10 @@ const char* const* hb_video_encoder_get_profiles(int encoder) return hb_h264_profile_names_8bit; case HB_VCODEC_FFMPEG_VCE_H265: return hb_h265_profile_names_8bit; - + + case HB_VCODEC_FFMPEG_NVENC_H264: + case HB_VCODEC_FFMPEG_NVENC_H265: + return hb_av_profile_get_names(encoder); default: return NULL; } @@ -1499,23 +1519,22 @@ const char* const* hb_video_encoder_get_levels(int encoder) } #endif -#ifdef USE_VCE - if (encoder & HB_VCODEC_FFMPEG_VCE_H264) - { - return hb_h264_level_names; - } - - if (encoder & HB_VCODEC_FFMPEG_VCE_H265) - { - return hb_h265_level_names; - } -#endif - switch (encoder) { case HB_VCODEC_X264_8BIT: case HB_VCODEC_X264_10BIT: + case HB_VCODEC_FFMPEG_NVENC_H264: + case HB_VCODEC_FFMPEG_VCE_H264: + return hb_h264_level_names; + + case HB_VCODEC_X265_8BIT: + case HB_VCODEC_X265_10BIT: + case HB_VCODEC_X265_12BIT: + case HB_VCODEC_X265_16BIT: + case HB_VCODEC_FFMPEG_NVENC_H265: + case HB_VCODEC_FFMPEG_VCE_H265: return hb_h264_level_names; + default: return NULL; diff --git a/libhb/common.h b/libhb/common.h index a91d608c9..1d28ada4c 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -510,7 +510,9 @@ struct hb_job_s #define HB_VCODEC_FFMPEG_VP9 0x0000080 #define HB_VCODEC_FFMPEG_VCE_H264 0x00040000 #define HB_VCODEC_FFMPEG_VCE_H265 0x00080000 -#define HB_VCODEC_FFMPEG_MASK (0x00000F0|HB_VCODEC_FFMPEG_VCE_H264|HB_VCODEC_FFMPEG_VCE_H265) +#define HB_VCODEC_FFMPEG_NVENC_H264 0x00160000 +#define HB_VCODEC_FFMPEG_NVENC_H265 0x00320000 +#define HB_VCODEC_FFMPEG_MASK (0x00000F0|HB_VCODEC_FFMPEG_VCE_H264|HB_VCODEC_FFMPEG_VCE_H265|HB_VCODEC_FFMPEG_NVENC_H264|HB_VCODEC_FFMPEG_NVENC_H265) #define HB_VCODEC_QSV_H264 0x0000100 #define HB_VCODEC_QSV_H265_8BIT 0x0000200 #define HB_VCODEC_QSV_H265_10BIT 0x0000400 @@ -521,14 +523,14 @@ struct hb_job_s #define HB_VCODEC_X264 HB_VCODEC_X264_8BIT #define HB_VCODEC_X264_10BIT 0x0020000 #define HB_VCODEC_X264_MASK 0x0030000 -#define HB_VCODEC_H264_MASK (HB_VCODEC_X264_MASK|HB_VCODEC_QSV_H264|HB_VCODEC_FFMPEG_VCE_H264) +#define HB_VCODEC_H264_MASK (HB_VCODEC_X264_MASK|HB_VCODEC_QSV_H264|HB_VCODEC_FFMPEG_VCE_H264|HB_VCODEC_FFMPEG_NVENC_H264) #define HB_VCODEC_X265_8BIT 0x0001000 #define HB_VCODEC_X265 HB_VCODEC_X265_8BIT #define HB_VCODEC_X265_10BIT 0x0002000 #define HB_VCODEC_X265_12BIT 0x0004000 #define HB_VCODEC_X265_16BIT 0x0008000 #define HB_VCODEC_X265_MASK 0x000F000 -#define HB_VCODEC_H265_MASK (HB_VCODEC_X265_MASK|HB_VCODEC_QSV_H265_MASK|HB_VCODEC_FFMPEG_VCE_H265) +#define HB_VCODEC_H265_MASK (HB_VCODEC_X265_MASK|HB_VCODEC_QSV_H265_MASK|HB_VCODEC_FFMPEG_VCE_H265|HB_VCODEC_FFMPEG_NVENC_H265) /* define an invalid CQ value compatible with all CQ-capable codecs */ #define HB_INVALID_VIDEO_QUALITY (-1000.) diff --git a/libhb/encavcodec.c b/libhb/encavcodec.c index ee914faba..17a6fdb25 100644 --- a/libhb/encavcodec.c +++ b/libhb/encavcodec.c @@ -68,6 +68,22 @@ static const char * const vpx_preset_names[] = "veryfast", "faster", "fast", "medium", "slow", "slower", "veryslow", NULL }; +static const char * const h26x_nvenc_preset_names[] = +{ + "losslesshp", "lossless", "llhp", "llhq", "ll", "bd", "hq", "hp", "fast", "medium", "slow", "default", NULL +}; + +static const char * const h264_nvenc_profile_names[] = +{ + "auto", "baseline", "main", "high", NULL // "high444p" not supported. +}; + +static const char * const h265_nvenc_profile_names[] = +{ + "auto", "main", "main10", "rext", NULL +}; + + int encavcodecInit( hb_work_object_t * w, hb_job_t * job ) { int ret = 0; @@ -75,6 +91,7 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job ) AVCodec * codec; AVCodecContext * context; AVRational fps; + int64_t bit_rate_ceiling = -1; hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) ); w->private_data = pv; @@ -110,13 +127,29 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job ) } break; case AV_CODEC_ID_H264: { - hb_log("encavcodecInit: H.264 (AMD VCE)"); - codec = avcodec_find_encoder_by_name("h264_amf"); + switch (job->vcodec) { + case HB_VCODEC_FFMPEG_NVENC_H264: + hb_log("encavcodecInit: H.264 (Nvidia NVENC)"); + codec = avcodec_find_encoder_by_name("h264_nvenc"); + break; + case HB_VCODEC_FFMPEG_VCE_H264: + hb_log("encavcodecInit: H.264 (AMD VCE)"); + codec = avcodec_find_encoder_by_name("h264_amf"); + break; + } }break; case AV_CODEC_ID_HEVC: { - hb_log("encavcodecInit: H.265 (AMD VCE)"); - codec = avcodec_find_encoder_by_name("hevc_amf"); + switch (job->vcodec) { + case HB_VCODEC_FFMPEG_NVENC_H265: + hb_log("encavcodecInit: H.265 (Nvidia NVENC)"); + codec = avcodec_find_encoder_by_name("hevc_nvenc"); + break; + case HB_VCODEC_FFMPEG_VCE_H264: + hb_log("encavcodecInit: H.265 (AMD VCE)"); + codec = avcodec_find_encoder_by_name("hevc_amf"); + break; + } }break; default: { @@ -213,6 +246,8 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job ) lavc_opts = hb_encopts_to_dict(job->encoder_options, job->vcodec); } + bit_rate_ceiling = (int64_t)job->width * (int64_t)job->height * (int64_t)fps.num / (int64_t)fps.den; + if (job->vquality != HB_INVALID_VIDEO_QUALITY) { if ( w->codec_param == AV_CODEC_ID_VP8 || @@ -221,7 +256,7 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job ) //This value was chosen to make the bitrate high enough //for libvpx to "turn off" the maximum bitrate feature //that is normally applied to constant quality. - context->bit_rate = job->width * job->height * fps.num / fps.den; + context->bit_rate = bit_rate_ceiling; } } @@ -263,14 +298,16 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job ) else { /* Constant quantizer */ - // These settings produce better image quality than - // what was previously used - context->flags |= AV_CODEC_FLAG_QSCALE; - context->global_quality = FF_QP2LAMBDA * job->vquality + 0.5; + //Set constant quality for libvpx if ( w->codec_param == AV_CODEC_ID_VP8 || w->codec_param == AV_CODEC_ID_VP9 ) { + // These settings produce better image quality than + // what was previously used + context->flags |= AV_CODEC_FLAG_QSCALE; + context->global_quality = FF_QP2LAMBDA * job->vquality + 0.5; + char quality[7]; snprintf(quality, 7, "%.2f", job->vquality); av_dict_set( &av_opts, "crf", quality, 0 ); @@ -280,8 +317,40 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job ) context->bit_rate = job->width * job->height * fps.num / fps.den; hb_log( "encavcodec: encoding at CQ %.2f", job->vquality ); } + //Set constant quality for nvenc + else if ( job->vcodec == HB_VCODEC_FFMPEG_NVENC_H264 || + job->vcodec == HB_VCODEC_FFMPEG_NVENC_H265 ) + { + char quality[7]; + snprintf(quality, 7, "%.2f", job->vquality); + av_dict_set( &av_opts, "rc", "vbr", 0 ); + av_dict_set( &av_opts, "cq", quality, 0 ); + + // further Advanced Quality Settings in Constant Quality Mode + av_dict_set( &av_opts, "init_qpP", "1", 0 ); + av_dict_set( &av_opts, "init_qpB", "1", 0 ); + av_dict_set( &av_opts, "init_qpI", "1", 0 ); + av_dict_set( &av_opts, "rc-lookahead", "16", 0 ); // also adds b-frames (h264 only it seems for now), max 32 causes errors + if( job->vcodec == HB_VCODEC_FFMPEG_NVENC_H265 ) { + av_dict_set( &av_opts, "spatial_aq", "1", 0 ); // oops, nvenc_hevc.c uses an underscore + } else { + av_dict_set( &av_opts, "spatial-aq", "1", 0 ); // oops, nvenc_h264.c uses a dash + } + hb_log( "encavcodec: encoding at rc=vbr CQ %.2f, init_qp 1, rc-lookahead 16, spatial_aq 1, aq-strength default", job->vquality ); + + //This value was chosen to make the bitrate high enough + //for nvenc to "turn off" the maximum bitrate feature + //that is normally applied to constant quality. + context->bit_rate = bit_rate_ceiling; + hb_log( "encavcodec: bit_rate.4 %ld", context->bit_rate); + } else { + // These settings produce better image quality than + // what was previously used + context->flags |= AV_CODEC_FLAG_QSCALE; + context->global_quality = FF_QP2LAMBDA * job->vquality + 0.5; + hb_log( "encavcodec: encoding at constant quantizer %d", context->global_quality ); } @@ -841,6 +910,10 @@ static int apply_encoder_preset(int vcodec, AVDictionary ** av_opts, case HB_VCODEC_FFMPEG_VP8: case HB_VCODEC_FFMPEG_VP9: return apply_vpx_preset(av_opts, preset); + case HB_VCODEC_FFMPEG_NVENC_H264: + case HB_VCODEC_FFMPEG_NVENC_H265: + av_dict_set( av_opts, "preset", preset, 0); + break; default: break; } @@ -860,7 +933,25 @@ const char* const* hb_av_preset_get_names(int encoder) case HB_VCODEC_FFMPEG_VCE_H265: return hb_vce_preset_names; + case HB_VCODEC_FFMPEG_NVENC_H264: + case HB_VCODEC_FFMPEG_NVENC_H265: + return h26x_nvenc_preset_names; + default: return NULL; } } + +const char* const* hb_av_profile_get_names(int encoder) +{ + switch (encoder) + { + case HB_VCODEC_FFMPEG_NVENC_H264: + return h264_nvenc_profile_names; + case HB_VCODEC_FFMPEG_NVENC_H265: + return h265_nvenc_profile_names; + + default: + return NULL; + } +} diff --git a/libhb/hbffmpeg.h b/libhb/hbffmpeg.h index b0aeba8b3..af0476586 100644 --- a/libhb/hbffmpeg.h +++ b/libhb/hbffmpeg.h @@ -45,4 +45,9 @@ static const char* const hb_vce_preset_names[] = { "speed", "balanced", "quality hb_buffer_t * hb_avframe_to_video_buffer(AVFrame *frame, AVRational time_base); void hb_avframe_set_video_buffer_flags(hb_buffer_t * buf, AVFrame *frame, AVRational time_base); + +int hb_av_encoder_present(int encoder); +const char* const* hb_av_profile_get_names(int encoder); +const char* const* hb_av_level_get_names(int encoder); + #endif diff --git a/libhb/module.defs b/libhb/module.defs index bc760b308..25f9b170c 100644 --- a/libhb/module.defs +++ b/libhb/module.defs @@ -86,6 +86,10 @@ ifeq (1,$(FEATURE.vce)) LIBHB.GCC.D += USE_VCE endif +ifeq (1,$(FEATURE.nvenc)) + LIBHB.GCC.D += USE_NVENC +endif + ifeq (1,$(FEATURE.x265)) LIBHB.GCC.D += USE_X265 endif diff --git a/libhb/muxavformat.c b/libhb/muxavformat.c index f1053f7ea..65d706565 100644 --- a/libhb/muxavformat.c +++ b/libhb/muxavformat.c @@ -208,6 +208,7 @@ static int avformatInit( hb_mux_object_t * m ) case HB_VCODEC_X264_10BIT: case HB_VCODEC_QSV_H264: case HB_VCODEC_FFMPEG_VCE_H264: + case HB_VCODEC_FFMPEG_NVENC_H264: track->st->codecpar->codec_id = AV_CODEC_ID_H264; if (job->mux == HB_MUX_AV_MP4 && job->inline_parameter_sets) { @@ -334,6 +335,7 @@ static int avformatInit( hb_mux_object_t * m ) case HB_VCODEC_QSV_H265: case HB_VCODEC_QSV_H265_10BIT: case HB_VCODEC_FFMPEG_VCE_H265: + case HB_VCODEC_FFMPEG_NVENC_H265: track->st->codecpar->codec_id = AV_CODEC_ID_HEVC; if (job->mux == HB_MUX_AV_MP4 && job->inline_parameter_sets) { diff --git a/libhb/nvenc_common.c b/libhb/nvenc_common.c new file mode 100644 index 000000000..6d1fcead6 --- /dev/null +++ b/libhb/nvenc_common.c @@ -0,0 +1,57 @@ +/* nvenc_common.c + * + * Copyright (c) 2003-2018 HandBrake Team + * This file is part of the HandBrake source code. + * Homepage: <http://handbrake.fr/>. + * It may be used under the terms of the GNU General Public License v2. + * For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html + */ + +#include "hbffmpeg.h" + +#ifdef USE_NVENC +#include <ffnvcodec/nvEncodeAPI.h> +#include <ffnvcodec/dynlink_loader.h> +#endif + +int hb_nvenc_h264_available() +{ + #ifdef USE_NVENC + return hb_check_nvenc_available(); + #else + return 0; + #endif +} + +int hb_nvenc_h265_available() +{ + #ifdef USE_NVENC + return hb_check_nvenc_available(); + #else + return 0; + #endif +} + +int hb_check_nvenc_available() +{ + #ifdef USE_NVENC + uint32_t nvenc_ver; + void *context; + NvencFunctions *nvenc_dl; + + int loadErr = nvenc_load_functions(&nvenc_dl, context); + if (loadErr < 0) { + return 0; + } + + NVENCSTATUS apiErr = nvenc_dl->NvEncodeAPIGetMaxSupportedVersion(&nvenc_ver); + if (apiErr != NV_ENC_SUCCESS) + { + return 0; + } + + return 1; + #else + return 0; + #endif +} diff --git a/libhb/nvenc_common.h b/libhb/nvenc_common.h new file mode 100644 index 000000000..cb58d5489 --- /dev/null +++ b/libhb/nvenc_common.h @@ -0,0 +1,11 @@ +/* nvenc_common.h + * + * Copyright (c) 2003-2018 HandBrake Team + * This file is part of the HandBrake source code. + * Homepage: <http://handbrake.fr/>. + * It may be used under the terms of the GNU General Public License v2. + * For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html + */ + +int hb_nvenc_h264_available(); +int hb_nvenc_h265_available(); diff --git a/libhb/work.c b/libhb/work.c index 1400fee1f..22825840a 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -253,6 +253,17 @@ hb_work_object_t* hb_video_encoder(hb_handle_t *h, int vcodec) w->codec_param = AV_CODEC_ID_HEVC; break; #endif +#ifdef USE_NVENC + case HB_VCODEC_FFMPEG_NVENC_H264: + w = hb_get_work(h, WORK_ENCAVCODEC); + w->codec_param = AV_CODEC_ID_H264; + break; + case HB_VCODEC_FFMPEG_NVENC_H265: + w = hb_get_work(h, WORK_ENCAVCODEC); + w->codec_param = AV_CODEC_ID_HEVC; + break; +#endif + default: hb_error("Unknown video codec (0x%x)", vcodec ); } @@ -486,6 +497,8 @@ void hb_display_job_info(hb_job_t *job) case HB_VCODEC_QSV_H265_10BIT: case HB_VCODEC_FFMPEG_VCE_H264: case HB_VCODEC_FFMPEG_VCE_H265: + case HB_VCODEC_FFMPEG_NVENC_H264: + case HB_VCODEC_FFMPEG_NVENC_H265: hb_log(" + profile: %s", job->encoder_profile); default: break; @@ -502,6 +515,8 @@ void hb_display_job_info(hb_job_t *job) case HB_VCODEC_QSV_H265_10BIT: case HB_VCODEC_FFMPEG_VCE_H264: case HB_VCODEC_FFMPEG_VCE_H265: + case HB_VCODEC_FFMPEG_NVENC_H264: + case HB_VCODEC_FFMPEG_NVENC_H265: hb_log(" + level: %s", job->encoder_level); default: break; diff --git a/make/configure.py b/make/configure.py index abe6abe47..4ec254fa6 100644 --- a/make/configure.py +++ b/make/configure.py @@ -1319,6 +1319,10 @@ def createCLI(): grp.add_option( '--enable-ffmpeg-aac', dest="enable_ffmpeg_aac", default=not host.match( '*-*-darwin*' ), action='store_true', help=h ) grp.add_option( '--disable-ffmpeg-aac', dest="enable_ffmpeg_aac", action='store_false' ) + h = IfHost( 'enable Nvidia NVEnc video encoder', '*-*-*', none=optparse.SUPPRESS_HELP ).value + grp.add_option( '--enable-nvenc', dest="enable_nvenc", default=not host.match( '*-*-darwin*' ), action='store_true', help=h ) + + cli.add_option_group( grp ) ## add launch options @@ -1845,6 +1849,7 @@ int main() doc.add( 'FEATURE.vce', int( options.enable_vce )) doc.add( 'FEATURE.xcode', int( not (Tools.xcodebuild.fail or options.disable_xcode or options.cross) )) doc.add( 'FEATURE.x265', int( options.enable_x265 )) + doc.add( 'FEATURE.nvenc', int( options.enable_nvenc )) if not Tools.xcodebuild.fail and not options.disable_xcode: doc.addBlank() diff --git a/make/include/main.defs b/make/include/main.defs index dac1985e9..d56b752d4 100644 --- a/make/include/main.defs +++ b/make/include/main.defs @@ -70,6 +70,10 @@ ifeq (1,$(FEATURE.vce)) MODULES += contrib/amf endif +ifeq (1,$(FEATURE.nvenc)) + MODULES += contrib/nvenc +endif + ifneq (,$(filter $(BUILD.system),darwin)) MODULES += contrib/xz endif diff --git a/test/module.defs b/test/module.defs index 85b13793d..11ac8a7ff 100644 --- a/test/module.defs +++ b/test/module.defs @@ -34,6 +34,10 @@ ifeq (1,$(FEATURE.vce)) TEST.GCC.D += USE_VCE endif +ifeq (1,$(FEATURE.nvenc)) + TEST.GCC.D += USE_NVENC +endif + ifeq (1,$(FEATURE.x265)) TEST.GCC.D += USE_X265 endif diff --git a/win/CS/HandBrake.Interop/Interop/HbLib/HbFunctions.cs b/win/CS/HandBrake.Interop/Interop/HbLib/HbFunctions.cs index 65b81c509..8e36dc6c6 100644 --- a/win/CS/HandBrake.Interop/Interop/HbLib/HbFunctions.cs +++ b/win/CS/HandBrake.Interop/Interop/HbLib/HbFunctions.cs @@ -415,6 +415,12 @@ namespace HandBrake.Interop.Interop.HbLib [DllImport("hb", EntryPoint = "hb_vce_h265_available", CallingConvention = CallingConvention.Cdecl)] public static extern int hb_vce_h265_available(); + [DllImport("hb", EntryPoint = "hb_nvenc_h264_available", CallingConvention = CallingConvention.Cdecl)] + public static extern int hb_nvenc_h264_available(); + + [DllImport("hb", EntryPoint = "hb_nvenc_h265_available", CallingConvention = CallingConvention.Cdecl)] + public static extern int hb_nvenc_h265_available(); + // hb_image_t* hb_get_preview2(hb_handle_t* h, int title_idx, int picture, hb_geometry_settings_t* geo, int deinterlace); [DllImport("hb", EntryPoint = "hb_get_preview2", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr hb_get_preview2(IntPtr hbHandle, int title_idx, int preview_idx, ref hb_geometry_settings_s geo, int deinterlace); diff --git a/win/CS/HandBrake.Interop/Interop/Model/Encoding/VideoEncoder.cs b/win/CS/HandBrake.Interop/Interop/Model/Encoding/VideoEncoder.cs index a5aded796..e8a2ed485 100644 --- a/win/CS/HandBrake.Interop/Interop/Model/Encoding/VideoEncoder.cs +++ b/win/CS/HandBrake.Interop/Interop/Model/Encoding/VideoEncoder.cs @@ -30,8 +30,12 @@ namespace HandBrake.Interop.Interop.Model.Encoding [DisplayName("H.264 (AMD VCE)")] [ShortName("vce_h264")] - VceH264, + VceH264, + [DisplayName("H.264 (Nvidia NVEnc)")] + [ShortName("nvenc_h264")] + NvencH264, + [DisplayName("MPEG-4")] [ShortName("mpeg4")] FFMpeg, @@ -68,6 +72,10 @@ namespace HandBrake.Interop.Interop.Model.Encoding [ShortName("vce_h265")] VceH265, + [DisplayName("H.265 (Nvidia NVEnc)")] + [ShortName("nvenc_h265")] + NvencH265, + [DisplayName("VP8")] [ShortName("VP8")] VP8, diff --git a/win/CS/HandBrake.Interop/Utilities/SystemInfo.cs b/win/CS/HandBrake.Interop/Utilities/SystemInfo.cs index a364c50ac..454132b53 100644 --- a/win/CS/HandBrake.Interop/Utilities/SystemInfo.cs +++ b/win/CS/HandBrake.Interop/Utilities/SystemInfo.cs @@ -18,6 +18,9 @@ namespace HandBrake.Interop.Utilities /// </summary> public class SystemInfo { + private static bool? isNvencH264Available; // Local cache to prevent log spam. + private static bool? isNvencH265Available; + /// <summary> /// Gets a value indicating whether is qsv available. /// </summary> @@ -122,5 +125,52 @@ namespace HandBrake.Interop.Utilities } } } + + public static bool IsNVEncH264Available + { + get + { + try + { + if (isNvencH264Available == null) + { + isNvencH264Available = HBFunctions.hb_nvenc_h264_available() != 0; + } + + return isNvencH264Available.Value; + } + catch (Exception) + { + // Silent failure. Typically this means the dll hasn't been built with --enable-qsv + return false; + } + } + } + + public static bool IsNVEncH265Available + { + get + { + try + { + if (!IsNVEncH264Available) + { + return false; + } + + if (isNvencH265Available == null) + { + isNvencH265Available = HBFunctions.hb_nvenc_h265_available() != 0; + } + + return isNvencH265Available.Value; + } + catch (Exception) + { + // Silent failure. Typically this means the dll hasn't been built with --enable-qsv + return false; + } + } + } } } diff --git a/win/CS/HandBrakeWPF/Converters/Video/VideoEncoderConverter.cs b/win/CS/HandBrakeWPF/Converters/Video/VideoEncoderConverter.cs index 42ccf1c10..40131ddb3 100644 --- a/win/CS/HandBrakeWPF/Converters/Video/VideoEncoderConverter.cs +++ b/win/CS/HandBrakeWPF/Converters/Video/VideoEncoderConverter.cs @@ -101,6 +101,16 @@ namespace HandBrakeWPF.Converters.Video encoders.Remove(VideoEncoder.VceH265);
}
+ if (!SystemInfo.IsNVEncH264Available)
+ {
+ encoders.Remove(VideoEncoder.NvencH264);
+ }
+
+ if (!SystemInfo.IsNVEncH265Available)
+ {
+ encoders.Remove(VideoEncoder.NvencH265);
+ }
+
return EnumHelper<VideoEncoder>.GetEnumDisplayValuesSubset(encoders);
}
diff --git a/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs index 4bd5b777d..74ac53a85 100644 --- a/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs @@ -349,6 +349,8 @@ namespace HandBrakeWPF.ViewModels case VideoEncoder.QuickSyncH265:
case VideoEncoder.VceH264:
case VideoEncoder.VceH265:
+ case VideoEncoder.NvencH264:
+ case VideoEncoder.NvencH265:
rfValue = 51.0 - value;
rfValue = Math.Round(rfValue, 0);
this.Task.Quality = rfValue;
@@ -977,7 +979,8 @@ namespace HandBrakeWPF.ViewModels if (preset.Task.VideoEncoder == VideoEncoder.X264 || preset.Task.VideoEncoder == VideoEncoder.X264_10
|| preset.Task.VideoEncoder == VideoEncoder.X265 || preset.Task.VideoEncoder == VideoEncoder.X265_10 || preset.Task.VideoEncoder == VideoEncoder.X265_12
|| preset.Task.VideoEncoder == VideoEncoder.QuickSync || preset.Task.VideoEncoder == VideoEncoder.QuickSyncH265 || preset.Task.VideoEncoder == VideoEncoder.QuickSyncH26510b
- || preset.Task.VideoEncoder == VideoEncoder.VceH264 || preset.Task.VideoEncoder == VideoEncoder.VceH265)
+ || preset.Task.VideoEncoder == VideoEncoder.VceH264 || preset.Task.VideoEncoder == VideoEncoder.VceH265
+ || preset.Task.VideoEncoder == VideoEncoder.NvencH264 || preset.Task.VideoEncoder == VideoEncoder.NvencH265)
{
this.VideoLevel = preset.Task.VideoLevel != null ? preset.Task.VideoLevel.Clone() : this.VideoLevels.FirstOrDefault();
this.VideoProfile = preset.Task.VideoProfile != null ? preset.Task.VideoProfile.Clone() : this.VideoProfiles.FirstOrDefault();
@@ -1090,7 +1093,8 @@ namespace HandBrakeWPF.ViewModels || this.Task.VideoEncoder == VideoEncoder.X265 || this.Task.VideoEncoder == VideoEncoder.X265_10
|| this.Task.VideoEncoder == VideoEncoder.X265_12 || this.Task.VideoEncoder == VideoEncoder.QuickSync
|| this.Task.VideoEncoder == VideoEncoder.QuickSyncH265 || this.Task.VideoEncoder == VideoEncoder.QuickSyncH26510b
- || this.Task.VideoEncoder == VideoEncoder.VceH264 || this.Task.VideoEncoder == VideoEncoder.VceH265)
+ || this.Task.VideoEncoder == VideoEncoder.VceH264 || this.Task.VideoEncoder == VideoEncoder.VceH265
+ || this.Task.VideoEncoder == VideoEncoder.NvencH264 || this.Task.VideoEncoder == VideoEncoder.NvencH265)
{
if (!Equals(preset.Task.VideoPreset, this.Task.VideoPreset))
{
@@ -1183,6 +1187,8 @@ namespace HandBrakeWPF.ViewModels case VideoEncoder.QuickSyncH265:
case VideoEncoder.VceH264:
case VideoEncoder.VceH265:
+ case VideoEncoder.NvencH264:
+ case VideoEncoder.NvencH265:
this.QualityMin = 0;
this.QualityMax = 51;
break;
@@ -1317,9 +1323,12 @@ namespace HandBrakeWPF.ViewModels case VideoEncoder.QuickSyncH26510b:
case VideoEncoder.VceH264:
case VideoEncoder.VceH265:
+ case VideoEncoder.NvencH264:
+ case VideoEncoder.NvencH265:
if (this.SelectedVideoEncoder == VideoEncoder.QuickSync || this.SelectedVideoEncoder == VideoEncoder.QuickSyncH265 || this.SelectedVideoEncoder == VideoEncoder.QuickSyncH26510b
- || this.SelectedVideoEncoder == VideoEncoder.VceH264 || this.SelectedVideoEncoder == VideoEncoder.VceH265)
+ || this.SelectedVideoEncoder == VideoEncoder.VceH264 || this.SelectedVideoEncoder == VideoEncoder.VceH265
+ || this.SelectedVideoEncoder == VideoEncoder.NvencH264 || this.SelectedVideoEncoder == VideoEncoder.NvencH265)
{
cqStep = 1;
}
@@ -1441,12 +1450,15 @@ namespace HandBrakeWPF.ViewModels // Update control display
this.UseAdvancedTab = selectedEncoder != VideoEncoder.QuickSync && selectedEncoder != VideoEncoder.QuickSyncH265 && selectedEncoder != VideoEncoder.QuickSyncH26510b
- && selectedEncoder != VideoEncoder.VceH264 && selectedEncoder != VideoEncoder.VceH265 && this.UseAdvancedTab;
+ && selectedEncoder != VideoEncoder.VceH264 && selectedEncoder != VideoEncoder.VceH265
+ && selectedEncoder != VideoEncoder.NvencH264 && selectedEncoder != VideoEncoder.NvencH265
+ && this.UseAdvancedTab;
this.DisplayOptimiseOptions = this.SelectedVideoEncoder == VideoEncoder.X264 || this.SelectedVideoEncoder == VideoEncoder.X264_10 ||
this.SelectedVideoEncoder == VideoEncoder.X265 || this.SelectedVideoEncoder == VideoEncoder.X265_10 || this.SelectedVideoEncoder == VideoEncoder.X265_12 ||
this.SelectedVideoEncoder == VideoEncoder.QuickSync || this.SelectedVideoEncoder == VideoEncoder.QuickSyncH265 || this.SelectedVideoEncoder == VideoEncoder.QuickSyncH26510b ||
this.SelectedVideoEncoder == VideoEncoder.VceH264 || this.SelectedVideoEncoder == VideoEncoder.VceH265 ||
+ this.SelectedVideoEncoder == VideoEncoder.NvencH264 || this.SelectedVideoEncoder == VideoEncoder.NvencH265 ||
this.SelectedVideoEncoder == VideoEncoder.VP8 || this.SelectedVideoEncoder == VideoEncoder.VP9;
this.DisplayNonQSVControls = this.SelectedVideoEncoder != VideoEncoder.QuickSync && this.SelectedVideoEncoder != VideoEncoder.QuickSyncH265 && this.SelectedVideoEncoder != VideoEncoder.QuickSyncH26510b;
@@ -1459,7 +1471,8 @@ namespace HandBrakeWPF.ViewModels this.DisplayLevelControl = this.SelectedVideoEncoder == VideoEncoder.X264 || this.SelectedVideoEncoder == VideoEncoder.X264_10 ||
this.SelectedVideoEncoder == VideoEncoder.QuickSync || this.SelectedVideoEncoder == VideoEncoder.QuickSyncH265 || this.SelectedVideoEncoder == VideoEncoder.QuickSyncH26510b ||
- this.SelectedVideoEncoder == VideoEncoder.VceH264 || this.SelectedVideoEncoder == VideoEncoder.VceH265;
+ this.SelectedVideoEncoder == VideoEncoder.VceH264 || this.SelectedVideoEncoder == VideoEncoder.VceH265 ||
+ this.SelectedVideoEncoder == VideoEncoder.NvencH264 || this.SelectedVideoEncoder == VideoEncoder.NvencH265;
this.DisplayProfileControl = this.SelectedVideoEncoder == VideoEncoder.X264
|| this.SelectedVideoEncoder == VideoEncoder.X264_10
@@ -1470,7 +1483,9 @@ namespace HandBrakeWPF.ViewModels || this.SelectedVideoEncoder == VideoEncoder.QuickSyncH265
|| this.SelectedVideoEncoder == VideoEncoder.QuickSyncH26510b
|| this.SelectedVideoEncoder == VideoEncoder.VceH264
- || this.SelectedVideoEncoder == VideoEncoder.VceH265;
+ || this.SelectedVideoEncoder == VideoEncoder.VceH265
+ || this.SelectedVideoEncoder == VideoEncoder.NvencH264
+ || this.SelectedVideoEncoder == VideoEncoder.NvencH265;
// Refresh Display
this.NotifyOfPropertyChange(() => this.Rfqp);
|