时间和媒体的表示

AV Foundation 框架中用 AVAsset 表示基于时间的视听数据, 比如电影文件或视频流. AVAsset 的结构决定了 AV Foundation 框架大部分的工作方式. AV Foundation 框架中使用的一些用来代表时间和媒体的底层数据结构来源于 Core Media 框架.

Asset的表示

AVAssetarrow-up-right 是 AV Foundation 框架的核心关键类, 它提供了对视听数据的格式无关的抽象. 类之间的关系如下图所示. 大部分情况下, 使用的都是这些类的子类: 使用 composition 的子类创建新的 asset, 使用AVURLAsset根据一个指定的 URL 创建 asset.

一个 asset 包含一组 track, 每个 track 都有特定媒体类型, 包括但不限于 audio, video, text, closed captions 以及 subtitles. Asset 对象提供整个资源的信息, 比如时长和标题. Asset 对象也可能包含元数据 (metadata), metadata 由 AVMetadataItemarrow-up-right 类表示.

如下图所示, 一个 track 由 AVAssetTrackarrow-up-right 类表示. 简单场景下, 一个 track 代表 audio component, 另一个 track 代表 video component; 复杂场景下, 可能有多个 audio 和 video 重叠的 track.

一个 track 包含多个属性, 比如类型 (video or audio), 视觉或听觉特性, 元数据, 以及时间轴 (表现在其父 asset 中). 此外, track 还包含一个描述格式的数组. 这个数组中的元素为CMFormatDescription对象 (参见 CMFormatDescriptionRefarrow-up-right), 用来描述 track 包含的媒体格式信息.

一个 track 可能被分为几段, 每一段由一个 AVAssetTrackSegmentarrow-up-right 对象表示. 一个AVAssetTrackSegment对象就是一个由资源数据到 track 时间轴的映射.

时间的表示

AV Foundation 框架中的时间由一个 Core Media 框架中的数据结构表示.

用 CMTime 表示一段时间

CMTimearrow-up-right 是一个以有理数表示时间的 C 语言结构体, 用一个int64_t类型作为分子, 一个int32_t类型作为分母. 从概念上来看, 时间段 (timescale) 描述了一秒中包含多少个时间单元. 如果 timescale 等于 4, 则每个时间单元代表四分之一秒; 果 timescale 等于 10, 则每个时间单元代表十分之一秒, 以此类推.

除了用来表示时间, CMTime还可以用来表示非数值的值: 正无穷大, 负无穷大, 不确定.

使用 CMTime

使用方法 CMTimeMakearrow-up-right 或者 CMTimeMakeWithSecondsarrow-up-right 创建一个时间.

更多详细信息参见 CMTime Referencearrow-up-right.

CMTime 的特殊值

Core Media 框架提供了一些常量: kCMTimeZero, kCMTimeInvalid,kCMTimePositiveInfinitykCMTimeNegativeInfinity. CMTime结构体能够进行很多操作, 比如要判断一个时间是否有效, 可以使用一些定义好的宏, 例如 CMTIME_IS_INVALIDarrow-up-right, CMTIME_IS_POSITIVE_INFINITYarrow-up-right 或者 CMTIME_IS_INDEFINITEarrow-up-right.

不能将 CMTime 结构体与kCMTimeZero直接进行比较.

将 CMTime 转换为对象

如果要在注释或者Core Foundation容器中使用 CMTime, 使用方法 CMTimeCopyAsDictionaryarrow-up-rightCMTimeMakeFromDictionaryarrow-up-right 可以在 CMTime 结构体和CFDictionary类型 (参见 CFDictionaryRefarrow-up-right) 之间进行相互转换. 使用方法 CMTimeCopyDescriptionarrow-up-right 可以获取 CMTime 结构体的字符串描述.

循环次数 (Epochs)

CMTime结构体中的 epoch 通常被设置为 0. 但是你可以使用这个值来区分不同循环次数中的同一个时间点.

用 CMTimeRange 表示一个时间范围

CMTimeRangearrow-up-right 是一个 C 语言结构体, 包含两个CMTime类型的属性: 起始时间start和时长duration. 一个时间范围并不包含start加上duration得到的时间.

使用方法 CMTimeRangeMakearrow-up-rightCMTimeRangeFromTimeToTimearrow-up-right 创建一个时间范围, 但是存在一些限制:

  • CMTimeRange不能跨过epoch

  • 只能对startepoch值相同的 CMTimeRange 进行相互操作

  • durationepoch值应该一直为 0, startepoch值为非负

处理 CMTimeRange

Core Media 框架提供了一个时间范围是否包含某个时间点或者其他时间范围的方法, 以及判断两个时间范围是否相同, 对两个时间范围进行交集和并集运算的方法. 例如, CMTimeRangeContainsTimearrow-up-right, CMTimeRangeEqualarrow-up-right, CMTimeRangeContainsTimeRangearrow-up-rightCMTimeRangeGetUnionarrow-up-right.

注意下面的表达式永远返回 false:

更多相关的详细信息, 参见 CMTimeRange Referencearrow-up-right.

CMTimeRange 的特殊值

Core Media 提供了一个表示空范围的常量和一个表示无效范围的常量: kCMTimeRangeZerokCMTimeRangeInvalid. 可以使用以下这些宏对 CMTimeRange 的特殊值进行判断: CMTIMERANGE_IS_VALIDarrow-up-right, CMTIMERANGE_IS_INVALIDarrow-up-right, CMTIMERANGE_IS_EMPTYarrow-up-right, CMTIMERANGE_IS_EMPTYarrow-up-right.

不能将 CMTimeRange 结构体与kCMTimeRangeInvalid直接进行比较.

将 CMTimeRange 转换为对象

如果要在注释或者Core Foundation容器中使用 CMTimeRange, 使用方法 CMTimeRangeCopyAsDictionaryarrow-up-rightCMTimeRangeMakeFromDictionaryarrow-up-right 可以在 CMTimeRange 结构体和CFDictionary类型 (参见 CFDictionaryRefarrow-up-right) 之间进行相互转换. 使用方法 CMTimeRangeCopyDescriptionarrow-up-right 可以获取 CMTimeRange 结构体的字符串描述.

媒体的表示

视频数据和与其相关联的元数据都使用 Core Media 框架中的对象类型来表示. Core Media 使用CMSampleBuffer(参见 CMSampleBufferRefarrow-up-right) 类型表示视频数据. 一个CMSampleBuffer对象是一个包含了视频数据帧的 sample buffer, 用来作为 Core Video pixel buffer(参见 CVPixelBufferRefarrow-up-right). 可以使用 CMSampleBufferGetImageBufferarrow-up-right 方法访问 sample buffer 中的 pixel buffer.

可以在 pixel buffer 访问到实际的视频数据, 参见下文.

此外, 对于视频数据而言, 还可以视频帧其他方面的信息:

}

Last updated