@@ -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
@@ -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
@@ -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)
{
@@ -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
}
@@ -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();
@@ -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;
@@ -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 @@ class Tools:
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()
@@ -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
@@ -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
@@ -415,6 +415,12 @@ public static class HBFunctions
[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);
@@ -30,8 +30,12 @@ public enum VideoEncoder

[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 @@ public enum VideoEncoder
[ShortName("vce_h265")]
VceH265,

[DisplayName("H.265 (Nvidia NVEnc)")]
[ShortName("nvenc_h265")]
NvencH265,

[DisplayName("VP8")]
[ShortName("VP8")]
VP8,
@@ -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 @@ public static bool IsVceH265Available
}
}
}

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;
}
}
}
}
}
@@ -101,6 +101,16 @@ public object Convert(object[] values, Type targetType, object parameter, Cultur
encoders.Remove(VideoEncoder.VceH265);
}

if (!SystemInfo.IsNVEncH264Available)
{
encoders.Remove(VideoEncoder.NvencH264);
}

if (!SystemInfo.IsNVEncH265Available)
{
encoders.Remove(VideoEncoder.NvencH265);
}

return EnumHelper<VideoEncoder>.GetEnumDisplayValuesSubset(encoders);
}

@@ -349,6 +349,8 @@ public int RF
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 @@ public void SetPreset(Preset preset, EncodeTask task)
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 @@ public bool MatchesPreset(Preset preset)
|| 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 @@ private void SetQualitySliderBounds()
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 @@ private void SetRF(double? quality)
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 @@ private void HandleEncoderChange(VideoEncoder selectedEncoder)

// 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 @@ private void HandleEncoderChange(VideoEncoder selectedEncoder)

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 @@ private void HandleEncoderChange(VideoEncoder selectedEncoder)
|| 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);