首先,我创建了玩家项目:
AVPlayerItem *item = [AVPlayerItem playerItemWithURL:vIDeoURL];// DEBUG LOGGINGAVAssetTrack *track = [[item.asset tracksWithMediaType:AVMediaTypeVIDeo] objectAtIndex:0];NSLog(@"Natural size is: %@",NsstringFromCGSize(track.naturalSize));NSLog(@"Preffered track transform is: %@",NsstringFromCGAffinetransform(track.preferredtransform));NSLog(@"Preffered asset transform is: %@",NsstringFromCGAffinetransform(item.asset.preferredtransform));
然后我需要应用视频合成.最初,我正在考虑用2条指令创建一个AVVIDeoComposition – 一个是用于旋转的AVVIDeoCompositionLayerInstruction,另一个是CIFilter应用程序.但是,我得到一个异常抛出的说法“期望视频合成仅包含AVCoreImageFilterVIDeoCompositionInstruction”,这意味着Apple不允许合并这两条指令.结果,我结合了两个过滤,这里是代码:
AVAsset *asset = playerItem.asset;CGAffinetransform rotation = [self transformForItem:playerItem];AVVIDeoComposition *composition = [AVVIDeoComposition vIDeoCompositionWithAsset:asset applyingCIFiltersWithHandler:^(AVAsynchronousCIImageFilteringRequest * _Nonnull request) { // Step 1: get the input frame image (screenshot 1) CIImage *sourceImage = request.sourceImage; // Step 2: rotate the frame CIFilter *transformFilter = [CIFilter filterWithname:@"CIAffinetransform"]; [transformFilter setValue:sourceImage forKey: kCIInputimageKey]; [transformFilter setValue: [NSValue valueWithCGAffinetransform: rotation] forKey: kCIinputtransformKey]; sourceImage = transformFilter.outputimage; CGRect extent = sourceImage.extent; CGAffinetransform translation = CGAffinetransformMakeTranslation(-extent.origin.x,-extent.origin.y); [transformFilter setValue:sourceImage forKey: kCIInputimageKey]; [transformFilter setValue: [NSValue valueWithCGAffinetransform: translation] forKey: kCIinputtransformKey]; sourceImage = transformFilter.outputimage; // Step 3: apply the custom filter chosen by the user extent = sourceImage.extent; sourceImage = [sourceImage imageByClamPingToExtent]; [filter setValue:sourceImage forKey:kCIInputimageKey]; sourceImage = filter.outputimage; sourceImage = [sourceImage imageByCropPingToRect:extent]; // Step 4: finish processing the frame (screenshot 2) [request finishWithImage:sourceImage context:nil];}];playerItem.vIDeoComposition = composition;
我在调试期间制作的屏幕截图显示图像已成功旋转并应用了滤镜(在此示例中,它是一个不会更改图像的标识过滤器).以下是截图1和截图2,它们是在上面评论中标记的点上拍摄的:
如您所见,旋转成功,结果帧的范围也是正确的.
当我尝试在播放器中播放此视频时,问题就出现了.这是我得到的:
所以似乎所有的帧都缩放并向下移动.绿色区域是空框架信息,当我夹到范围以使框架无限大时,它显示边框像素而不是绿色.我感觉玩家在从AVPlayerItem旋转之前仍然需要一些旧的大小信息,这就是为什么在上面的第一个代码片段中我记录了大小和变换,有日志:
Natural size is: {1920,1080}Preffered track transform is: [0,1,-1,1080,0]Preffered asset transform is: [1,0]
播放器设置如下:
layer.vIDeoGravity = AVLayerVIDeoGravityResizeAspectFill;layer.needsdisplayOnBoundsChange = YES;
请注意最重要的事情:这只发生在应用程序本身使用相机以横向iPhone [6s]方向记录并保存在设备存储之前的视频中.应用程序以纵向模式记录的视频完全没问题(顺便说一下,肖像视频的大小完全相同,并且像风景视频一样转换日志!奇怪……也许iphone将旋转信息放入视频中并修复它).因此,在旋转之前,缩放和移动视频看起来像是“纵横填充”和旧分辨率信息的组合.顺便说一下,纵向显示纵向视频帧是因为缩放以填充具有不同宽高比的播放器区域,但这是预期的行为.
让我知道你对此的想法,如果你知道如何更好地完成我需要的东西,那么知道它会很棒.
解决方法 更新:在播放过程中更容易“更改”AVPlayerItem视频尺寸 – 设置视频合成的renderSize属性(可以使用AVMutableVIDeoComposition类完成).我的老答案如下:
经过大量调试后,我理解了问题并找到了解决方案.我最初猜测AVPlayer仍然认为视频是原始大小是正确的.在下图中,它解释了发生了什么:
至于解决方案,我找不到改变AVAsset或AVPlayerItem内部视频大小的方法.所以我只是 *** 纵视频以适应AVPlayer所期望的大小和比例,然后在具有正确宽高比的游戏中进行游戏并标记缩放并填充玩家区域 – 一切看起来都很好.这是图解说明:
这里需要插入问题中提到的applyCIFiltersWithHandler块中的其他代码:
... after Step 3 in the question codes above// make the frame the same aspect ratio as the original input frame// by adding empty spaces at the top and the bottom of the extent rectangleCGfloat newHeight = originalExtent.size.height * originalExtent.size.height / extent.size.height;CGfloat inset = (extent.size.height - newHeight) / 2;extent = CGRectInset(extent,inset);sourceImage = [sourceImage imageByCropPingToRect:extent];// scale down to the original frame sizeCGfloat scale = originalExtent.size.height / newHeight;CGAffinetransform scaletransform = CGAffinetransformMakeScale(scale,scale);[transformFilter setValue:sourceImage forKey: kCIInputimageKey];[transformFilter setValue: [NSValue valueWithCGAffinetransform: scaletransform] forKey: kCIinputtransformKey];sourceImage = transformFilter.outputimage;// translate the frame to make it's origin start at (0,0)CGAffinetransform translation = CGAffinetransformMakeTranslation(0,-inset * scale);[transformFilter setValue:sourceImage forKey: kCIInputimageKey];[transformFilter setValue: [NSValue valueWithCGAffinetransform: translation] forKey: kCIinputtransformKey];sourceImage = transformFilter.outputimage;总结
以上是内存溢出为你收集整理的ios – AVPlayer错误地播放视频合成结果全部内容,希望文章能够帮你解决ios – AVPlayer错误地播放视频合成结果所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)