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/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 time1 = CMTimeMake(3, 1);
CMTime time2 = CMTimeMake(300, 100);
CMTime time3 = CMTimeMake(1800, 600);
CMTime time1 = CMTimeMakeWithSeconds(5, 1);
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");
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 创建
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}}
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

上一篇 下一篇

猜你喜欢

热点阅读