Trying to understand CMTime and CMTimeMake
Asked Answered
M

6

168

1) CMTimeMake(1,10) means duration of 1 second and timescale of 10, or 10 frames per second. This means 1s duration of video with 10 frames?

2)

CMTime lastTime=CMTimeMake(1,10);
CMTime frameTime=CMTimeMake(1, 10);
CMTime currentTime=CMTimeAdd(lastTime, frameTime)

= (2, 10) ?

2 seconds of video and with 10 frames per second of the currentTime?

Madelon answered 23/10, 2010 at 0:1 Comment(1)
if your video is 48 FPS (frame per second) then you would easily do CMTimeMake(1, 48) to run a block of code every 1/48 of a second ie 1 block per frameIrrationality
F
190

1) CMTimeMake(1,10) actually means a value of 1 and a timescale of 10. They are a numerator and denominator, so it is 1/10 of a second, not 1 second.

2) The result will be like CMTimeMake(2, 10), which is 2/10ths of a second.

Fastigiate answered 23/10, 2010 at 0:16 Comment(2)
Why apple's reference don't say this?Lafountain
Now it says: value/timescale = seconds explicitly.Magnum
I
154

Peter is right. The following code makes the concept more clear:

1)

Float64 seconds = 5; 
int32_t preferredTimeScale = 600;
CMTime inTime = CMTimeMakeWithSeconds(seconds, preferredTimeScale);
CMTimeShow(inTime);

The above code gives: {3000/600 = 5.000}

Which means a total duration of 5 seconds, with 3000 frames with a timescale of 600 frames per second.

2)

int64_t value = 10000;
int32_t preferredTimeScale = 600;
CMTime inTime = CMTimeMake(value, preferredTimeScale);
CMTimeShow(inTime);

This one gives {10000/600 = 16.667}

Which means a total duration of 16.667 seconds, with 10000 frames with a timescale of 600 frames per second.

Notice the difference between CMTimeMake(int64_t value, int32_t timescale) and CMTimeMakeWithSeconds(Float64 seconds, int32_t preferredTimeScale)

Hope this explanation helps. For further clarifications, please don't hesitate to post further questions on this post.

Inductor answered 10/6, 2011 at 8:2 Comment(2)
I wonder why setMaxRecordedDuration needs the preferredTimeScale when frame_rate is set differently. Everyone is just blindly using 600, and no good explanation as to exactly what it is doing.Putrescine
@Putrescine 600 is a multiple of the common video frame rates. Warren Moore explains it at warrenmoore.net/understanding-cmtime pretty well.Mady
E
42

With CMTimeMake(A, B) you store a rational number, an exact fraction A / B seconds

  • CMTimeMake(1, 4) -> the time interval 0.25 seconds

With CMTimeMakeWithSeconds(A, B) you store A seconds to a resolution of B steps

  • CMTimeMakeWithSeconds(0.25, ...) -> the time interval 0.25 seconds

You commonly see CMTimeMakeWithSeconds(time, NSEC_PER_SEC). The NSEC_PER_SEC effectively means "max resolution".

Epigeous answered 6/3, 2014 at 3:5 Comment(0)
B
12

Interval for 1 Second

If you only want to know how to make an interval for 1 second (like me), this is your answer:

int seconds = 1;

CMTime interval = CMTimeMakeWithSeconds(seconds, NSEC_PER_SEC);
Brokerage answered 6/2, 2018 at 8:59 Comment(0)
U
3

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

See See this SO Answer which is clear

Unit answered 30/8, 2016 at 6:55 Comment(0)
M
0

Swift CMTime

When you operate time it is important to save accuracy. CMTime propose you to use two integers(value and timescale) to present a float number. Additional functions simplify CMTime mathematics in contrast to float operations

Important CMTime properties are:

  • value
  • timescale - number of equal parts of one second
  • seconds

The formula is

Int64 value(numerator) / Int32 timescale(denominator) = Float64 seconds

//for example
//value 1 / timescale 10 = 1/10(0.1) seconds

Next example shows next items:

  • You can create CMTime using constructor(init()) or CMTimeMake function
  • time.seconds is the same as CMTimeGetSeconds(time)
  • mathematics with CMTime - CMTimeCompare, CMTimeAdd...
import CoreMedia

func testTime() {
   let value: Int64 = 1
   let timescale: Int32 = 10
   let secondsResult: Double = 0.1 // 1/10 sec
   
   let time1: CMTime = CMTime(value: value, timescale: timescale)
   let time2: CMTime = CMTime(seconds: secondsResult, preferredTimescale: timescale)
   
   let time3: CMTime = CMTimeMake(value: value, timescale: timescale)
   let time4: CMTime = CMTimeMakeWithSeconds(secondsResult, preferredTimescale: timescale)
   
   let seconds1: Double = time1.seconds
   let seconds2: Float64 = CMTimeGetSeconds(time1)
   assert(seconds1 == seconds2)
   assert(seconds1 == secondsResult)
   
   assert(time1 == time2)
   assert(time1 == time3)
   assert(time1 == time4)
        
   assert(CMTimeCompare(time1, time2) == 0)
}

Create CMTime using seconds

You are able to create CMTime using value and timescale where seconds will be calculated(value / timescale). This approach is clear but also you are able to create CMTime using seconds and preferredTimescale. In this case your value and seconds can be different and be recalculated to satisfy formula(value must be Int64) that is why it can be rounded, as a result seconds also is recalculated

//preset - seconds: 0.1, preferredTimescale: 10, expect value == 1
//result - seconds: 0.1, value: 1
let time5: CMTime = CMTime(seconds: 0.1, preferredTimescale: 10)
assert(time5.value == 1)
assert(time5.seconds == 0.1)

//preset - seconds: 0.1, preferredTimescale: 1, expect value == 0.1
//result - seconds: 0, value: 0
let time6: CMTime = CMTime(seconds: 0.1, preferredTimescale: 1)
assert(time6.value == 0)
assert(time6.seconds == 0)

//preset - seconds: 1.31, preferredTimescale: 10, expect value == 13.1
//result - seconds: 1.3, value: 13
let time7: CMTime = CMTime(seconds: 1.31, preferredTimescale: 10)
assert(time7.value == 13)
assert(time7.seconds == 1.3)
Mineralogy answered 14/4 at 17:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.