Skip to content

Commit

Permalink
hwaccel: enable DirectX11 decoding support for snapdragon devices (Ha…
Browse files Browse the repository at this point in the history
  • Loading branch information
dashsantosh-mcw authored Aug 6, 2024
1 parent ecb0687 commit 4546b29
Show file tree
Hide file tree
Showing 20 changed files with 154 additions and 4 deletions.
4 changes: 4 additions & 0 deletions contrib/ffmpeg/module.defs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,10 @@ endif

ifeq (1,$(FEATURE.mf))
FFMPEG.CONFIGURE.extra += \
--enable-hwaccel=h264_d3d11va \
--enable-hwaccel=hevc_d3d11va \
--enable-hwaccel=h264_d3d11va2 \
--enable-hwaccel=hevc_d3d11va2 \
--enable-encoder=h264_mf \
--enable-encoder=hevc_mf
endif
Expand Down
10 changes: 9 additions & 1 deletion libhb/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,9 @@ static void hb_common_global_hw_init()
#endif
#if HB_PROJECT_FEATURE_VCE
hb_vce_h264_available();
#endif
#if HB_PROJECT_FEATURE_MF
hb_directx_available();
#endif
// first initialization and QSV adapters list collection should happen after other hw vendors initializations to prevent device order issues
#if HB_PROJECT_FEATURE_QSV
Expand Down Expand Up @@ -6720,14 +6723,19 @@ static int pix_hw_fmt_is_supported(hb_job_t *job, int pix_fmt)
{
return 1;
}
if (pix_fmt == AV_PIX_FMT_D3D11 &&
job->hw_decode & HB_DECODE_SUPPORT_MF)
{
return 1;
}
}

return 0;
}

static const enum AVPixelFormat hw_pipeline_pix_fmts[] =
{
AV_PIX_FMT_QSV, AV_PIX_FMT_CUDA, AV_PIX_FMT_VIDEOTOOLBOX, AV_PIX_FMT_NONE
AV_PIX_FMT_QSV, AV_PIX_FMT_CUDA, AV_PIX_FMT_VIDEOTOOLBOX, AV_PIX_FMT_D3D11, AV_PIX_FMT_NONE
};

int hb_get_best_hw_pix_fmt(hb_job_t *job)
Expand Down
8 changes: 8 additions & 0 deletions libhb/decavcodec.c
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,10 @@ static void closePrivData( hb_work_private_t ** ppv )
}
if ( pv->context )
{
if (pv->context->hw_device_ctx)
{
av_buffer_unref(&pv->context->hw_device_ctx);
}
hb_avcodec_free_context(&pv->context);
}
av_packet_free(&pv->pkt);
Expand Down Expand Up @@ -2497,6 +2501,10 @@ static int decavcodecvInfo( hb_work_object_t *w, hb_work_info_t *info )
{
info->video_decode_support |= HB_DECODE_SUPPORT_VIDEOTOOLBOX;
}
else if (pv->context->pix_fmt == AV_PIX_FMT_D3D11)
{
info->video_decode_support |= HB_DECODE_SUPPORT_MF;
}

return 1;
}
Expand Down
3 changes: 2 additions & 1 deletion libhb/handbrake/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -1246,8 +1246,9 @@ struct hb_title_s
#define HB_DECODE_SUPPORT_QSV 0x02 // Intel Quick Sync Video
#define HB_DECODE_SUPPORT_NVDEC 0x04
#define HB_DECODE_SUPPORT_VIDEOTOOLBOX 0x08
#define HB_DECODE_SUPPORT_MF 0x10 // Windows Media Foundation

#define HB_DECODE_SUPPORT_HWACCEL (HB_DECODE_SUPPORT_NVDEC | HB_DECODE_SUPPORT_VIDEOTOOLBOX)
#define HB_DECODE_SUPPORT_HWACCEL (HB_DECODE_SUPPORT_NVDEC | HB_DECODE_SUPPORT_VIDEOTOOLBOX | HB_DECODE_SUPPORT_MF)
#define HB_DECODE_SUPPORT_FORCE_HW 0x80000000

hb_metadata_t * metadata;
Expand Down
2 changes: 2 additions & 0 deletions libhb/handbrake/hwaccel.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

#include "handbrake/hbffmpeg.h"

int hb_directx_available();

enum AVPixelFormat hw_hwaccel_get_hw_format(AVCodecContext *ctx, const enum AVPixelFormat *pix_fmts);

