CMTime CMTimeRange CMTimeMapping

在使用 AVFoundation 框架处理多媒体资源时,通常会用到一些在 CoreMedia 框架中定义的结构体,
这里对其中描述时间的类型 CMTime 、CMTimeRange 、CMTimeMapping 进行简单的小结。

CMTime

概述

CMTime 是一个结构体,其用来表示一个有理数,描述一个时刻或时段。在结构体中有4个成员,如下:

typedef struct
{
CMTimeValue value;
CMTimeScale timescale;
CMTimeFlags flags;
CMTimeEpoch epoch;
} CMTime;

该结构体类型的变量表示的时刻或时段的值为 value/timescale ,单位是秒。

timescale 这个分母值的含义是将 1 秒钟分成了多少个单元
value 这个分子值的含义是所表示的时刻或时段共计占用了多少个单元
那么 1/timescale 表示一个单元占用了多长时间,这个时间小于 1 秒,而 value * (1/timescale) 即表示整个结构体变量所表示的时间长度。

flags 该标识可以表示当前变量表示的时刻或时段是否有效、是否是准确值等,可取的值如下:

  • kCMTimeFlags_Valid = 1UL<<0 该值必需设置,否则当前变量会被认为是无效的
  • kCMTimeFlags_HasBeenRounded = 1UL<<1 表示当前变量是约数并不是原始的精确值,或者是由其他非精确的值生成的
  • kCMTimeFlags_PositiveInfinity = 1UL<<2 表示当前变量为正无穷
  • kCMTimeFlags_NegativeInfinity = 1UL<<3 表示当前变量为负无穷
  • kCMTimeFlags_Indefinite = 1UL<<4 表示当前变量未定义
  • kCMTimeFlags_ImpliedValueFlagsMask = kCMTimeFlags_PositiveInfinity | kCMTimeFlags_NegativeInfinity | kCMTimeFlags_Indefinite 表示正负无穷或未定义

epoch 可以用来区分两个表示相同时间的变量,如循环递增的时间,这个值可以区分不同循环内的相同的时间的变量。

常量

在 CoreMedia 框架中,提供了一些常量,用来表示特殊的 CMTime 值。

  • kCMTimeInvalid 用来初始化无效的 CMTime 值,该变量的每个成员的值都是 0
  • kCMTimeZero 用来表示时间为 0 ,该变量的成员值为 value=0,timescale=1,flags=kCMTimeFlags_Valid,epoch=0
  • kCMTimePositiveInfinity 表示时间为正无穷,flags=5(即 kCMTimeFlags_Valid|kCMTimeFlags_PositiveInfinity),其他成员的值都是 0
  • kCMTimeNegativeInfinity 表示时间为负无穷,flags=9(即 kCMTimeFlags_Valid|kCMTimeFlags_NegativeInfinity),其他成员的值都是 0
  • kCMTimeIndefinite 表示时间未定义,flags=17(即 kCMTimeFlags_Valid|kCMTimeFlags_Indefinite),其他成员的值都是 0

要判断已知的变量是否等于上述的变量时,不可以使用 “==” 进行判断,而是要使用框架中提供的宏,在这些宏定义中,都是对变量的成员 flags 值进行了判断。

  • CMTIME_IS_VALID(time) 判断已知的 CMTime 变量是否是有效的
  • CMTIME_IS_INVALID(time) 判断已知的 CMTime 变量是否是无效的
  • CMTIME_IS_POSITIVE_INFINITY(time) 判断已知的 CMTime 变量是否表示时间正无穷
  • CMTIME_IS_NEGATIVE_INFINITY(time) 判断已知的 CMTime 变量是否表示时间负无穷
  • CMTIME_IS_INDEFINITE(time) 判断已知的 CMTime 变量是否是未定义的
  • CMTIME_IS_NUMERIC(time) 判断已知的 CMTime 变量是否是明确的时间,而不是正负无穷或未定义
  • CMTIME_HAS_BEEN_ROUNDED(time) 判断已知的 CMTime 变量是否是约数

函数

CMTime CMTimeMake(int64_t value,int32_t timescale);
CMTime CMTimeMakeWithEpoch(int64_t value,int32_t timescale,int64_t epoch);

上面两个是生成 CMTime 变量的常见函数,通过指定相应的成员变量的值来生成相应的变量。

CMTime CMTimeMakeWithSeconds(Float64 seconds,int32_t preferredTimescale)

除了指定相应的成员变量来生成 CMTime 变量外,还可以通过指定时间和时间粒度来生成变量。返回的变量,其成员 epoch 被设置为 0 ,而 value 的值则是 seconds 与 preferredTimescale 的乘积,所以 value 的值可能会溢出。

