Trying to Understand Cmtime

Trying to understand CMTime

A CMTime struct represents a length of time that is stored as rational number (see CMTime Reference). CMTime has a value and a timescale field, and represents the time value/timescale seconds .

CMTimeMake is a function that returns a CMTime structure, for example:

CMTime t1 = CMTimeMake(1, 10); // 1/10 second = 0.1 second
CMTime t2 = CMTimeMake(2, 1); // 2 seconds
CMTime t3 = CMTimeMake(3, 4); // 3/4 second = 0.75 second
CMTime t4 = CMTimeMake(6, 8); // 6/8 second = 0.75 second

The last two time values t3 and t4 represent the same time value, therefore

CMTimeCompare(t3, t4) == 0

If you set the videoMinFrameDuration of a AVCaptureSession is does not make a difference if you set

connection.videoMinFrameDuration = CMTimeMake(1, 20); // or
connection.videoMinFrameDuration = CMTimeMake(2, 40);

In both cases the minimum time interval between frames is set to 1/20 = 0.05 seconds.

Help me understand CMTime in AVAssetWriter

You will need to generate a CMTime structure using CMTimeMake. You will need to increment the time by 1/30 of a second for each frame.

Here is a sketch:

CMTime time = CMTimeMake(0, 30); // (time, time_scale)

for(each image) {
[adaptor appendPixelBuffer:buffer withPresentationTime:time]
time.value += 1;
}

With the time setup as shown,the smallest time resolution is 1/30 of a second. time / time_scale = 1 second. I am not certain if there is a specific requirement for H.264. AVFoundation uses a time scale of 1000000000 (1,000,000,000 or 1 billion) when capturing (in my experience).

Update:

Just to review. From the CMTime struct:

CMTimeValue value;  /*! @field value The value of the CMTime. value/timescale = seconds. */
CMTimeScale timescale; /*! @field timescale The timescale of the CMTime. value/timescale = seconds. */

The timebase would stay the same throughout the video. Let say you have a current value of 10 with a time scale of 30. The current time in seconds is 10/30 = 0.33333 seconds. The time value for the 40th frame of your movie is 40/30 = 1.33333. So the 40th frame should render at 1.3333 seconds into the movie.

I am not sure if this time base is appropriate for an H.264 video. I am not familiar with the spec. I know when capturing video the presentation time base for video frames is 1000000000. Technically it should not matter. The time is a rational number -- 1000000000 / 1000000000 = 1 second and 30 / 30 = 1 second.

Make CMTime with a very small value

CMTime represents a time value as a rational number with integer
numerator (the value) and denominator (the timescale) . In order to represent a small value
like yours, you have to choose a larger timescale (depending on
the desired accuracy). Example:

let smallValue = 0.0401588716
let frameTime = CMTime(seconds: smallValue, preferredTimescale: 1000000)

print(frameTime.seconds) // 0.040158

preferredTimescale in CMTimeMakeWithSeconds

You should view the discussion here

Preferred time scale will add a denominator to your seconds, meaning if you set 5 seconds and preferredTimeScale of 60 it will be 1/12 of a second

swift and CMTimeMake

CMTime and CMTimeMake are defined in the "CoreMedia" module, therefore you have to

import CoreMedia

Then this compiles without problems:

let seconds : Int64 = 10
let preferredTimeScale : Int32 = 1
let aMovieFileOutput = AVCaptureMovieFileOutput()
let maxDuration : CMTime = CMTimeMake(seconds, preferredTimeScale)
aMovieFileOutput.maxRecordedDuration = maxDuration

Update for Swift 3:

let maxDuration = CMTime(seconds: Double(seconds), preferredTimescale: 1)

CMTime seconds output


NSLog(@"seconds = %f", CMTimeGetSeconds(cmTime));


Related Topics



Leave a reply



Submit