int hb_hwaccel_hw_ctx_init(int codec_id, int hw_decode, void **hw_device_ctx);
Expand Down
30 changes: 30 additions & 0 deletions libhb/hwaccel.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ int hb_hwaccel_hw_ctx_init(int codec_id, int hw_decode, void **hw_device_ctx)
{
hw_type = av_hwdevice_find_type_by_name("cuda");
}
else if (hw_decode & HB_DECODE_SUPPORT_MF)
{
hw_type = av_hwdevice_find_type_by_name("d3d11va");
}

if (hw_type != AV_HWDEVICE_TYPE_NONE)
{
Expand Down Expand Up @@ -313,3 +317,29 @@ int hb_hwaccel_decode_is_enabled(hb_job_t *job)
return 0;
}
}

#if HB_PROJECT_FEATURE_MF
int hb_directx_available()
{
if (is_hardware_disabled())
{
return 0;
}
enum AVHWDeviceType hw_type = av_hwdevice_find_type_by_name("d3d11va");
if (hw_type == AV_HWDEVICE_TYPE_NONE)
{
hb_log("directx: not available on this system");
return 0;
}

hb_log("directx: is available");
return 1;
}
#else // HB_PROJECT_FEATURE_MF

int hb_directx_available()
{
return -1;
}

#endif // HB_PROJECT_FEATURE_MF
5 changes: 5 additions & 0 deletions libhb/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,11 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title, int flush )
{
hw_decode = HB_DECODE_SUPPORT_VIDEOTOOLBOX;
}
else if (data->hw_decode & HB_DECODE_SUPPORT_MF &&
hb_hwaccel_available(title->video_codec_param, "d3d11va"))
{
hw_decode = HB_DECODE_SUPPORT_MF;
}

void *hw_device_ctx = NULL;
if (hw_decode)
Expand Down
4 changes: 4 additions & 0 deletions libhb/work.c
Original file line number Diff line number Diff line change
Expand Up @@ -1683,6 +1683,10 @@ static void do_job(hb_job_t *job)
{
job->hw_decode = 0;
}
if (job->hw_decode == HB_DECODE_SUPPORT_MF)
{
job->hw_decode |= HB_DECODE_SUPPORT_FORCE_HW;
}

// This must be performed before initializing filters because
// it can add the subtitle render filter.
Expand Down
4 changes: 4 additions & 0 deletions test/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -3219,6 +3219,10 @@ static int ParseOptions( int argc, char ** argv )
}
#endif
}
else if (!strcmp(optarg, "mf"))
{
hw_decode = HB_DECODE_SUPPORT_MF;
}
else
{
hw_decode = 0;
Expand Down
26 changes: 26 additions & 0 deletions win/CS/HandBrake.Interop/Interop/HandBrakeHardwareEncoderHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public class HandBrakeHardwareEncoderHelper
private static int? qsvHardwareGeneration;
private static bool? isQsvAvailable;

private static bool? isDirectXAvailable;

private static bool? isSafeMode;

public static bool IsSafeMode
Expand Down Expand Up @@ -225,6 +227,30 @@ public static bool IsQsvAvailableAV110bit
}
}
}

/* DirectX Support */

public static bool IsDirectXAvailable
{
get
{
try
{
if (isDirectXAvailable != null)
{
return isDirectXAvailable.Value;
}

isDirectXAvailable = HBFunctions.hb_directx_available() > 0;

return isDirectXAvailable.Value;
}
catch (Exception)
{
return false;
}
}
}

/* AMD VCE Support */

Expand Down
3 changes: 3 additions & 0 deletions win/CS/HandBrake.Interop/Interop/HbLib/HbFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,9 @@ [In] [MarshalAs(UnmanagedType.LPStr)] string h264_level,
int width,
int height);

[DllImport("hb", EntryPoint = "hb_directx_available", CallingConvention = CallingConvention.Cdecl)]
public static extern int hb_directx_available();

[DllImport("hb", EntryPoint = "hb_qsv_available", CallingConvention = CallingConvention.Cdecl)]
public static extern int hb_qsv_available();

Expand Down
3 changes: 2 additions & 1 deletion win/CS/HandBrake.Interop/Interop/HbLib/NativeConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ public class NativeConstants
public const uint HB_DECODE_SUPPORT_QSV = 0x02;
public const uint HB_DECODE_SUPPORT_NVDEC = 0x04;
public const uint HB_DECODE_SUPPORT_VIDEOTOOLBOX = 0x08;
public const uint HB_DECODE_SUPPORT_MF = 0x10;