当发生溢出时,会将 preferredTimescale 的值自动减半,直到 value 的值不再溢出,或者 preferredTimescale 减到 1 ,如果减到 1 后,value 仍然溢出,则这个变量表示无穷大。

由于提供的时间是浮点型,而计算得到的成员变量 value 是整型值,所以计算时,value 的值可能含有小数,如果有小数部分,便需要舍入。如此,使用成员变量再次计算得到的时间值与原来提供的时间值不相等,所以对于这种情况,返回值的成员变量 flags 中,kCMTimeFlags_HasBeenRounded 标识会被设置。

Float64 CMTimeGetSeconds(CMTime time);
使用该方法将 CMTime 类型的变量转化为时间值,如果变量本身表示的值无效或是正负无穷值,则返回 NaN 或 +Inf 、-Inf 。

CMTime CMTimeConvertScale(CMTime time,int32_t newTimescale,CMTimeRoundingMethod method);

该方法可以修改已知的 CMTime 类型变量的 timescale 成员变量的值,计算 value 的值时可能需要舍入小数部分,所以调用函数时要指定舍入方法。

CMTimeRoundingMethod 有以下可取值:

  • kCMTimeRoundingMethod_RoundHalfAwayFromZero = 1, 表示四舍五入
  • kCMTimeRoundingMethod_RoundTowardZero = 2, 始终舍弃小数部分
  • kCMTimeRoundingMethod_RoundAwayFromZero = 3, 始终进1
  • kCMTimeRoundingMethod_QuickTime = 4, 当时间粒度值变大,则应进1,反之,时间粒度值变小,舍弃小数部分,而当表示的时间是负的时,舍弃小数后,value 若为 0 ,应将其置为 -1
  • kCMTimeRoundingMethod_Default = kCMTimeRoundingMethod_RoundHalfAwayFromZero
//转换后 time2 的 value 为 1
CMTime time1 = CMTimeMake(1, 4);
CMTime tiem2 = CMTimeConvertScale(time, 2, kCMTimeRoundingMethod_RoundHalfAwayFromZero); //转换后 time2 的 value 为 0
CMTime time1 = CMTimeMake(1, 5);
CMTime tiem2 = CMTimeConvertScale(time, 2, kCMTimeRoundingMethod_RoundHalfAwayFromZero); //转换后 time2 的 value 为 0
CMTime time1 = CMTimeMake(1, 5);
CMTime tiem2 = CMTimeConvertScale(time, 2, kCMTimeRoundingMethod_QuickTime); //转换后 time2 的 value 为 -1
CMTime time1 = CMTimeMake(-1, 5);
CMTime tiem2 = CMTimeConvertScale(time, 2, kCMTimeRoundingMethod_QuickTime);

CMTime CMTimeAdd( CMTime addend1,CMTime addend2);

CMTime CMTimeSubtract(CMTime minuend,CMTime subtrahend);

两个 CMTime 类型的变量之和或之差,得到的结果的 timescale 的值是两个变量的 timescale 的最小公倍数。如果这个公倍数大于 kCMTimeMaxTimescale 这个值,那么 timescale 就使用 kCMTimeMaxTimescale 这个值。在转换这个 timescale 的过程中,计算 value 的值时采用默认的舍入方法,如果 value 的值溢出,便减半 timescale 再进行计算,判断其是否溢出,若溢出,再次减半,直到其值为 1 ,如果仍然溢出,则返回的结果为无穷大。

CMTime CMTimeMultiply(CMTime time,int32_t multiplier);

CMTime CMTimeMultiplyByFloat64(CMTime time,Float64 multiplier);

扩大已知的 time 的倍数,value 的值扩大 multiplier 倍,如果溢出,持续减半 timescale 的值,直到不再溢出或为 1 ,如果为 1 时仍然溢出,返回的值表示无穷大。

CMTime CMTimeMultiplyByRatio(CMTime time,int32_t multiplier,int32_t divisor)

用已知的 time 的 value 值乘以 multiplier 再除以 divisor 得到新的 value 值,如果 value 的值发生溢出,那么 timescale 便会发生转变。

int32_t CMTimeCompare(CMTime time1,CMTime time2)

两个时间比较,遵循的规则:负无穷 < 具体时间 < 未定义 < 正无穷 < 无效时间

具体的两个时间比较大小时,其成员 epoch 也参与比较,epoch 较大的时间较大。

