视频合成在其指令的聚合时间范围内的任何时间描述了用于产生对应于该时间的合成视频帧的视频轨道的数量和ID。当使用AVFoundation
的内置视频合成器时,AVVideoComposition
包含的指令可以为每个视频源指定空间变换,不透明度值和裁剪矩形,并且这些指令可以通过简单的线性渐变功能随时间变化。
通过实现AVVideoCompositing
协议,可以实现自己的自定义视频合成程序;自定义视频合成程序在回放和其他操作期间为其每个视频源提供像素缓冲区,并可以对其执行任意图形操作以产生可视输出。
一、视频合成不可变对象AVVideoComposition
AVVideoComposition 继承自NSObject
,表示不可变视频合成的对象。
AVFoundation
框架还提供了一个可变子类AVMutableVideoComposition
,可以使用它创建新视频。
1、创建视频组合对象
1.1、指定Asset
创建并返回配置为显示指定AVAsset
的视频轨道的视频合成对象。
+ (AVVideoComposition *)videoCompositionWithPropertiesOfAsset:(AVAsset *)asset;
- 参数
asset
:配置与视频合成的预期使用相匹配的资源。
此方法创建AVVideoComposition
对象,并使用适合于呈现指定资产的视频轨道的值和指令对其进行配置。 返回的对象包含遵循指定资产的视频轨道的空间属性和时间范围的指令。 它还以下列方式配置对象属性:
-
frameDuration
属性的值设置为足够短的值,以容纳资产视频轨道中的最大标称帧速率值,如每个轨道的nominalFrameRate
属性所示。如果所有资产轨道的标称帧速率为0,则使用每秒30帧的帧速率,相应地设置帧持续时间。 - 分配给renderSize属性的值取决于
asset
是否为AVComposition对象。 如果是,则将值设置为合成的naturalSize
属性的值。如果不是,则将该值设置为包含所有资产视频轨道的值。 -
renderScale
属性设置为1.0。 -
animationTool
属性设置为nil。
1.2、将Core Image
过滤器应用于指定Asset
的每个视频帧
创建一个视频组合,配置为将Core Image
过滤器应用于指定Asset
的每个视频帧。
+ (AVVideoComposition *)videoCompositionWithAsset:(AVAsset *)asset
applyingCIFiltersWithHandler:(void (^)(AVAsynchronousCIImageFilteringRequest *request))applier;
- 参数
asset
:配置与视频合成的预期使用相匹配的asset
。 - 参数
applier
:AVFoundation
在处理每个视频帧时调用的块。块只接受一个参数,没有返回值; - 块中参数
request
:表示要处理的帧的AVAsynchronousCIImageFilteringRequest
对象。
要使用Core Image
过滤器处理视频帧:无论是显示还是导出,使用此方法创建合成。AVFoundation
会调用块block
一次,以便从资产的第一个启用的视频轨道显示(或处理导出)每个帧。在该块block
中,使用提供的AVAsynchronousCIImageFilteringRequest
对象访问视频帧并返回过滤结果。使用该对象的sourceImage
属性以可以应用过滤器的CIImage
对象的形式获取视频帧。将过滤器的结果传递给请求对象的-finishWithImage:context:
方法。(如果过滤器渲染失败,请调用请求对象的-finishWithError:
方法,如果无法应用过滤器。)
用此方法创建一个AVVideoComposition
,为下列属性设置值:
-
frameDuration
属性设置为容纳资产的第一个启用的视频轨道的nominalFrameRate
值。如果标称帧速率为零,则AVFoundation
使用30 fps
的默认帧速率。 -
renderSize
属性被设置为一个大小,该大小包含资产的第一个启用的视频跟踪,这与跟踪的preferredTransform
属性有关。 -
renderScale
属性设置为1.0。
2、获取合成属性
只读属性 | 数据类型 | 描述 |
---|---|---|
frameDuration |
CMTime |
视频合成应该渲染合成视频帧的时间间隔。 |
renderSize |
CGSize |
视频合成渲染的大小。 |
instructions |
NSArray |
视频合成说明;该数组包含AVVideoCompositionInstruction 的实例。对于数组中的第一条指令,timeRange.start 必须小于或等于将尝试播放或其他处理的最早时间,通常为kCMTimeZero 。对于后续指令,timeRange.start 必须等于先前指令的结束时间。最后一条指令的结束时间必须大于或等于将尝试播放或其他处理的最新时间,通常是与AVVideoComposition 实例关联的资产的持续时间。 |
animationTool |
AVVideoCompositionCoreAnimationTool |
在离线渲染中与Core Animation 一起使用的视频合成工具;这个属性可能是nil。如果将合成与AVAssetExportSession 一起用于离线渲染,而不是与AVPlayer 一起,则可以设置一个动画工具。 |
renderScale |
float |
视频合成渲染的比例。这个值必须是1.0,除非合成设置在AVPlayerItem 上。 |
customVideoCompositorClass |
Class |
要使用的自定义合成器类;默认为nil,表示使用的是内部视频合成程序。customVideoCompositorClass 必须实现AVVideoCompositing 协议。 |
sourceTrackIDForFrameTiming |
CMPersistentTrackID |
3、验证时间范围
- (BOOL)isValidForAsset:(AVAsset *)asset
timeRange:(CMTimeRange)timeRange
validationDelegate:(id)validationDelegate;
指示合成指令的时间范围是否符合验证要求:
- 参数
asset
:根据资产的持续时间验证指令的时间范围,并根据资产的轨道验证层指令的trackID
;如果nil
则跳过验证。 - 参数
timeRange
:一个时间范围;只有那些时间范围与此时间范围重叠的指令才会被验证。要验证所有可能用于回放或其他处理的指令,不管时间范围如何,请通过CMTimeRangeMake(kCMTimeZero, kCMTimePositiveInfinity)
。 - 参数
validationDelegate
:表示实现AVVideoCompositionValidationHandling
协议的对象,用于在处理期间接收有关视频合成中有问题部分的详细信息。如果不想被告知细节,请通过nil。 - 返回值:如果合成指令的时间范围符合验证要求,则为YES,否则为NO。
在验证过程中,如果有的话接收器将参考视频合成中的任何故障点来调用其委托。如果委托在验证期间修改接收器的指令数组或其中包含的任何AVVideoCompositionInstruction
对象的层指令数组,则此方法引发异常。
4、定义色彩空间
@property(nonatomic, readonly) NSString *colorPrimaries;
@property(nonatomic, readonly) NSString *colorTransferFunction;
@property(nonatomic, readonly) NSString *colorYCbCrMatrix;
二、视频合成可变对象AVMutableVideoComposition
AVMutableVideoComposition 继承自AVVideoComposition
,表示可变视频合成的对象。
1、创建视频合成
返回一个新的可变视频合成。
+ (AVMutableVideoComposition *)videoComposition;
返回的AVMutableVideoComposition
具有以下属性:
-
frameDuration
属性为kCMTimeZero
; -
renderSize
属性为{0.0, 0.0}
; - 数组
instructions
属性为nil
。 -
animationTool
属性为nil
。
1.1、指定asset
+ (AVMutableVideoComposition *)videoCompositionWithPropertiesOfAsset:(AVAsset *)asset;
返回具有指定```属性的新的可变视频组合:
- 参数
asset
:在调用此方法之前,请确保已加载asset
的duration
和tracks
属性。
返回的AVMutableVideoComposition
命令会尊重指定资产的视频轨道的空间属性和时间范围。它的属性值如下:
-
frameDuration
的值足够短,以容纳资产视频轨道中最大的nominalFrameRate
。如果所有资产的视频轨道的nominalFrameRate
为0,则使用30fps的默认帧速率。 - 如果指定的
asset
是AVComposition
的实例,则renderSize
设置为AVComposition
的naturalSize
; 否则,renderSize
将被设置为包含所有资产视频轨道的值。 -
renderScale
属性为 1.0. -
animationTool
属性为nil。
1.2、将Core Image
过滤器应用于指定Asset
的每个视频帧
+ (AVMutableVideoComposition *)videoCompositionWithAsset:(AVAsset *)asset
applyingCIFiltersWithHandler:(void (^)(AVAsynchronousCIImageFilteringRequest *request))applier;
创建可变视频合成,配置为将Core Image
过滤器应用于指定资产的每个视频帧:
- 参数
asset
:配置与视频合成的预期使用相匹配的asset
。 - 参数
applier
:AVFoundation
在处理每个视频帧时调用的块。块只接受一个参数,没有返回值: - 块中参数
request
:表示要处理的帧的AVAsynchronousCIImageFilteringRequest
对象。
要使用Core Image
过滤器处理视频帧:无论是显示还是导出,使用此方法创建合成。AVFoundation
会调用块block
一次,以便从资产的第一个启用的视频轨道显示(或处理导出)每个帧。在该块block
中,使用提供的AVAsynchronousCIImageFilteringRequest
对象访问视频帧并返回过滤结果。使用该对象的sourceImage
属性以可以应用过滤器的CIImage
对象的形式获取视频帧。将过滤器的结果传递给请求对象的-finishWithImage:context:
方法。(如果过滤器渲染失败,请调用请求对象的-finishWithError:
方法,如果无法应用过滤器。)
用此方法创建一个AVMutableVideoComposition
,为下列属性设置值:
-
frameDuration
属性设置为容纳资产的第一个启用的视频轨道的nominalFrameRate
值。如果标称帧速率为零,则AVFoundation
使用30 fps
的默认帧速率。 -
renderSize
属性被设置为一个大小,该大小包含资产的第一个启用的视频跟踪,这与跟踪的preferredTransform
属性有关。 -
animationTool
属性设置为1.0。
2、配置视频合成属性
只读属性 | 数据类型 | 描述 |
---|---|---|
frameDuration |
CMTime |
视频合成应该渲染合成视频帧的时间间隔。 |
renderSize |
CGSize |
视频合成渲染的大小。 |
renderScale |
float |
视频合成渲染的比例。这个值必须是1.0,除非合成设置在AVPlayerItem 上。 |
instructions |
NSArray |
视频合成说明;该数组包含AVVideoCompositionInstruction 的实例。对于数组中的第一条指令,timeRange.start 必须小于或等于将尝试播放或其他处理的最早时间,通常为kCMTimeZero 。对于后续指令,timeRange.start 必须等于先前指令的结束时间。最后一条指令的结束时间必须大于或等于将尝试播放或其他处理的最新时间,通常是与AVVideoComposition 实例关联的资产的持续时间。 |
animationTool |
AVVideoCompositionCoreAnimationTool |
在离线渲染中与Core Animation 一起使用的视频合成工具;这个属性可能是nil。如果将合成与AVAssetExportSession 一起用于离线渲染,而不是与AVPlayer 一起,则可以设置一个动画工具。 |
customVideoCompositorClass |
Class |
要使用的自定义合成器类;默认为nil,表示使用的是内部视频合成程序。customVideoCompositorClass 必须实现AVVideoCompositing 协议。 |
sourceTrackIDForFrameTiming |
CMPersistentTrackID |
|
colorPrimaries |
NSString |
|
colorTransferFunction |
NSString |
|
colorYCbCrMatrix |
NSString |
三、合成对象协议AVVideoCompositing
AVVideoCompositing AVVideoComposition必须实现的方法。
1、渲染合成
1.1 异步创建一个新的像素缓冲区
引导一个视频合成对象AVVideoComposition
,以创建一个新的像素缓冲区,该像素缓冲区由一组源异步组合而成。
- (void)startVideoCompositionRequest:(AVAsynchronousVideoCompositionRequest *)asyncVideoCompositionRequest;
- 参数
asyncVideoCompositionRequest
:该实例为请求的组合提供上下文。
AVVideoComposition
应该随后或立即调用asyncVideoCompositionRequest
对象的finishWithComposedVideoFrame:
或-finishWithError:
方法。
如果打算在处理此消息返回后完成渲染帧,则必须保留asyncVideoCompositionRequest
,直到合成完成。
注意,如果AVVideoComposition
的此方法的实现在不立即完成合成的情况下返回,则可以在先前请求完成之前使用另一个合成请求再次调用它。在这种情况下,AVVideoComposition
应该准备好管理多个组合请求。
如果渲染的帧与其中一个源帧完全相同,不需要进行letterboxing、pillboxing或裁剪,那么在CFRetain被调用之后,可能会返回适当的源像素缓冲区。(Letterbox指的是16:9的图像在4:3的设备上的显示方法,即图像与设备同宽,在上下添加黑边的显示模式;Pillarbox正好相反,为4:3的图像在16:9的设备的显示模式,左右会被添加黑边)
1.2、取消所有待处理的视频合成请求
指示AVVideoComposition
取消或完成所有待处理的视频合成请求。
- (void)cancelAllPendingVideoCompositionRequests;
收到此消息后,AVVideoComposition
阻塞线程,直到它取消所有挂起的帧请求,并为每个请求调用-finishCancelledRequest
方法。 如果无法取消,则该方法阻塞线程,直到它完成所有帧的处理并为每个帧调用-finishWithComposedVideoFrame:
方法。
2、渲染上下文设置
@property(nonatomic, readonly) BOOL supportsWideColorSourceFrames;
2.1、切换到不同的上下文渲染
通知AVVideoComposition
将切换到不同的上下文渲染。
- (void)renderContextChanged:(AVVideoCompositionRenderContext *)newRenderContext;
- 参数
newRenderContext
:将处理AVVideoComposition
的新上下文渲染。
实现AVVideoComposting
协议的类的实例必须实现此方法,以便在AVVideoCompositionRenderContext
实例处理视频合成更改时得到通知。该实例是不可变的,每当视频组成参数发生变化时都会发生这样的变化。
3、像素缓冲区属性
3.1、像素缓冲区属性:创建新缓冲区所需的
AVVideoComposition
为处理创建的新缓冲区所需的像素缓冲区属性。
@property(nonatomic, readonly) NSDictionary *requiredPixelBufferAttributesForRenderContext;
该属性需要在字典中提供kCVPixelBufferPixelFormatTypeKey
键,以及合成器需要特定值才能正常工作的属性。组合引擎将提供省略的属性,以实现最佳性能。如果属性kCVPixelBufferPixelFormatTypeKey
键不在字典中,则会引发异常。 kCVPixelBufferPixelFormatTypeKey
的值是Pixel_Format_Types
中定义的kCVPixelFormatType_ *
常量数组。
在创建新的渲染上下文之前检索requiredPixelBufferAttributesForRenderContext
的值; 返回值中的属性与合成引擎提供的附加属性的组合将用于创建后续渲染上下文的pixelBuffers
。
在向compositor
发送任何组合请求之前,将查询此属性一次。之后不支持更改所需的缓冲区属性。
3.2、像素缓冲区属性:创建新缓冲区所需的
AVVideoComposition
可以接受的源帧像素缓冲区属性的类型作为输入。
@property(nonatomic, readonly) NSDictionary *sourcePixelBufferAttributes;
sourcePixelBufferAttributes
该属性需要在字典中提供kCVPixelBufferPixelFormatTypeKey
键,以及合成器需要特定值才能正常工作的属性。组合引擎将提供省略的属性,以实现最佳性能。如果属性kCVPixelBufferPixelFormatTypeKey
键不在字典中,则会引发异常。 kCVPixelBufferPixelFormatTypeKey
的值是Pixel_Format_Types
中定义的kCVPixelFormatType_ *
常量数组。
如果定制的compositor
要与使用-videoCompositionCoreAnimationToolWithAdditionalLayer:asTrackID:
方法创建的AVVideoCompositionCoreAnimationTool
一起使用,那么kCVPixelFormatType_32BGRA
应该包括在支持的像素格式类型中。
AVVideoComposition
会将丢失的属性设置为允许最佳性能的值。
在向compositor
发送任何组合请求之前,将查询此属性一次。之后不支持更改所需的缓冲区属性。