CGTime CMTimeRange CMTimeMapping 小结
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 小结的更多相关文章
- 从零开始编写自己的C#框架(26)——小结
一直想写个总结,不过实在太忙了,所以一直拖啊拖啊,拖到现在,不过也好,有了这段时间的沉淀,发现自己又有了小小的进步.哈哈...... 原想框架开发的相关开发步骤.文档.代码.功能.部署等都简单的讲过了 ...
- Python自然语言处理工具小结
Python自然语言处理工具小结 作者:白宁超 2016年11月21日21:45:26 目录 [Python NLP]干货!详述Python NLTK下如何使用stanford NLP工具包(1) [ ...
- java单向加密算法小结(2)--MD5哈希算法
上一篇文章整理了Base64算法的相关知识,严格来说,Base64只能算是一种编码方式而非加密算法,这一篇要说的MD5,其实也不算是加密算法,而是一种哈希算法,即将目标文本转化为固定长度,不可逆的字符 ...
- iOS--->微信支付小结
iOS--->微信支付小结 说起支付,除了支付宝支付之外,微信支付也是我们三方支付中最重要的方式之一,承接上面总结的支付宝,接下来把微信支付也总结了一下 ***那么首先还是由公司去创建并申请使用 ...
- iOS 之UITextFiled/UITextView小结
一:编辑被键盘遮挡的问题 参考自:http://blog.csdn.net/windkisshao/article/details/21398521 1.自定方法 ,用于移动视图 -(void)mov ...
- K近邻法(KNN)原理小结
K近邻法(k-nearst neighbors,KNN)是一种很基本的机器学习方法了,在我们平常的生活中也会不自主的应用.比如,我们判断一个人的人品,只需要观察他来往最密切的几个人的人品好坏就可以得出 ...
- scikit-learn随机森林调参小结
在Bagging与随机森林算法原理小结中,我们对随机森林(Random Forest, 以下简称RF)的原理做了总结.本文就从实践的角度对RF做一个总结.重点讲述scikit-learn中RF的调参注 ...
- Bagging与随机森林算法原理小结
在集成学习原理小结中,我们讲到了集成学习有两个流派,一个是boosting派系,它的特点是各个弱学习器之间有依赖关系.另一种是bagging流派,它的特点是各个弱学习器之间没有依赖关系,可以并行拟合. ...
- scikit-learn 梯度提升树(GBDT)调参小结
在梯度提升树(GBDT)原理小结中,我们对GBDT的原理做了总结,本文我们就从scikit-learn里GBDT的类库使用方法作一个总结,主要会关注调参中的一些要点. 1. scikit-learn ...
- 梯度提升树(GBDT)原理小结
在集成学习之Adaboost算法原理小结中,我们对Boosting家族的Adaboost算法做了总结,本文就对Boosting家族中另一个重要的算法梯度提升树(Gradient Boosting De ...
随机推荐
- flutter Slivers
一. Slivers 我们考虑一个这样的布局:一个滑动的视图中包括一个标题视图(HeaderView),一个列表视图(ListView),一个网格视图(GridView). 我们怎么可以让它们做到统一 ...
- Jmeter学习:文件类函数
一.__StringFromFile 功能介绍: 从文件中读取一行数据,所有线程共享行数,依次读取,默认路径为$JMETER_HOME/bin/ ${__StringFromFile(参数 1,参数 ...
- JAVA学习笔记-08
package: 对类文件进行分类管理 给类提供多层命令空间 写在程序文件第一行,包名全部字母小写 类名的全称是 包名.类名 包也是一种封装形式. 包与包之间的访问: 包与包之间进行访问,被访问的包 ...
- 高级测试工程师&资深测试工程师应实现的价值
一 技能 自动化: 接口自动化 web ui 自动化(selenium) 移动端自动化 二 项目支撑----项目集,不是单个项目(大小项目) 1.具体功能web 2.小程序 3.移动端 三 项目职责 ...
- Oversampling Techniques
ADC Operation Improving ADC Resolution 总结 根据奈奎斯特采样定理,Fsample >= 2 * Fsignal 在频域中,过采样能够降低白噪声功率谱密度 ...
- js过滤掉指定html标签
替换标签 var str = "<p><span style='color:#ccc;'>这是测试标签</span><span>这是测试htm ...
- 《TensorFlow+Keras自然语言处理实战》图书介绍
#好书推荐##好书奇遇季#<TensorFlow+Keras自然语言处理实战>.当当京东天猫均有发售. https://item.jd.com/12788707.html 文后有本书配套源 ...
- git clone 指定分支/指定commit
方法一 下载整个branch及历史记录,文件较大,耗时 git clone --depth 1 [git-url] -b [branch-name] git reset --hard [commit- ...
- php 图片加水印插件
问题:背景透明的水印图片,在加到原图上后不显示,待解决 <?php /** * 图片加水印(适用于png/jpg/gif格式) * * @author flynetcn * * @param $ ...
- docker-compose 搭建 redis 集群
准备配置文件 bind 0.0.0.0 # redis端口 port ${PORT} requirepass redispwd # 关闭保护模式 protected-mode no # 开启集群 cl ...