public const uint HB_DECODE_SUPPORT_HWACCEL = (HB_DECODE_SUPPORT_NVDEC | HB_DECODE_SUPPORT_VIDEOTOOLBOX);
public const uint HB_DECODE_SUPPORT_HWACCEL = (HB_DECODE_SUPPORT_NVDEC | HB_DECODE_SUPPORT_VIDEOTOOLBOX | HB_DECODE_SUPPORT_MF);
}
}
9 changes: 9 additions & 0 deletions win/CS/HandBrakeWPF/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions win/CS/HandBrakeWPF/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1125,6 +1125,9 @@ Hint: File overwrite behaviour can be controlled in preferences. </value>
<data name="OptionsView_EnableNvencEncoding" xml:space="preserve">
<value>Allow use of the Nvidia NVENC Encoders</value>
</data>
<data name="OptionsView_EnableDirectXDecoding" xml:space="preserve">
<value>Allow use of DirectX Decoding</value>
</data>
<data name="OptionsView_EnableQuicksyncEncoding" xml:space="preserve">
<value>Allow use of the Intel QuickSync Encoders</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,17 @@ private Source CreateSource(EncodeTask job)
}

bool nvdec = this.userSettingService.GetUserSetting<bool>(UserSettingConstants.EnableNvDecSupport);
bool directx = this.userSettingService.GetUserSetting<bool>(UserSettingConstants.EnableDirectXDecoding);

int hwDecode = 0;
if (nvdec)
{
hwDecode = (int)NativeConstants.HB_DECODE_SUPPORT_NVDEC;
}
if (directx)
{
hwDecode = (int)NativeConstants.HB_DECODE_SUPPORT_MF;
}

bool qsv = this.userSettingService.GetUserSetting<bool>(UserSettingConstants.EnableQuickSyncDecoding);
if (qsv)
Expand Down Expand Up @@ -292,7 +297,13 @@ private Video CreateVideo(EncodeTask job)
if (this.isEncodePath && HandBrakeHardwareEncoderHelper.IsNVDecAvailable && this.userSettingService.GetUserSetting<bool>(UserSettingConstants.EnableNvDecSupport) && job.VideoEncoder.IsNVEnc)
{
video.HardwareDecode = (int)NativeConstants.HB_DECODE_SUPPORT_NVDEC;
}
}

if (this.userSettingService.GetUserSetting<bool>(UserSettingConstants.EnableDirectXDecoding))
{
video.HardwareDecode = (int)NativeConstants.HB_DECODE_SUPPORT_MF;
}


return video;
}
Expand Down
6 changes: 6 additions & 0 deletions win/CS/HandBrakeWPF/Services/Scan/LibScan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -250,11 +250,17 @@ private void ScanSource(List<string> sourcePaths, int title, int previewCount)
List<string> excludedExtensions = this.userSettingService.GetUserSetting<List<string>>(UserSettingConstants.ExcludedExtensions);

bool nvdec = this.userSettingService.GetUserSetting<bool>(UserSettingConstants.EnableNvDecSupport);
bool directx = this.userSettingService.GetUserSetting<bool>(UserSettingConstants.EnableDirectXDecoding);

int hwDecode = 0;
if (nvdec && HandBrakeHardwareEncoderHelper.IsNVDecAvailable)
{
hwDecode = (int)NativeConstants.HB_DECODE_SUPPORT_NVDEC;
}
if (directx)
{
hwDecode = (int)NativeConstants.HB_DECODE_SUPPORT_MF;
}

bool keepDuplicateTitles = this.userSettingService.GetUserSetting<bool>(UserSettingConstants.KeepDuplicateTitles);

Expand Down
1 change: 1 addition & 0 deletions win/CS/HandBrakeWPF/Services/UserSettingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ private Dictionary<string, object> GetDefaults()
defaults.Add(UserSettingConstants.EnableVceEncoder, true);
defaults.Add(UserSettingConstants.EnableNvencEncoder, nvidiaDefaultSetting);
defaults.Add(UserSettingConstants.EnableNvDecSupport, nvidiaDefaultSetting);
defaults.Add(UserSettingConstants.EnableDirectXDecoding, true);
defaults.Add(UserSettingConstants.EnableQuickSyncLowPower, true);

