lilzz
lilzz

Reputation: 5413

Trying to understand CMTime and CMTimeMake

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?

Upvotes: 169

Views: 85838

Answers (6)

yoAlex5
yoAlex5

Reputation: 34175

Swift CMTime CoreMediaTime

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)

Upvotes: 0

MGY
MGY

Reputation: 8463

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);

Upvotes: 12

kandelvijaya
kandelvijaya

Reputation: 1585

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

Upvotes: 3

bcattle
bcattle

Reputation: 12819

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".

Upvotes: 43

Raunak
Raunak

Reputation: 3414

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.

Upvotes: 154

Peter DeWeese
Peter DeWeese

Reputation: 18333

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.

Upvotes: 191

Related Questions