time1 > time2 ,返回值为 1
time1 < time2 ,返回值为 -1
time1 = time2 ,返回值为 0
框架中提供了一个宏 CMTIME_COMPARE_INLINE(time1, comparator, time2) ,通过提供比较运算符(>、>=、=、<、=<)comparator 来获取 time1 与 time2 的大小关系。

CMTime CMTimeMinimum(CMTime time1,CMTime time2)
返回 time1 与 time2 中较小的值

CMTime CMTimeMaximum(CMTime time1,CMTime time2)
返回 time1 与 time2 中较大的值

CMTime CMTimeAbsoluteValue(CMTime time)

返回 time 的绝对值

CFDictionaryRef CM_NULLABLE CMTimeCopyAsDictionary(CMTime time,CFAllocatorRef CM_NULLABLE allocator)

CMTime CMTimeMakeFromDictionary(CFDictionaryRef CM_NULLABLE dict)

上面两个方法,可以将 CMTime 类型的变量转化为 CFDictionaryRef 类型的变量,或者从已经转化的变量中生成一个 CMTime 类型的变量。在 CFDictionary 中,它应包含键值:kCMTimeValueKey 、kCMTimeScaleKey 、kCMTimeEpochKey 、kCMTimeFlagsKey 分别对应 CMTime 的各个成员变量。

CFStringRef CM_NULLABLE CMTimeCopyDescription(CFAllocatorRef CM_NULLABLE allocator,CMTime time)

void CMTimeShow(CMTime time)

上面的两个方法,可以获取 CMTime 类型变量的字符串描述,或者直接将字符串描述打印出来。

CMTimeRange

概述

CMTimeRange 是用来表示一个时间范围的结构体变量,它的两个成员变量都是 CMTime 类型的变量,分别表示时间范围的开始时刻和时间范围的持续时长,所以开始时刻与持续时长的和得到的时刻并不属于该类型表示的时间范围。

typedef struct
{
CMTime start;
CMTime duration;
} CMTimeRange;

可以使用 kCMTimeRangeZero 、kCMTimeRangeInvalid 分别表示时间范围为 0 和无效的的 CMTimeRange 类型变量。

对于有效的 CMTimeRange 类型变量,它的两个 CMTime 成员变量都必须是有效的,并且 duration.epoch 必须是 0 ,duration.value 的值必须是非负的。可以直接使用框架中提供的宏定义,进行判断。

  • CMTIMERANGE_IS_VALID(range) 当 start 、duration 是有效的,且 duration.epoch == 0 且 duration.value >= 0 时,返回 true
  • CMTIMERANGE_IS_INVALID(range) 返回的真假值与上面的宏返回的值相反
  • CMTIMERANGE_IS_INDEFINITE(range) 当 range 为有效值,且 range.start 和 range.duration 中至少有一个为未定义时,这个宏返回 true
  • CMTIMERANGE_IS_EMPTY(range) 当 range 为有效值,且 range.duration 为 kCMTimeZero 时,这个宏返回 true

函数

CMTimeRange CMTimeRangeMake(CMTime start,CMTime duration)
创建一个表示时间范围的变量

CMTimeRange CMTimeRangeGetUnion(CMTimeRange range1,CMTimeRange range2)

返回两个时间范围的最小并集

CMTimeRange CMTimeRangeGetIntersection(CMTimeRange range1,CMTimeRange range2)

返回两个时间范围的最大交集

Boolean CMTimeRangeEqual(CMTimeRange range1,CMTimeRange range2)

返回两个时间范围是否相等

Boolean CMTimeRangeContainsTime(CMTimeRange range,CMTime time)

返回指定的时间范围内是否包含指定的时间

Boolean CMTimeRangeContainsTimeRange(CMTimeRange range1,CMTimeRange range2)

返回指定的时间范围 range1 是否包含 指定的时间范围 range2

CMTime CMTimeRangeGetEnd(CMTimeRange range)

返回指定时间范围的结束时间,这个时间是不包含在时间范围内的,即

CMTimeRangeContainsTime(range, CMTimeRangeGetEnd(range)) 的返回值总是 false 。

CMTime CMTimeMapTimeFromRangeToRange(CMTime t,CMTimeRange fromRange,CMTimeRange toRange )

将指定的时间 t 根据时间范围 fromRange 和 toRange 进行转换,如果 t 是 fromRange 的开始或者结束时间,那么转换后,其就是 toRange 的开始或结束时间。如果 t 是其他时间,那么按照公式
result = (t-fromRange.start)*(toRange.duration/fromRange.duration)+toRange.start
进行计算。

CMTime CMTimeClampToRange(CMTime time,CMTimeRange range)