// Advanced
Expand Down
1 change: 1 addition & 0 deletions win/CS/HandBrakeWPF/UserSettingConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public class UserSettingConstants
public const string EnableQuickSyncEncoding = "EnableQuickSyncEncoding";
public const string EnableQuickSyncHyperEncode = "EnableQuickSyncHyperEncode";
public const string EnableVceEncoder = "EnableVceEncoder";
public const string EnableDirectXDecoding = "EnableDirectXDecoding";
public const string EnableNvencEncoder = "EnableNvencEncoder";
public const string UiLanguage = "UiLanguage";
public const string ShowAddAllToQueue = "ShowAddAllToQueue";
Expand Down
20 changes: 20 additions & 0 deletions win/CS/HandBrakeWPF/ViewModels/OptionsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ public class OptionsViewModel : ViewModelBase, IOptionsViewModel
private bool playSoundWhenQueueDone;
private bool enableQuickSyncEncoding;
private bool enableVceEncoder;
private bool enableDirectXDecoding;
private bool enableNvencEncoder;
private InterfaceLanguage selectedLanguage;
private bool showAddSelectionToQueue;
Expand Down Expand Up @@ -972,6 +973,21 @@ public bool EnableVceEncoder
}
}

public bool EnableDirectXDecoding
{
get => this.enableDirectXDecoding;
set
{
if (value == this.enableDirectXDecoding)
{
return;
}

this.enableDirectXDecoding = value;
this.NotifyOfPropertyChange(() => this.EnableDirectXDecoding);
}
}

public bool EnableNvencEncoder
{
get => this.enableNvencEncoder && this.IsNvencAvailable;
Expand Down Expand Up @@ -1073,6 +1089,8 @@ public bool DisplayNvidiaDriverWarning

public bool IsNvencAvailable { get; } = HandBrakeHardwareEncoderHelper.IsNVEncH264Available;

public bool IsDirectXAvailable { get; } = HandBrakeHardwareEncoderHelper.IsDirectXAvailable;

public bool IsUseQsvDecAvailable => this.IsQuickSyncAvailable && this.EnableQuickSyncDecoding;

public bool IsNvdecAvailable => HandBrakeHardwareEncoderHelper.IsNVDecAvailable && this.EnableNvencEncoder;
Expand Down Expand Up @@ -1495,6 +1513,7 @@ public override void OnLoad()
this.EnableVceEncoder = this.userSettingService.GetUserSetting<bool>(UserSettingConstants.EnableVceEncoder);
this.EnableNvencEncoder = this.userSettingService.GetUserSetting<bool>(UserSettingConstants.EnableNvencEncoder);
this.EnableNvDecSupport = this.userSettingService.GetUserSetting<bool>(UserSettingConstants.EnableNvDecSupport);
this.EnableDirectXDecoding = this.userSettingService.GetUserSetting<bool>(UserSettingConstants.EnableDirectXDecoding);

// #############################
// Process
Expand Down Expand Up @@ -1690,6 +1709,7 @@ private void Save()
this.userSettingService.SetUserSetting(UserSettingConstants.EnableVceEncoder, this.EnableVceEncoder);
this.userSettingService.SetUserSetting(UserSettingConstants.EnableNvencEncoder, this.EnableNvencEncoder);
this.userSettingService.SetUserSetting(UserSettingConstants.EnableNvDecSupport, this.EnableNvDecSupport);
this.userSettingService.SetUserSetting(UserSettingConstants.EnableDirectXDecoding, this.EnableDirectXDecoding);
this.userSettingService.SetUserSetting(UserSettingConstants.EnableQuickSyncLowPower, this.EnableQuickSyncLowPower);

/* System and Logging */
Expand Down
3 changes: 3 additions & 0 deletions win/CS/HandBrakeWPF/Views/Options/OptionsHardware.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@

<CheckBox Content="{x:Static Properties:Resources.OptionsView_EnableNvDecSupport}" Margin="25,5,0,0" IsEnabled="{Binding IsNvencAvailable}"
Visibility="{Binding IsNvdecAvailable, Converter={StaticResource boolToVisConverter}}" IsChecked="{Binding EnableNvDecSupport}" />

<!-- DirectX -->
<CheckBox Content="{x:Static Properties:Resources.OptionsView_EnableDirectXDecoding}" Margin="0,25,0,0" IsEnabled="{Binding IsDirectXAvailable}" IsChecked="{Binding EnableDirectXDecoding}" />

</StackPanel>

Expand Down

0 comments on commit 4546b29

Please sign in to comment.