OC之视频合成AVVideoComposition

视频合成在其指令的聚合时间范围内的任何时间描述了用于产生对应于该时间的合成视频帧的视频轨道的数量和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发送任何组合请求之前,将查询此属性一次。之后不支持更改所需的缓冲区属性。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容

  • AVFoundation框架提供了一组功能丰富的类,以便于编辑音频视频Asset。 AVFoundation的编辑...
    lion_xion阅读 5,298评论 2 17
  • 文章目录 1. Export - 输出1.1. Reading an Asset - 读取资产1.1.1. Cre...
    __season____阅读 529评论 0 1
  • 《房思琪的初恋乐园》算是近一年来的文学作品爆款。买了很久,一直没看。对于这类很确定会打动内心、并契合自己审美标准的...
    一周加餐阅读 852评论 0 2
  • 大目标化成一个个小目标,要有长期目标,一个阶段的目标,一年的目标,一个月的目标,一天的目标,一个小时的目标,一分钟...
    0818ba15cc2b阅读 118评论 0 0
  • 我不会笑,常引以为憾事。所以,特别愿意看到笑脸。笑脸很美。在这样极端热情的天气里,踩着人力三轮车讨生活,他的笑脸,...
    张全敏阅读 203评论 1 0