HaishinKit.swift/Sources/Extension/CMSampleBuffer+Extension.swift

122 lines
3.5 KiB
Swift

import Accelerate
import AVFoundation
import CoreMedia
extension CMSampleBuffer {
var isNotSync: Bool {
get {
getAttachmentValue(for: kCMSampleAttachmentKey_NotSync) ?? false
}
set {
setAttachmentValue(for: kCMSampleAttachmentKey_NotSync, value: newValue)
}
}
@available(iOS, obsoleted: 13.0)
@available(tvOS, obsoleted: 13.0)
@available(macOS, obsoleted: 10.15)
var isValid: Bool {
CMSampleBufferIsValid(self)
}
@available(iOS, obsoleted: 13.0)
@available(tvOS, obsoleted: 13.0)
@available(macOS, obsoleted: 10.15)
var dataBuffer: CMBlockBuffer? {
get {
CMSampleBufferGetDataBuffer(self)
}
set {
_ = newValue.map {
CMSampleBufferSetDataBuffer(self, newValue: $0)
}
}
}
@available(iOS, obsoleted: 13.0)
@available(tvOS, obsoleted: 13.0)
@available(macOS, obsoleted: 10.15)
var imageBuffer: CVImageBuffer? {
CMSampleBufferGetImageBuffer(self)
}
@available(iOS, obsoleted: 13.0)
@available(tvOS, obsoleted: 13.0)
@available(macOS, obsoleted: 10.15)
var numSamples: CMItemCount {
CMSampleBufferGetNumSamples(self)
}
@available(iOS, obsoleted: 13.0)
@available(tvOS, obsoleted: 13.0)
@available(macOS, obsoleted: 10.15)
var duration: CMTime {
CMSampleBufferGetDuration(self)
}
@available(iOS, obsoleted: 13.0)
@available(tvOS, obsoleted: 13.0)
@available(macOS, obsoleted: 10.15)
var formatDescription: CMFormatDescription? {
CMSampleBufferGetFormatDescription(self)
}
@available(iOS, obsoleted: 13.0)
@available(tvOS, obsoleted: 13.0)
@available(macOS, obsoleted: 10.15)
var decodeTimeStamp: CMTime {
CMSampleBufferGetDecodeTimeStamp(self)
}
@available(iOS, obsoleted: 13.0)
@available(tvOS, obsoleted: 13.0)
@available(macOS, obsoleted: 10.15)
var presentationTimeStamp: CMTime {
CMSampleBufferGetPresentationTimeStamp(self)
}
func muted(_ muted: Bool) -> CMSampleBuffer? {
guard muted else {
return self
}
guard let dataBuffer = dataBuffer else {
return nil
}
let status = CMBlockBufferFillDataBytes(
with: 0,
blockBuffer: dataBuffer,
offsetIntoDestination: 0,
dataLength: dataBuffer.dataLength
)
guard status == noErr else {
return nil
}
return self
}
// swiftlint:disable discouraged_optional_boolean
@inline(__always)
private func getAttachmentValue(for key: CFString) -> Bool? {
guard
let attachments = CMSampleBufferGetSampleAttachmentsArray(self, createIfNecessary: false) as? [[CFString: Any]],
let value = attachments.first?[key] as? Bool else {
return nil
}
return value
}
@inline(__always)
private func setAttachmentValue(for key: CFString, value: Bool) {
guard
let attachments: CFArray = CMSampleBufferGetSampleAttachmentsArray(self, createIfNecessary: true), 0 < CFArrayGetCount(attachments) else {
return
}
let attachment = unsafeBitCast(CFArrayGetValueAtIndex(attachments, 0), to: CFMutableDictionary.self)
CFDictionarySetValue(
attachment,
Unmanaged.passUnretained(key).toOpaque(),
Unmanaged.passUnretained(value ? kCFBooleanTrue : kCFBooleanFalse).toOpaque()
)
}
}