返回的是指定的时间范围内 range 中距离指定时间 time 最近的时间。如果 time 的时间小于 range 的开始时间,那么返回的就是 range 的开始时间,如果 time 在 range 范围内,那么返回其本身,如果 time 是 range 的结束时间或结束时间之后,那么返回的都是 range 的结束时间(即使该结束时间不属于 range 表示的时间范围之内)。

CMTime CMTimeMapDurationFromRangeToRange(CMTime dur,CMTimeRange fromRange,CMTimeRange toRange )

将指定的时间范围的持续时长根据时间范围 fromRange 和 toRange 进行转换,实际是对持续时长进行了缩小或放大,其计算公式为
result = dur*(toRange.duration/fromRange.duration)

CMTimeRange CMTimeRangeFromTimeToTime(CMTime start,CMTime end)
根据指定的开始时间和结束时间构建一个表示时间范围的变量。

CFDictionaryRef CM_NULLABLE CMTimeRangeCopyAsDictionary(CMTimeRange range,CFAllocatorRef CM_NULLABLE allocator)

CMTimeRange CMTimeRangeMakeFromDictionary(CFDictionaryRef CM_NONNULL dict)

上面的方法实现了 CMTimeRange 类型变量与 CFDictionaryRef 变量的相互转换,CFDictionary 中的键 kCMTimeRangeStartKey 、kCMTimeRangeDurationKey 分别对应着 CMTimeRange 中的成员。

CFStringRef CM_NULLABLE CMTimeRangeCopyDescription(CFAllocatorRef CM_NULLABLE allocator,CMTimeRange range)

void CMTimeRangeShow(CMTimeRange range)

上面的两个方法,可以获取 CMTimeRange 类型变量的字符串描述,或者直接将字符串描述打印出来。

CMTimeMapping

概述

CMTimeMapping 是一个描述媒体资源时间线映射关系的结构体变量,其包含两个 CMTimeRange 类型的成员变量。

typedef struct
{
CMTimeRange source;
CMTimeRange target;
} CMTimeMapping;
  • source 表示的是源资源的时间线范围,包括开始的时刻和持续的时长,如果开始时间为 kCMTimeInvalid ,表示没有资源的编辑信息,即该变量为空。
  • target 表示的是资源目标的时间线,包含开始时间和持续时长,如果 source 和 target 的 duration 不同,那么资源在播放时,速度为 source.duration/target.duration 以保证资源播放完整。在框架中,使用 kCMTimeMappingInvalid 来表示无效的 CMTimeMapping 类型变量,可以使用 CMTIMEMAPPING_IS_VALID(mapping) 、CMTIMEMAPPING_IS_INVALID(mapping) 来判断变量 mapping 是否有效(mapping.target 有效即可),或者使用 CMTIMEMAPPING_IS_EMPTY(mapping) 来判断 mapping 是否为空(mapping 有效且 mapping.source.start 为 kCMTimeInvalid)

函数

CMTimeMapping CMTimeMappingMake(CMTimeRange source,CMTimeRange target)

创建一个映射关系变量,提供的 source 和 target 的 epoch 的值必需为 0 ,否则将返回一个无效值。

CMTimeMapping CMTimeMappingMakeEmpty(CMTimeRange target)

创建一个空的变量,提供的 target 的 epoch 必需时 0 ,否则将返回一个无效值。

CFDictionaryRef CM_NULLABLE CMTimeMappingCopyAsDictionary(CMTimeMapping mapping,CFAllocatorRef CM_NULLABLE allocator)

CMTimeMapping CMTimeMappingMakeFromDictionary(CFDictionaryRef CM_NONNULL dict)

上面的方法实现了 CMTimeMapping 类型变量与 CFDictionaryRef 变量的相互转换,CFDictionary 中的键 kCMTimeMappingSourceKey 、kCMTimeMappingTargetKey 分别对应着 CMTimeMapping 中的成员。

CFStringRef CM_NULLABLE CMTimeMappingCopyDescription(CFAllocatorRef CM_NULLABLE allocator,CMTimeMapping mapping)
void CMTimeMappingShow(CMTimeMapping mapping)

转载自:https://blog.csdn.net/u011374318/article/details/78882092

