master ohmu/fastfetch-openbsd / src / detection / codec / codec_apple.c
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}