/*!
@typedef CMTime
@abstract Rational time value represented as int64/int32.
*/
typedef 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. */
CMTimeFlags flags; /*! @field flags The flags, eg. kCMTimeFlags_Valid, kCMTimeFlags_PositiveInfinity, etc. */
CMTimeEpoch epoch; /*! @field epoch Differentiates between equal timestamps that are actually different because
of looping, multi-item sequencing, etc.
Will be used during comparison: greater epochs happen after lesser ones.
Additions/subtraction is only possible within a single epoch,
however, since epoch length may be unknown/variable. */
} CMTime;
CMTime
是专门针对视频时间的一种数据类型,首先我们探讨一下,有两个视频AB
,A
视频共15帧
,播放速度为5fps
(即每秒播放5帧),那么A的持续时间为3s
,同样有B
视频,共60帧
,播放速率为20fps
,那么B的持续时间也为3s
。既然两个视频都是3s
的持续时长,那我们怎么用一种时间格式表示他们之间的差异,CMTime
就适用于这种场景。
现在再去看注释中的/*! @field value The value of the CMTime. value/timescale = seconds. */
是否理解了value
和timescale
的意义了。
CM_EXPORT
CMTime CMTimeMake(
int64_t value, /*! @param value Initializes the value field of the resulting CMTime. */
int32_t timescale) /*! @param timescale Initializes the timescale field of the resulting CMTime. */
__OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0);
在VideoToolBox
中,我们通常需要进行编码视频数据,或许我们都有如下相似的编码代码:
self->_frameCount++;
// Create properties
CMTime pts = CMTimeMake(self->_frameCount, _configuration.videoFrameRate);
VTEncodeInfoFlags flags;
CMTime dur = CMTimeMake(1, (int32_t)_configuration.videoFrameRate);
NSNumber *timeStamp = @(CACurrentMediaTime()*1000);
NSDictionary *properties = nil;
if (self->_frameCount % (int32_t)_configuration.videoMaxKeyframeInterval == 0) {
properties = @{(__bridge NSString *)kVTEncodeFrameOptionKey_ForceKeyFrame: @YES};
}
// Pass it to the encoder
if (!self->_encodingSession) {
BOOL isSuccess = [self createSession];
if (!isSuccess) {
GSLog(@"createSession failed return");
}
}
OSStatus status = VTCompressionSessionEncodeFrame(self->_encodingSession, pixelBuffer, pts, dur, (__bridge CFDictionaryRef)properties, (__bridge_retained void*)timeStamp, &flags);
CMTime pts = CMTimeMake(self->_frameCount, _configuration.videoFrameRate);
这里的CMTimeMake
生成了一个CMTime,即产生了一个 帧数/FPS 的时间,给了VideoToolBox
.
CMTime dur = CMTimeMake(1, (int32_t)_configuration.videoFrameRate);
这个即表示播放1帧的所需要的时间,对吧?FPS的倒数嘛,fps=5
,每秒5帧,那么1帧占用0.2s
timescale到底代表什么喃?它表示1秒的时间被分成了多少份。因为整个CMTime的精度是由它控制的所以它显的尤为重要。例如,当timescale为1的时候,CMTime不能表示1秒一下的时间和1秒内的增长。相同的,当timescale为1000的时候,每秒钟便被分成了1000份,CMTime的value便代表了多少毫秒。
怎么去选取适当的timescale喃?苹果的对视频的建议是timescale=600,因为600是常见视频每秒帧数 ( 24,25,30FPS )的公倍数,如果是音频,你可以用60,000或更高的timescale。用64位integer的value来计算,你仍能够表示580万年内的每1/60,000增长,这是非常精确的。
摘自 https://www.jianshu.com/p/d6f9d7e493b6
CMTime CMTimeMakeWithSeconds(Float64 seconds, int32_t preferredTimescale)
这里的preferredTimescale
它表示1
秒的时间被分成了多少份
例如CMTimeMakeWithSeconds(0.5,1)
生成的时间为0,因为1
是最小的计算单元