What I am trying to do
Record a stream of CMSampleBuffer that lack timestamps
Problem
I am trying to add timestamps and it fails to append the new sample buffer
Steps to reproduce:
- get video stream from external camera, h.264 encoded in .mp4 format
- create filepath to save video and handle auth/permissions
- create a variable
frameDuration = CMTime(seconds: 1.0/30.0, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
- create a variable for next presentation timestamp
nextPTS: CMTime = CMTimeMake(value: 0, timescale: 0)
- Setup AVAssetWriter using
CMSampleBufferGetFormatDescription(mySampleBuffer)
Setup AVAssetWriter Func
private func setupAssetWriter(format formatDescription: CMFormatDescription?) -> Bool {
// allocate the writer object with our output file URL
guard let videoWriter = try? AVAssetWriter(outputURL: URL(fileURLWithPath: self.path), fileType: AVFileType.mp4),
formatDescription != nil else {
print("Error: No Format For Video to create AVAssetWriter")
return false
}
self.assetWriter = videoWriter
// initialize a new input for video to receive sample buffers for writing
// passing nil for outputSettings instructs the input to pass through appended samples, doing no processing before they are written
let videoInput = AVAssetWriterInput(mediaType: .video, outputSettings: nil, sourceFormatHint: formatDescription)
videoInput.expectsMediaDataInRealTime = true
guard videoWriter.canAdd(videoInput) else {
print("Error: Cannot add Video Input to AVAssetWriter")
return false
}
videoWriter.add(videoInput)
// initiates a sample-writing at time 0
self.nextPTS = CMTime.zero
videoWriter.startWriting()
videoWriter.startSession(atSourceTime: CMTime.zero)
self.assetWriter = videoWriter
self.assetWriterInput = videoInput
return true
}
- Append frames as they come in
func appendFrame(_ sampleBuffer: CMSampleBuffer) {
// set up the AVAssetWriter using the format description from the first sample buffer captured
if self.assetWriter == nil {
let formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer)
guard self.setupAssetWriter(format: formatDescription) else {
print("Error: Failed to set up asset writer")
return
}
}
// re-time the sample buffer - in this sample frameDuration is set to 30 fps
var timingInfo = CMSampleTimingInfo.invalid // a way to get an instance without providing 3 CMTime objects
timingInfo.duration = self.frameDuration
timingInfo.presentationTimeStamp = self.nextPTS
var sbufWithNewTiming: CMSampleBuffer? = nil
guard CMSampleBufferCreateCopyWithNewTiming(allocator: kCFAllocatorDefault,
sampleBuffer: sampleBuffer,
sampleTimingEntryCount: 1, // numSampleTimingEntries
sampleTimingArray: &timingInfo,
sampleBufferOut: &sbufWithNewTiming) == 0 else {
print("Error: Failed to set up CMSampleBufferCreateCopyWithNewTiming")
return
}
// append the sample buffer if we can and increment presentation time
guard let writeInput = self.assetWriterInput, writeInput.isReadyForMoreMediaData else {
print("Error: AVAssetWriterInput not ready for more media")
return
}
guard let sbufWithNewTiming = sbufWithNewTiming else {
print("Error: sbufWithNewTiming is nil")
return
}
if writeInput.append(sbufWithNewTiming) {
self.nextPTS = CMTimeAdd(self.frameDuration, self.nextPTS)
} else {
let error = self.assetWriter!.error
NSLog("Error: Failed to append sample buffer: \(error!)")
}
}
Cannot append the sample buffer, the
NSLog("Error: Failed to append sample buffer: \(error!)")
Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSLocalizedFailureReason=An unknown error occurred (-17507), NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x283cf7810 {Error Domain=NSOSStatusErrorDomain Code=-17507 "(null)"}}
I can't find any code -17507 references online