一个简单的 Swift 包,用于视频编码和解码,带有 Annex-B 适配器,专为通过网络传输视频而优化。
Transcoding 用于 Castaway 中的视频编码和解码,Castaway 是一款将 HDMI 采集设备从 iPad 或 Mac 流式传输到附近的 Vision Pro 的应用程序。
VideoEncoder 是一个对象,它接收包含 CVPixelBuffer 的 CMSampleBuffer,并输出包含压缩后的 H264/HEVC 数据的 CMBlockBuffer 的 CMSampleBuffer 流。 VideoEncoder 使用 Config 初始化,其中包含用于实时采集、主动转码、后台转码和超低延迟的预设,遵循 Apple 的建议。
let videoEncoder = VideoEncoder(config: .ultraLowLatency)
encoderStreamTask = Task {
for await encodedSampleBuffer in videoEncoder.encodedSampleBuffers {
// encodedSampleBuffer: CMSampleBuffer > CMBlockBuffer
}
}
videoEncoder.encode(sampleBuffer)
VideoDecoder 是一个对象,它接收包含压缩后的 H264/HEVC 数据的 CMBlockBuffers 的 CMSampleBuffer,并输出包含 CVPixelBuffer 的 CMSampleBuffer 流。 VideoDecoder 使用包含各种可选解压缩设置的 Config 初始化。
let videoDecoder = VideoDecoder(config: .init(realTime: true))
decoderStreamTask = Task {
for await decodedSampleBuffer in videoDecoder.decodedSampleBuffers {
// decodedSampleBuffer: CMSampleBuffer > CVPixelBuffer
}
}
videoDecoder.decode(sampleBuffer)
VideoEncoderAnnexBAdaptor 和 VideoDecoderAnnexBAdaptor 可用于将压缩后的 CMSampleBuffer 转换为 Annex B (ITU-T-REC-H.265) 字节流,以及从 Annex B 字节流转换为压缩后的 CMSampleBuffer。 这非常适合通过网络发送压缩视频数据。
在此示例中,来自采集设备的视频帧被编码和解码为 Annex-B 数据流,该数据流针对低延迟进行了优化。
let videoEncoder = VideoEncoder(config: .ultraLowLatency)
let videoEncoderAnnexBAdaptor = VideoEncoderAnnexBAdaptor(
videoEncoder: videoEncoder
)
let videoDecoder = VideoDecoder(config: .init(realTime: true))
let videoDecoderAnnexBAdaptor = VideoDecoderAnnexBAdaptor(
videoDecoder: videoDecoder,
codec: .hevc
)
videoEncoderTask = Task {
for await data in videoEncoderAnnexBAdaptor.annexBData {
// send data over network or whatever
}
}
videoDecoderTask = Task {
for await decodedSampleBuffer in videoDecoder.decodedSampleBuffers {
// here you have a received decoded sample buffer with image buffer
}
}
receivedMessageTask = Task {
// Replace `realtimeStreaming.receivedMessages` with however you receive encoded data packets
for await (data, _) in realtimeStreaming.receivedMessages {
videoDecoderAnnexBAdaptor.decode(data)
}
}
captureSessionTask = Task {
// Replace `captureSession.pixelBuffers` with your video data source
for await pixelBuffer in captureSession.pixelBuffers {
videoEncoder.encode(pixelBuffer)
}
}
VideoDecoderAnnexBAdaptor 仅支持解码完整的 NALU,这意味着如果您通过网络或某些流传输数据,则必须确保接收完整的视频帧数据包,而不仅仅是任意大小的数据流。 例如,当使用 Network.framework 时,您可以使用自定义的 NWProtocolFramerImplementation 来接收单个消息。encoder/decoder.invalidate() 来处理其他情况。 例如,如果您维护一个编码器,然后从对等方/解码器断开连接后又重新连接,则需要使编码器失效,以确保它再次发送 H264/HEVC 参数集。 否则,解码器将无法解码帧,因为编码器已优化为仅在必要时才发送 SPS/PPS/VPS。