From e548697a369827b693237270f13451557859fa19 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 26 Jul 2024 00:35:32 -0500 Subject: [PATCH] Move VT decoding support detection into a single base class --- app/app.pro | 1 + app/streaming/video/ffmpeg-renderers/vt.h | 8 ++ .../ffmpeg-renderers/vt_avsamplelayer.mm | 76 +----------------- .../video/ffmpeg-renderers/vt_base.mm | 78 +++++++++++++++++++ .../video/ffmpeg-renderers/vt_metal.mm | 70 +---------------- 5 files changed, 90 insertions(+), 143 deletions(-) create mode 100644 app/streaming/video/ffmpeg-renderers/vt_base.mm diff --git a/app/app.pro b/app/app.pro index 606ab5c8..073d08d2 100644 --- a/app/app.pro +++ b/app/app.pro @@ -398,6 +398,7 @@ macx { message(VideoToolbox renderer selected) SOURCES += \ + streaming/video/ffmpeg-renderers/vt_base.mm \ streaming/video/ffmpeg-renderers/vt_avsamplelayer.mm \ streaming/video/ffmpeg-renderers/vt_metal.mm diff --git a/app/streaming/video/ffmpeg-renderers/vt.h b/app/streaming/video/ffmpeg-renderers/vt.h index 7079f02c..06674080 100644 --- a/app/streaming/video/ffmpeg-renderers/vt.h +++ b/app/streaming/video/ffmpeg-renderers/vt.h @@ -2,6 +2,14 @@ #include "renderer.h" +#ifdef __OBJC__ +#import +class VTBaseRenderer : public IFFmpegRenderer { +public: + bool checkDecoderCapabilities(id device, PDECODER_PARAMETERS params); +}; +#endif + // A factory is required to avoid pulling in // incompatible Objective-C headers. diff --git a/app/streaming/video/ffmpeg-renderers/vt_avsamplelayer.mm b/app/streaming/video/ffmpeg-renderers/vt_avsamplelayer.mm index 38218b44..83bf4494 100644 --- a/app/streaming/video/ffmpeg-renderers/vt_avsamplelayer.mm +++ b/app/streaming/video/ffmpeg-renderers/vt_avsamplelayer.mm @@ -31,7 +31,7 @@ @end -class VTRenderer : public IFFmpegRenderer +class VTRenderer : public VTBaseRenderer { public: VTRenderer() @@ -379,80 +379,8 @@ public: { @autoreleasepool { int err; - if (params->videoFormat & VIDEO_FORMAT_MASK_H264) { - if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_H264)) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "No HW accelerated H.264 decode via VT"); - return false; - } - } - else if (params->videoFormat & VIDEO_FORMAT_MASK_H265) { - if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC)) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "No HW accelerated HEVC decode via VT"); - return false; - } - - // HEVC Main10 requires more extensive checks because there's no - // simple API to check for Main10 hardware decoding, and if we don't - // have it, we'll silently get software decoding with horrible performance. - if (params->videoFormat == VIDEO_FORMAT_H265_MAIN10) { - id device = MTLCreateSystemDefaultDevice(); - if (device == nullptr) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "Unable to get default Metal device"); - return false; - } - - // Exclude all GPUs earlier than macOSGPUFamily2 - // https://developer.apple.com/documentation/metal/mtlfeatureset/mtlfeatureset_macos_gpufamily2_v1 - if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily2_v1]) { - if ([device.name containsString:@"Intel"]) { - // 500-series Intel GPUs are Skylake and don't support Main10 hardware decoding - if ([device.name containsString:@" 5"]) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "No HEVC Main10 support on Skylake iGPU"); - [device release]; - return false; - } - } - else if ([device.name containsString:@"AMD"]) { - // FirePro D, M200, and M300 series GPUs don't support Main10 hardware decoding - if ([device.name containsString:@"FirePro D"] || - [device.name containsString:@" M2"] || - [device.name containsString:@" M3"]) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "No HEVC Main10 support on AMD GPUs until Polaris"); - [device release]; - return false; - } - } - } - else { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "No HEVC Main10 support on macOS GPUFamily1 GPUs"); - [device release]; - return false; - } - - [device release]; - } - } - else if (params->videoFormat & VIDEO_FORMAT_MASK_AV1) { - #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 130000 - if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_AV1)) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "No HW accelerated AV1 decode via VT"); - return false; - } - - // 10-bit is part of the Main profile for AV1, so it will always - // be present on hardware that supports 8-bit. - #else - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "AV1 requires building with Xcode 14 or later"); + if (!checkDecoderCapabilities([MTLCreateSystemDefaultDevice() autorelease], params)) { return false; - #endif } err = av_hwdevice_ctx_create(&m_HwContext, diff --git a/app/streaming/video/ffmpeg-renderers/vt_base.mm b/app/streaming/video/ffmpeg-renderers/vt_base.mm new file mode 100644 index 00000000..e3b928f8 --- /dev/null +++ b/app/streaming/video/ffmpeg-renderers/vt_base.mm @@ -0,0 +1,78 @@ +// Nasty hack to avoid conflict between AVFoundation and +// libavutil both defining AVMediaType +#define AVMediaType AVMediaType_FFmpeg +#include "vt.h" +#undef AVMediaType + +#import +#import +#import +#import + +bool VTBaseRenderer::checkDecoderCapabilities(id device, PDECODER_PARAMETERS params) { + if (params->videoFormat & VIDEO_FORMAT_MASK_H264) { + if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_H264)) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "No HW accelerated H.264 decode via VT"); + return false; + } + } + else if (params->videoFormat & VIDEO_FORMAT_MASK_H265) { + if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC)) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "No HW accelerated HEVC decode via VT"); + return false; + } + + // HEVC Main10 requires more extensive checks because there's no + // simple API to check for Main10 hardware decoding, and if we don't + // have it, we'll silently get software decoding with horrible performance. + if (params->videoFormat == VIDEO_FORMAT_H265_MAIN10) { + // Exclude all GPUs earlier than macOSGPUFamily2 + // https://developer.apple.com/documentation/metal/mtlfeatureset/mtlfeatureset_macos_gpufamily2_v1 + if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily2_v1]) { + if ([device.name containsString:@"Intel"]) { + // 500-series Intel GPUs are Skylake and don't support Main10 hardware decoding + if ([device.name containsString:@" 5"]) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "No HEVC Main10 support on Skylake iGPU"); + return false; + } + } + else if ([device.name containsString:@"AMD"]) { + // FirePro D, M200, and M300 series GPUs don't support Main10 hardware decoding + if ([device.name containsString:@"FirePro D"] || + [device.name containsString:@" M2"] || + [device.name containsString:@" M3"]) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "No HEVC Main10 support on AMD GPUs until Polaris"); + return false; + } + } + } + else { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "No HEVC Main10 support on macOS GPUFamily1 GPUs"); + return false; + } + } + } + else if (params->videoFormat & VIDEO_FORMAT_MASK_AV1) { + #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 130000 + if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_AV1)) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "No HW accelerated AV1 decode via VT"); + return false; + } + + // 10-bit is part of the Main profile for AV1, so it will always + // be present on hardware that supports 8-bit. + #else + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "AV1 requires building with Xcode 14 or later"); + return false; + #endif + } + + return true; +} diff --git a/app/streaming/video/ffmpeg-renderers/vt_metal.mm b/app/streaming/video/ffmpeg-renderers/vt_metal.mm index ac3fa326..b5172ba6 100644 --- a/app/streaming/video/ffmpeg-renderers/vt_metal.mm +++ b/app/streaming/video/ffmpeg-renderers/vt_metal.mm @@ -97,7 +97,7 @@ struct Vertex vector_float2 texCoord; }; -class VTMetalRenderer : public IFFmpegRenderer +class VTMetalRenderer : public VTBaseRenderer { public: VTMetalRenderer() @@ -518,74 +518,6 @@ public: m_NextDrawable = nullptr; }} - bool checkDecoderCapabilities(id device, PDECODER_PARAMETERS params) { - if (params->videoFormat & VIDEO_FORMAT_MASK_H264) { - if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_H264)) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "No HW accelerated H.264 decode via VT"); - return false; - } - } - else if (params->videoFormat & VIDEO_FORMAT_MASK_H265) { - if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC)) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "No HW accelerated HEVC decode via VT"); - return false; - } - - // HEVC Main10 requires more extensive checks because there's no - // simple API to check for Main10 hardware decoding, and if we don't - // have it, we'll silently get software decoding with horrible performance. - if (params->videoFormat == VIDEO_FORMAT_H265_MAIN10) { - // Exclude all GPUs earlier than macOSGPUFamily2 - // https://developer.apple.com/documentation/metal/mtlfeatureset/mtlfeatureset_macos_gpufamily2_v1 - if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily2_v1]) { - if ([device.name containsString:@"Intel"]) { - // 500-series Intel GPUs are Skylake and don't support Main10 hardware decoding - if ([device.name containsString:@" 5"]) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "No HEVC Main10 support on Skylake iGPU"); - return false; - } - } - else if ([device.name containsString:@"AMD"]) { - // FirePro D, M200, and M300 series GPUs don't support Main10 hardware decoding - if ([device.name containsString:@"FirePro D"] || - [device.name containsString:@" M2"] || - [device.name containsString:@" M3"]) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "No HEVC Main10 support on AMD GPUs until Polaris"); - return false; - } - } - } - else { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "No HEVC Main10 support on macOS GPUFamily1 GPUs"); - return false; - } - } - } - else if (params->videoFormat & VIDEO_FORMAT_MASK_AV1) { - #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 130000 - if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_AV1)) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "No HW accelerated AV1 decode via VT"); - return false; - } - - // 10-bit is part of the Main profile for AV1, so it will always - // be present on hardware that supports 8-bit. - #else - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "AV1 requires building with Xcode 14 or later"); - return false; - #endif - } - - return true; - } - id getMetalDevice() { if (qgetenv("VT_FORCE_METAL") == "0") { SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,