I'm finding it impossible to write a stream of frames (from a webcam) to storage, and then at a later time, read the frame back out. If I write them using an AssetWriter in AVVideoCodecH264, then I can't read them with an AssetReader because I get the following error:
AVAssetReaderOutput does not currently support compressed output
If I try to write uncompressed (remove the AVVIdeoCodecH264 from the outputsettings) then I get the opposite error.
AVAssetWriter does not currently support uncompressed output (paraphrased)
So I can only write in a compressed format and I can only read from an uncompressed format, even though the write/read function belong to the same API!!!
Any ideas?
Below is the code for writing:
outputSettings = [AVVideoCodecKey : AVVideoCodecH264,
AVVideoWidthKey : NSNumber(value: Float(640)),
AVVideoHeightKey : NSNumber(value: Float(480))]
as [String : Any]
assetWriterInput = AVAssetWriterInput(mediaType: AVMediaTypeVideo,
outputSettings: outputSettings)
pixelBufferAdaptor = AVAssetWriterInputPixelBufferAdaptor(
assetWriterInput: assetWriterInput!,
sourcePixelBufferAttributes: [ kCVPixelBufferPixelFormatTypeKey
as String : Int(kCVPixelFormatType_420YpCbCr8PlanarFullRange)])
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let fileUrl = paths[0].appendingPathComponent("output.mov")
try? FileManager.default.removeItem(at: fileUrl)
assetWriter = try? AVAssetWriter(url: fileUrl, fileType: AVFileTypeMPEG4)
assetWriter?.add(assetWriterInput!)
assetWriterInput!.expectsMediaDataInRealTime = true
assetWriter?.startWriting()
saving = true;
assetWriter?.startSession(atSourceTime: kCMTimeZero)
and the code for reading...
let asset = AVAsset(url: fileUrl)
self.assetReader = try? AVAssetReader(asset: asset);
guard let videoTrack = asset.tracks(withMediaType: AVMediaTypeVideo).first
else { return }
self.assetReaderOutput = AVAssetReaderTrackOutput(
track: videoTrack,
outputSettings:[String(kCVPixelBufferPixelFormatTypeKey):
NSNumber(value: kCVPixelFormatType_420YpCbCr8PlanarFullRange)])
self.assetReader!.add(self.assetReaderOutput!)
self.assetReader!.startReading()