CMTime & CMTimeRange
2020-03-19 本文已影响0人
沉江小鱼
这篇文章主要是为了学习记录CMTime,为了之后用到时可以翻阅。
1.CMTime介绍
Core Media定义的一种时间数据类型,很精确。
CMTime实际上就是一个C结构体。它是这样的 :
typedef struct
{
CMTimeValue value; /
CMTimeScale timescale;//
CMTimeFlags flags;
CMTimeEpoch epoch;
} CMTime;
- value
64位有符号整型变量,作为分子 - timescale
32位有符号整型变量,作为分母 - flags
flas的各种值允许我们指出时间戳是正无穷还是负无穷,或者它是由于某种中间计算而四舍五入的
注意:value/timescale = 对应时间 - 秒
value的解释:将value存储为整数值是为了避免我们在浮点示例中看到的类型错误。同样,通过将整个64位分配给分子(value是分子,timescale是分母),我们可以表示90亿亿个不同的正数,最多可以是19个十进制数字,对于每个可能的时间刻度值,没有歧义。
timescale值是多少? 它表示每秒钟划分的“片”的数量。这很重要,因为CMTime对象作为一个整体的精度受到这个量的限制。例如,如果timescale是1,那么对象不能表示小于1秒的时间戳,并且时间戳以1秒为增量。类似地,如果timescale为1000,则每秒钟被细分为1000个片段,value表示我们希望表示的毫秒数。
苹果建议视频的timescale为600,并解释说600是普通视频帧率(24、25和30帧)的倍数。如果需要对音频文件进行精确的采样索引,您可能需要将此值调高到60,000或更高。这64位的好处在于你仍然可以以1/ 60000秒的增量来表示580万年。
2. CMTime方法介绍
2.1 创建CMTime
- CMTime CMTimeMake( int64_t value,int32_t timescale)
CMTime time1 = CMTimeMake(3, 1);
CMTime time2 = CMTimeMake(300, 100);
CMTime time3 = CMTimeMake(1800, 600);
- CMTimeMakeWithSeconds(Float64 seconds, int32_t preferredTimescale)
CMTime time1 = CMTimeMakeWithSeconds(5, 1);
- CMTimeMakeFromDictionary()
NSDictionary *timeData = @{(id)kCMTimeValueKey : @2,
(id)kCMTimeScaleKey : @1,
(id)kCMTimeFlagsKey : @1,
(id)kCMTimeEpochKey : @0};
CMTime t = CMTimeMakeFromDictionary((__bridge CFDictionaryRef)timeData);
2.2 CMTime运算
- 加减
CMTime ts1 = CMTimeMake(3, 1);
CMTime ts2 = CMTimeMake(5, 2);
CMTime result;
result = CMTimeAdd(ts1, ts2);
//{11/2 = 5.500}
result = CMTimeSubtract(ts1, ts2);
//{1/2 = 0.500}
- 比较
CMTime t1 = CMTimeMake(300, 100); // 3 seconds
CMTime t2 = CMTimeMakeWithSeconds(5, 1); // 5 seconds
int32_t r = CMTimeCompare(t1, t2);
NSLog(@"compare: %d",r);
//t1 < t2 => -1
//t1 == t2 => 0
//t1 > ts => 1
或者
NSLog(@"t1 > t2 => %@",CMTIME_COMPARE_INLINE(t1, >, t2) ? @"YES":@"NO");
- 验证CMTIME_IS_VALID()
NSLog(@"ti is valid :%@",CMTIME_IS_VALID(t1) ? @"YES":@"NO");
// ti is valid :YES
2.3 CMTime转换为秒 CMTimeGetSeconds()
CMTime t1 = CMTimeMake(3001, 100);
NSLog(@"second : %f",CMTimeGetSeconds(t1));
//second : 30.010000
2.4 转换为对象NSValue
+ (NSValue *)valueWithCMTime:(CMTime)time;
CMTime structTime = CMTimeMake(1, 3);
NSValue *valueTime = [NSValue valueWithCMTime:structTime];
NSLog(@"%@", valueTime);
//CMTime: {1/3 = 0.333}
structTime = [valueTime CMTimeValue];
//{1/3 = 0.333}
2.5 转换字典NSDictionary
CMTime structTime = CMTimeMake(1, 3);
NSDictionary *timeDict = CFBridgingRelease(CMTimeCopyAsDictionary(structTime, NULL));
NSLog(@"%@", timeDict);
structTime = CMTimeMakeFromDictionary((__bridge CFDictionaryRef)(timeDict));
/*
{
epoch = 0;
flags = 1;
timescale = 3;
value = 1;
}
{1/3 = 0.333}
*/
3. CMTimeRange介绍
时间范围的数据类型:CMTimeRange,由两个CMTime值组成,第一个定义时间范围的起点,第二个定义时间范围的持续时间。
typedef struct
{
CMTime start;
CMTime duration;
} CMTimeRange;
4. CMTimeRange方法
4.1 创建
- CMTimeRangeMake()
CMTimeRange CMTimeRangeMake( CMTime start, CMTime duration)
//创建一个时间范围,从时间轴的5秒位置开始,持续时长5秒
CMTime duration = CMTimeMake(5, 1);
CMTimeRange range = CMTimeRangeMake(duration, duration);
CMTimeRangeShow(range);
//{{5/1 = 5.000}, {5/1 = 5.000}}
- CMTimeRangeFromTimeToTime()
CMTimeRange CMTimeRangeFromTimeToTime( CMTime start, CMTime end )
CMTime beginTime = CMTimeMake(5, 1);
CMTime endTime = CMTimeMake(12, 1);
CMTimeRange rangeTime = CMTimeRangeFromTimeToTime(beginTime, endTime);
CMTimeRangeShow(rangeTime);
//{{5/1 = 5.000}, {7/1 = 7.000}}
4.2 运算
- 定义变量:
CMTime duration = CMTimeMake(5, 1);
CMTimeRange range = CMTimeRangeMake(duration, duration);
CMTimeRangeShow(range);
//{{5/1 = 5.000}, {5/1 = 5.000}}
CMTime beginTime = CMTimeMake(7, 1);
CMTime endTime = CMTimeMake(12, 1);
CMTimeRange rangeTime = CMTimeRangeFromTimeToTime(beginTime, endTime);
//{{7/1 = 7.000}, {5/1 = 5.000}}
- 取交叉时间范围
CMTimeRange intersetionRange = CMTimeRangeGetIntersection(range, rangeTime);
//{{7/1 = 7.000}, {3/1 = 3.000}}
- 取时间范围总和
CMTimeRange unionRange = CMTimeRangeGetUnion(range, rangeTime);
CMTimeRangeShow(unionRange);
//{{5/1 = 5.000}, {7/1 = 7.000}}
4.3 转换为对象NSValue
+ (NSValue *)valueWithCMTimeRange:(CMTimeRange)timeRange
CMTimeRange structTimeRange = CMTimeRangeMake(kCMTimeZero, kCMTimePositiveInfinity);
NSValue *valueTimeRange = [NSValue valueWithCMTimeRange:structTimeRange];
NSLog(@"%@", valueTimeRange);
//CMTimeRange: {{0/1 = 0.000}, {+INFINITY}}
structTimeRange = [valueTimeRange CMTimeRangeValue];
CMTimeRangeShow(structTimeRange);
//{{0/1 = 0.000}, {+INFINITY}}
4.4 转换成字典NSDictionary
NSDictionary *timeRangeDict = CFBridgingRelease(CMTimeRangeCopyAsDictionary(structTimeRange, NULL));
NSLog(@"%@", timeRangeDict);
structTimeRange = CMTimeRangeMakeFromDictionary((__bridge CFDictionaryRef)(timeRangeDict));
CMTimeRangeShow(structTimeRange);
/*
{
duration = {
epoch = 0;
flags = 5;
timescale = 0;
value = 0;
};
start = {
epoch = 0;
flags = 1;
timescale = 1;
value = 0;
};
}
{{0/1 = 0.000}, {+INFINITY}}
*/
参考文章:
https://blog.csdn.net/fengzhixinfei/article/details/80729346
https://warrenmoore.net/understanding-cmtime