OC之视频合成AVVideoComposition

作者: 苏沫离 | 来源:发表于2018-10-20 00:46 被阅读65次

    视频合成在其指令的聚合时间范围内的任何时间描述了用于产生对应于该时间的合成视频帧的视频轨道的数量和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
    • 参数applierAVFoundation在处理每个视频帧时调用的块。块只接受一个参数,没有返回值;
    • 块中参数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<AVVideoCompositing> 要使用的自定义合成器类;默认为nil,表示使用的是内部视频合成程序。customVideoCompositorClass必须实现AVVideoCompositing协议。
    sourceTrackIDForFrameTiming CMPersistentTrackID

    3、验证时间范围

    - (BOOL)isValidForAsset:(AVAsset *)asset
    timeRange:(CMTimeRange)timeRange
    validationDelegate:(id<AVVideoCompositionValidationHandling>)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:在调用此方法之前,请确保已加载assetdurationtracks属性。

    返回的AVMutableVideoComposition命令会尊重指定资产的视频轨道的空间属性和时间范围。它的属性值如下:

    • frameDuration的值足够短,以容纳资产视频轨道中最大的nominalFrameRate。如果所有资产的视频轨道的nominalFrameRate为0,则使用30fps的默认帧速率。
    • 如果指定的assetAVComposition的实例,则renderSize设置为AVCompositionnaturalSize; 否则,renderSize将被设置为包含所有资产视频轨道的值。
    • renderScale 属性为 1.0.
    • animationTool属性为nil。
    1.2、将Core Image过滤器应用于指定Asset的每个视频帧
    + (AVMutableVideoComposition *)videoCompositionWithAsset:(AVAsset *)asset
    applyingCIFiltersWithHandler:(void (^)(AVAsynchronousCIImageFilteringRequest *request))applier;
    

    创建可变视频合成,配置为将Core Image过滤器应用于指定资产的每个视频帧:

    • 参数asset:配置与视频合成的预期使用相匹配的asset
    • 参数applierAVFoundation在处理每个视频帧时调用的块。块只接受一个参数,没有返回值:
    • 块中参数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<AVVideoCompositing> 要使用的自定义合成器类;默认为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<NSString *,id> *requiredPixelBufferAttributesForRenderContext;
    

    该属性需要在字典中提供kCVPixelBufferPixelFormatTypeKey键,以及合成器需要特定值才能正常工作的属性。组合引擎将提供省略的属性,以实现最佳性能。如果属性kCVPixelBufferPixelFormatTypeKey键不在字典中,则会引发异常。 kCVPixelBufferPixelFormatTypeKey的值是Pixel_Format_Types中定义的kCVPixelFormatType_ *常量数组。

    在创建新的渲染上下文之前检索requiredPixelBufferAttributesForRenderContext的值; 返回值中的属性与合成引擎提供的附加属性的组合将用于创建后续渲染上下文的pixelBuffers

    在向compositor发送任何组合请求之前,将查询此属性一次。之后不支持更改所需的缓冲区属性。

    3.2、像素缓冲区属性:创建新缓冲区所需的

    AVVideoComposition可以接受的源帧像素缓冲区属性的类型作为输入。

    @property(nonatomic, readonly) NSDictionary<NSString *,id> *sourcePixelBufferAttributes;
    sourcePixelBufferAttributes
    

    该属性需要在字典中提供kCVPixelBufferPixelFormatTypeKey键,以及合成器需要特定值才能正常工作的属性。组合引擎将提供省略的属性,以实现最佳性能。如果属性kCVPixelBufferPixelFormatTypeKey键不在字典中,则会引发异常。 kCVPixelBufferPixelFormatTypeKey的值是Pixel_Format_Types中定义的kCVPixelFormatType_ *常量数组。

    如果定制的compositor要与使用-videoCompositionCoreAnimationToolWithAdditionalLayer:asTrackID:方法创建的AVVideoCompositionCoreAnimationTool一起使用,那么kCVPixelFormatType_32BGRA应该包括在支持的像素格式类型中。

    AVVideoComposition会将丢失的属性设置为允许最佳性能的值。

    在向compositor发送任何组合请求之前,将查询此属性一次。之后不支持更改所需的缓冲区属性。

    相关文章

      网友评论

        本文标题:OC之视频合成AVVideoComposition

        本文链接:https://www.haomeiwen.com/subject/cjwyzftx.html