0

Given a list of CMSampleBuffers that have been read in from an asset, I want to adjust the duration of the asset so that it's half length (twice the speed) of the original.

Currently my function for generating new time stamps looks like:

func adjustTimeStampsForBuffers(buffers: [CMSampleBuffer]) -> [CMTime] {
    let frameCount = buffers.count
    // self.duration is CMTimeGetSeconds(asset.duration)
    let increment = Float(self.duration / 2) / Float(frameCount)
    return Array(0.stride(to: frameCount, by: 1)).enumerate().map {
        let seconds: Float64 = Float64(increment) * Float64($0.index)
        return CMTimeMakeWithSeconds(seconds, self.asset.duration.timescale)
    }
}

however this doesn't seem to work and the outputted assets are in fact twice the length, not half. Can anybody point out where I'm going wrong?

Edit:

Thanks to @sschale, here's my final answer:

func adjustTimeStampsForBuffers(buffers: [CMSampleBuffer]) -> [CMTime] {
    return buffers.map {
        let time = CMSampleBufferGetPresentationTimeStamp($0)
        return CMTimeMake(time.value, time.timescale * 2)
    }
}

Instead of calculating new values, the timestamp is adjusted instead.

barndog
  • 6,975
  • 8
  • 53
  • 105

1 Answers1

1

Based on my reading of the docs, it looks like that self.asset.duration.timescale may be the key here, as changing it will influence the whole file (if I'm understanding the reference you're making that that timescale is for the whole file, or maybe you need to adjust it in each of the buffers).

See here for more info as well.

Relevant section:

A CMTime is represented as a rational number, with a numerator (an int64_t value), and a denominator (an int32_t timescale). Conceptually, the timescale specifies the fraction of a second each unit in the numerator occupies. Thus if the timescale is 4, each unit represents a quarter of a second; if the timescale is 10, each unit represents a tenth of a second, and so on. In addition to a simple time value, a CMTime can represent non-numeric values: +infinity, -infinity, and indefinite. Using a flag CMTime indicates whether the time been rounded at some point.

CMTimes contain an epoch number, which is usually set to 0, but can be used to distinguish unrelated timelines: for example, it could be incremented each time through a presentation loop, to differentiate between time N in loop 0 from time N in loop 1

Community
  • 1
  • 1
sschale
  • 5,168
  • 3
  • 29
  • 36
  • That's a good suggestion, I changed it so that every new timestamp is being calculated using `CMSampleBufferGetPresentationTimeStamp`. Unfortunately that didn't seem to have any effect. I was reading up on `CMTime` here: https://warrenmoore.net/understanding-cmtime and my suspicion is that it has to do with `CMTimeMakeSeconds` – barndog May 30 '16 at 06:06
  • Is it possible to directly set `timescale` (not timestamp)? – sschale May 30 '16 at 06:07
  • Yeah should be, something along the lines of keep the value the same and adjusting the timescale as needed. That's actually a great idea, ill try that out – barndog May 30 '16 at 06:10