ohmu
·
2026-10-15
1#include "codec.h"
2
3#include <VideoToolbox/VideoToolbox.h>
4#include "common/apple/cf_helpers.h"
5
6#ifdef MAC_OS_VERSION_11_0
7[[clang::weak_import]] VT_EXPORT void VTRegisterSupplementalVideoDecoderIfAvailable(CMVideoCodecType codecType);
8#endif
9
10static const struct {
11 CMVideoCodecType codec;
12 FFCodecType type;
13} FF_CODEC_CODECS[] = {
14 { 'h263', FF_CODEC_TYPE_H263 }, // kCMVideoCodecType_H263
15 { 'jpeg', FF_CODEC_TYPE_MJPEG }, // kCMVideoCodecType_JPEG
16 { 'dmb1', FF_CODEC_TYPE_MJPEG }, // kCMVideoCodecType_JPEG_OpenDML
17 { 'mp1v', FF_CODEC_TYPE_MPEG1 }, // kCMVideoCodecType_MPEG1Video
18 { 'mp2v', FF_CODEC_TYPE_MPEG2 }, // kCMVideoCodecType_MPEG2Video
19 { 'mp4v', FF_CODEC_TYPE_DIVX_XVID }, // kCMVideoCodecType_MPEG4Video
20 { 'avc1', FF_CODEC_TYPE_H264 }, // kCMVideoCodecType_H264
21 { 'hvc1', FF_CODEC_TYPE_HEVC }, // kCMVideoCodecType_HEVC
22 { 'muxa', FF_CODEC_TYPE_HEVC }, // kCMVideoCodecType_HEVCWithAlpha
23 { 'dvh1', FF_CODEC_TYPE_DOLBY_VISION_HEVC }, // kCMVideoCodecType_DolbyVisionHEVC
24 { 'dish', FF_CODEC_TYPE_HEVC }, // kCMVideoCodecType_DisparityHEVC
25 { 'deph', FF_CODEC_TYPE_HEVC }, // kCMVideoCodecType_DepthHEVC
26 { 'vp09', FF_CODEC_TYPE_VP9 }, // kCMVideoCodecType_VP9
27 { 'av01', FF_CODEC_TYPE_AV1 }, // kCMVideoCodecType_AV1
28 { 'ap4x', FF_CODEC_TYPE_PRORES }, // kCMVideoCodecType_AppleProRes4444XQ
29 { 'ap4h', FF_CODEC_TYPE_PRORES }, // kCMVideoCodecType_AppleProRes4444
30 { 'apch', FF_CODEC_TYPE_PRORES }, // kCMVideoCodecType_AppleProRes422HQ
31 { 'apcn', FF_CODEC_TYPE_PRORES }, // kCMVideoCodecType_AppleProRes422
32 { 'apcs', FF_CODEC_TYPE_PRORES }, // kCMVideoCodecType_AppleProRes422LT
33 { 'apco', FF_CODEC_TYPE_PRORES }, // kCMVideoCodecType_AppleProRes422Proxy
34 { 'aprn', FF_CODEC_TYPE_PRORES_RAW }, // kCMVideoCodecType_AppleProResRAW
35 { 'aprh', FF_CODEC_TYPE_PRORES_RAW }, // kCMVideoCodecType_AppleProResRAWHQ
36};
37
38static FFCodecType ffCodecCodecToType(CMVideoCodecType codec) {
39 for (uint32_t i = 0; i < ARRAY_SIZE(FF_CODEC_CODECS); ++i) {
40 if (FF_CODEC_CODECS[i].codec == codec) {
41 return FF_CODEC_CODECS[i].type;
42 }
43 }
44 return FF_CODEC_TYPE_NONE;
45}
46
47static FFCodecType ffCodecDetectEncoders(void) {
48 FF_CFTYPE_AUTO_RELEASE CFArrayRef encoderList = nullptr;
49 if (VTCopyVideoEncoderList(nullptr, &encoderList) != noErr || !encoderList) {
50 return FF_CODEC_TYPE_NONE;
51 }
52
53 FFCodecType types = FF_CODEC_TYPE_NONE;
54 for (uint32_t i = 0; i < CFArrayGetCount(encoderList); ++i) {
55 CFDictionaryRef encoder = CFArrayGetValueAtIndex(encoderList, i);
56 bool isHardwareAccelerated;
57 int codec;
58 if (ffCfDictGetBool(encoder, CFSTR("IsHardwareAccelerated"), &isHardwareAccelerated) != nullptr ||
59 !isHardwareAccelerated ||
60 ffCfDictGetInt(encoder, CFSTR("CodecType"), &codec) != nullptr) {
61 continue;
62 }
63 types |= ffCodecCodecToType((CMVideoCodecType) codec);
64 }
65
66 return types;
67}
68
69static FFCodecType ffCodecDetectDecoders() {
70 FFCodecType types = FF_CODEC_TYPE_NONE;
71 for (uint32_t i = 0; i < ARRAY_SIZE(FF_CODEC_CODECS); ++i) {
72 auto codec = FF_CODEC_CODECS[i];
73 if (types & codec.type) {
74 continue;
75 }
76
77#ifdef MAC_OS_VERSION_11_0
78 if (VTRegisterSupplementalVideoDecoderIfAvailable) {
79 VTRegisterSupplementalVideoDecoderIfAvailable(codec.codec);
80 }
81#endif
82 bool supported = VTIsHardwareDecodeSupported(codec.codec);
83 if (!supported) {
84 continue;
85 }
86
87 types |= codec.type;
88 }
89
90 return types;
91}
92
93const char* ffDetectCodecNative(FFCodecOptions* options, FFlist* result /* list of FFCodecResult */) {
94 FFCodecType decoders = options->showType & FF_CODEC_SHOW_TYPE_DECODER ? ffCodecDetectDecoders() : FF_CODEC_TYPE_NONE;
95 FFCodecType encoders = options->showType & FF_CODEC_SHOW_TYPE_ENCODER ? ffCodecDetectEncoders() : FF_CODEC_TYPE_NONE;
96
97 if (decoders != FF_CODEC_TYPE_NONE || encoders != FF_CODEC_TYPE_NONE) {
98 FFCodecResult* item = FF_LIST_ADD(FFCodecResult, *result);
99 ffStrbufInitStatic(&item->gpu, "Default");
100 item->decoders = decoders;
101 item->encoders = encoders;
102 item->platformApi = "VideoToolbox";
103 }
104
105 return nullptr;
106}