Trying to append CVPixelBuffers to AVAssetWriterInputPixelBufferAdaptor at the intended framerate

451 Views Asked by At

I'm trying to append CVPixelBuffers to AVAssetWriterInputPixelBufferAdaptor at the intended framerate, but it seems to be too fast, and my math is off. This isn't capturing from the camera, but capturing changing images. The actual video is much to fast than the elapsed time it was captured.

I have a function that appends the CVPixelBuffer every 1/24 of a second. So I'm trying to add an offset of 1/24 of a second to the last time.

I've tried:

let sampleTimeOffset = CMTimeMake(value: 100, timescale: 2400)

and:

let sampleTimeOffset = CMTimeMake(value: 24, timescale: 600)

and:

let sampleTimeOffset = CMTimeMakeWithSeconds(0.0416666666, preferredTimescale: 1000000000)

I'm adding onto the currentSampleTime and appending like so:

self.currentSampleTime = CMTimeAdd(currentSampleTime, sampleTimeOffset)

let success = self.assetWriterPixelBufferInput?.append(cv, withPresentationTime: currentSampleTime)

One other solution I thought of is get the difference between the last time and the current time, and add that onto the currentSampleTime for accuracy, but unsure how to do it.

1

There are 1 best solutions below

5
Chewie The Chorkie On

I found a way to accurately capture the time delay by comparing the last time in milliseconds compared to the current time in milliseconds.

First, I have a general current milliseconds time function:

func currentTimeInMilliSeconds()-> Int
{
    let currentDate = Date()
    let since1970 = currentDate.timeIntervalSince1970
    return Int(since1970 * 1000)
}

When I create a writer, (when I start recording video) I set a variable in my class to the current time in milliseconds:

currentCaptureMillisecondsTime = currentTimeInMilliSeconds()

Then in my function that's supposed to be called 1/24 of a second is not always accurate, so I need to get the difference in milliseconds between when I started writing, or my last function call.

Do a conversion of milliseconds to seconds, and set that to CMTimeMakeWithSeconds.

let lastTimeMilliseconds = self.currentCaptureMillisecondsTime
let nowTimeMilliseconds = currentTimeInMilliSeconds()
let millisecondsDifference = nowTimeMilliseconds - lastTimeMilliseconds

// set new current time
self.currentCaptureMillisecondsTime = nowTimeMilliseconds

let millisecondsToSeconds:Float64 = Double(millisecondsDifference) * 0.001

let sampleTimeOffset = CMTimeMakeWithSeconds(millisecondsToSeconds, preferredTimescale: 1000000000)

I can now append my frame with the accurate delay that actually occurred.

self.currentSampleTime = CMTimeAdd(currentSampleTime, sampleTimeOffset)

let success = self.assetWriterPixelBufferInput?.append(cv, withPresentationTime: currentSampleTime)

When I finish writing the video and I save it to my camera roll, it is the exact duration from when I was recording.