一个简单的 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。