Move VT decoding support detection into a single base class

This commit is contained in:
Cameron Gutman 2024-07-26 00:35:32 -05:00
parent c707dab70a
commit e548697a36
5 changed files with 90 additions and 143 deletions

View File

@ -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

View File

@ -2,6 +2,14 @@
#include "renderer.h"
#ifdef __OBJC__
#import <Metal/Metal.h>
class VTBaseRenderer : public IFFmpegRenderer {
public:
bool checkDecoderCapabilities(id<MTLDevice> device, PDECODER_PARAMETERS params);
};
#endif
// A factory is required to avoid pulling in
// incompatible Objective-C headers.

View File

@ -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<MTLDevice> 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,

View File

@ -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 <Cocoa/Cocoa.h>
#import <VideoToolbox/VideoToolbox.h>
#import <AVFoundation/AVFoundation.h>
#import <Metal/Metal.h>
bool VTBaseRenderer::checkDecoderCapabilities(id<MTLDevice> 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;
}

View File

@ -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<MTLDevice> 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<MTLDevice> getMetalDevice() {
if (qgetenv("VT_FORCE_METAL") == "0") {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,