Skip to content

Instantly share code, notes, and snippets.

@ycrack
Last active November 25, 2023 11:51
Show Gist options
  • Select an option

  • Save ycrack/f6880f7828be183c2f0330ae86d883d4 to your computer and use it in GitHub Desktop.

Select an option

Save ycrack/f6880f7828be183c2f0330ae86d883d4 to your computer and use it in GitHub Desktop.
VideoToolBoxのハードウェアサポートを確認する
import PlaygroundSupport
import SwiftUI
struct ContentView: View {
var body: some View {
DecoderSupportView()
EncoderSupportView()
}
}
let host = UIHostingController(rootView: ContentView())
PlaygroundPage.current.liveView = host
import Foundation
extension FourCharCode: ExpressibleByStringLiteral {
public init(stringLiteral value: StringLiteralType) {
var code: FourCharCode = 0
if value.count == 4 && value.utf8.count == 4 {
for byte in value.utf8 {
code = code << 8 + FourCharCode(byte)
}
}
else {
print("FourCharCode: Can't initialize with '\(value)', only printable ASCII allowed. Setting to '????'.")
code = 0x3F3F3F3F // = '????'
}
self = code
}
public init(extendedGraphemeClusterLiteral value: String) {
self = FourCharCode(stringLiteral: value)
}
public init(unicodeScalarLiteral value: String) {
self = FourCharCode(stringLiteral: value)
}
public init(_ value: String) {
self = FourCharCode(stringLiteral: value)
}
public var string: String {
let bytes: [CChar] = [
CChar((self >> 24) & 0xff),
CChar((self >> 16) & 0xff),
CChar((self >> 8) & 0xff),
CChar(self & 0xff),
0
]
let result = String(cString: bytes)
let characterSet = CharacterSet.whitespaces
return result.trimmingCharacters(in: characterSet)
}
}
import VideoToolbox
import SwiftUI
public protocol CodecBase {
var fourcc: FourCharCode { get }
var description: String { get }
}
public struct Codec: CodecBase {
public var fourcc: FourCharCode
public var description: String
}
public struct CodecSupport: Identifiable, CodecBase {
public let fourcc: FourCharCode
public let description: String
public let supported: Bool
public let id = UUID()
var formattedSupported: String {
supported ? "yes" : "no"
}
}
public let codecs: [Codec] = [
.init(fourcc: kCMVideoCodecType_422YpCbCr8, description: "Y'CbCr 8-bit 4:2:2 ordered Cb Y'0 Cr Y'1"),
.init(fourcc: kCMVideoCodecType_Animation, description: "Apple Animation"),
.init(fourcc: kCMVideoCodecType_AppleProRes422, description: "Apple ProRes 422"),
.init(fourcc: kCMVideoCodecType_AppleProRes422HQ, description: "Apple ProRes 422 HQ"),
.init(fourcc: kCMVideoCodecType_AppleProRes422LT, description: "Apple ProRes 422 LT"),
.init(fourcc: kCMVideoCodecType_AppleProRes422Proxy, description: "Apple ProRes 422 proxy"),
.init(fourcc: kCMVideoCodecType_AppleProRes4444, description: "Apple ProRes 4444"),
.init(fourcc: kCMVideoCodecType_AppleProRes4444XQ, description: "Apple ProRes 4444XQ"),
.init(fourcc: kCMVideoCodecType_AppleProResRAW, description: "Apple ProRes RAW"),
.init(fourcc: kCMVideoCodecType_AppleProResRAWHQ, description: "Apple ProRes RAW HQ"),
.init(fourcc: kCMVideoCodecType_Cinepak, description: "cinepak"),
.init(fourcc: kCMVideoCodecType_DVCNTSC, description: "DV NTSC"),
.init(fourcc: kCMVideoCodecType_DVCPAL, description: "DV PAL"),
.init(fourcc: kCMVideoCodecType_DVCPROHD1080i50, description: "Panasonic DVCPro-HD 1080i50"),
.init(fourcc: kCMVideoCodecType_DVCPROHD1080i60, description: "Panasonic DVCPro-HD 1080i60"),
.init(fourcc: kCMVideoCodecType_DVCPROHD1080p25, description: "Panasonic DVCPro-HD 1080p25"),
.init(fourcc: kCMVideoCodecType_DVCPROHD1080p30, description: "Panasonic DVCPro-HD 1080p30"),
.init(fourcc: kCMVideoCodecType_DVCPROHD720p50, description: "Panasonic DVCPro-HD 720p50"),
.init(fourcc: kCMVideoCodecType_DVCPROHD720p60, description: "Panasonic DVCPro-HD 720p60"),
.init(fourcc: kCMVideoCodecType_DVCPro50NTSC, description: "Panasonic DVCPro-50 NTSC"),
.init(fourcc: kCMVideoCodecType_DVCPro50PAL, description: "Panasonic DVCPro-50 PAL"),
.init(fourcc: kCMVideoCodecType_DVCProPAL, description: "Panasonic DVCPro PAL"),
.init(fourcc: kCMVideoCodecType_H263, description: "ITU-T H.263"),
.init(fourcc: kCMVideoCodecType_H264, description: "ITU-T H.264"),
.init(fourcc: kCMVideoCodecType_HEVC, description: "ITU-T HEVC"),
.init(fourcc: kCMVideoCodecType_HEVCWithAlpha, description: "HEVC with alpha"),
.init(fourcc: kCMVideoCodecType_JPEG, description: "JPEG"),
.init(fourcc: kCMVideoCodecType_JPEG_OpenDML, description: "JPEG with Open-DML extension"),
.init(fourcc: kCMVideoCodecType_MPEG1Video, description: "MPEG-1"),
.init(fourcc: kCMVideoCodecType_MPEG2Video, description: "MPEG-2"),
.init(fourcc: kCMVideoCodecType_MPEG4Video, description: "MPEG-4 Part 2"),
.init(fourcc: kCMVideoCodecType_SorensonVideo, description: "sorenson"),
.init(fourcc: kCMVideoCodecType_SorensonVideo3, description: "sorenson 3"),
.init(fourcc: kCMVideoCodecType_DepthHEVC, description: "depth HEVC"),
.init(fourcc: kCMVideoCodecType_DisparityHEVC, description: "disparity HEVC"),
.init(fourcc: kCMVideoCodecType_DolbyVisionHEVC, description: "Dolby Vision HEVC"),
.init(fourcc: kCMVideoCodecType_VP9, description: "VP9"),
.init(fourcc: kCMVideoCodecType_AV1, description: "AV1")
]
public func getDecoders() -> [CodecSupport] {
return codecs.map {
CodecSupport(
fourcc: $0.fourcc,
description: $0.description,
supported: VTIsHardwareDecodeSupported($0.fourcc)
)
}
}
public struct DecoderSupportView: View {
public init() {}
@State var data = getDecoders()
@State var order = [KeyPathComparator(\CodecSupport.formattedSupported)]
public var body: some View {
VStack {
Text("Decoders")
Table(data, sortOrder: $order) {
TableColumn("Supported", value: \.formattedSupported) {
Text($0.supported ? "✅" : "❌")
}.width(96)
TableColumn("FourCC", value: \.fourcc.string) {
Text($0.fourcc.string).font(Font.system(size: 16).monospaced())
}.width(64)
TableColumn("description", value: \.description)
}.onChange(of: order) {
data.sort(using: $0)
}
}
}
}
public func getEncoders() -> [CodecSupport] {
var encoderList: CFArray?
let status = VTCopyVideoEncoderList(nil, &encoderList)
if status == noErr, let encoders = encoderList as? [[NSString: Any]] {
return encoders.map {
CodecSupport(
fourcc: $0[kVTVideoEncoderList_CodecType] as! CMVideoCodecType,
description: $0[kVTVideoEncoderList_DisplayName] as! String,
supported: $0[kVTVideoEncoderList_IsHardwareAccelerated] as? Int == 1 || false
)
}
} else {
return []
}
}
public struct EncoderSupportView: View {
public init() {}
@State var data = getEncoders()
@State var order = [KeyPathComparator(\CodecSupport.formattedSupported)]
public var body: some View {
VStack {
Text("Encoders")
Table(data, sortOrder: $order) {
TableColumn("Supported", value: \.formattedSupported) {
Text($0.supported ? "✅" : "❌")
}.width(96)
TableColumn("FourCC", value: \.fourcc.string) {
Text($0.fourcc.string).font(Font.system(size: 16).monospaced())
}.width(64)
TableColumn("description", value: \.description)
}.onChange(of: order) {
data.sort(using: $0)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment