音视频开发-CMTime的运用

CMTime

/*!
	@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的意义了。

CMTimeMake

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

CMTimeMakeWithSeconds

CMTime CMTimeMakeWithSeconds(Float64 seconds, int32_t preferredTimescale)

这里的preferredTimescale它表示1秒的时间被分成了多少份
例如CMTimeMakeWithSeconds(0.5,1)生成的时间为0,因为1是最小的计算单元

其他待续

猜你喜欢

转载自blog.csdn.net/shengpeng3344/article/details/93985465