CGTime CMTimeRange CMTimeMapping 小结的更多相关文章

  1. 从零开始编写自己的C#框架(26)——小结

    一直想写个总结,不过实在太忙了,所以一直拖啊拖啊,拖到现在,不过也好,有了这段时间的沉淀,发现自己又有了小小的进步.哈哈...... 原想框架开发的相关开发步骤.文档.代码.功能.部署等都简单的讲过了 ...

  2. Python自然语言处理工具小结

    Python自然语言处理工具小结 作者:白宁超 2016年11月21日21:45:26 目录 [Python NLP]干货!详述Python NLTK下如何使用stanford NLP工具包(1) [ ...

  3. java单向加密算法小结(2)--MD5哈希算法

    上一篇文章整理了Base64算法的相关知识,严格来说,Base64只能算是一种编码方式而非加密算法,这一篇要说的MD5,其实也不算是加密算法,而是一种哈希算法,即将目标文本转化为固定长度,不可逆的字符 ...

  4. iOS--->微信支付小结

    iOS--->微信支付小结 说起支付,除了支付宝支付之外,微信支付也是我们三方支付中最重要的方式之一,承接上面总结的支付宝,接下来把微信支付也总结了一下 ***那么首先还是由公司去创建并申请使用 ...

  5. iOS 之UITextFiled/UITextView小结

    一:编辑被键盘遮挡的问题 参考自:http://blog.csdn.net/windkisshao/article/details/21398521 1.自定方法 ,用于移动视图 -(void)mov ...

  6. K近邻法(KNN)原理小结

    K近邻法(k-nearst neighbors,KNN)是一种很基本的机器学习方法了,在我们平常的生活中也会不自主的应用.比如,我们判断一个人的人品,只需要观察他来往最密切的几个人的人品好坏就可以得出 ...

  7. scikit-learn随机森林调参小结

    在Bagging与随机森林算法原理小结中,我们对随机森林(Random Forest, 以下简称RF)的原理做了总结.本文就从实践的角度对RF做一个总结.重点讲述scikit-learn中RF的调参注 ...

  8. Bagging与随机森林算法原理小结

    在集成学习原理小结中,我们讲到了集成学习有两个流派,一个是boosting派系,它的特点是各个弱学习器之间有依赖关系.另一种是bagging流派,它的特点是各个弱学习器之间没有依赖关系,可以并行拟合. ...

  9. scikit-learn 梯度提升树(GBDT)调参小结

    在梯度提升树(GBDT)原理小结中,我们对GBDT的原理做了总结,本文我们就从scikit-learn里GBDT的类库使用方法作一个总结,主要会关注调参中的一些要点. 1. scikit-learn ...

  10. 梯度提升树(GBDT)原理小结

    在集成学习之Adaboost算法原理小结中,我们对Boosting家族的Adaboost算法做了总结,本文就对Boosting家族中另一个重要的算法梯度提升树(Gradient Boosting De ...

随机推荐

  1. (0514)python学习-思维导图

  2. Win10家庭版找不到组策略gpedit.msc怎么办

    Win10家庭版找不到组策略gpedit.msc怎么办 @echo off pushd "%~dp0" dir /b %systemroot%\Windows\servicing\ ...

  3. [转]idea 试用30天“无限续费”idea破解

    首先打开idea设置 左上角点击file-->setting-->Plugins   https://plugins.zhile.io 然后点击 确定 ("OK") 点 ...

  4. 【服务器数据恢复】RAID6数据恢复案例

    服务器数据恢复环境:一台Web服务器中有一组由8块磁盘组建的raid6磁盘阵列,用来运行数据库和存储普通办公文件. 服务器故障:服务器raid6磁盘阵列中有两块硬盘离线,但是管理员没有注意到这种情况, ...

  5. 关于filter_input函数

    PHP: filter_input <?php $search_html = filter_input(INPUT_GET, 'search', FILTER_SANITIZE_SPECIAL_ ...

  6. synchronized与CAS

    参考:java3y<对线面试官> synchronized synchronized是⼀种互斥锁,⼀次只能允许⼀个线程进⼊被锁住的代码块synchronized是Java的⼀个关键字,它能 ...

  7. 力扣1143. 最长公共子序列(dp)

    给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度.如果不存在 公共子序列 ,返回 0 . 一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符 ...

  8. http 请求头 content-type 字段值

    Content-type 定义了 http 请求的数据类型. 如果设置在请求头中,则定义的是请求体的数据类型: 如果设置在响应头中,则定义的是响应体的数据类型: 请求头--Request-Header ...

  9. hbase修改表TTL

    创建表时可以指定TTL create 'test_lwt',{NAME=>'d',TTL=>3600}  设置test_lwt表数据TTL为3600秒 修改已存在的表TTL disable ...

  10. python之路3:文件操作和函数基础

    文件操作 字符编码解码 函数基础 内置函数 一.文件操作 对文件操作流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 打开文件的模式有: r,只读模式(默认). w,只写 ...