我一直在使用新的视频工具箱方法拍摄H.264视频流,并使用AVSampleBufferDisplayLayer
将其显示在视图控制器中。这一切都按预期工作,流看起来很棒。 但是,当我尝试截取整个视图的屏幕截图时,AVSampleBufferDisplayLayer
(即解压缩的视频流)的内容不会显示在快照中。快照显示所有其他内容UI按钮/标签/等。但屏幕截图仅显示AVSampleBufferDisplayLayer
(我设置为亮蓝色)的背景颜色,而不是实时视频输入。
在下面的方法中(受this post启发)我从我的流中取出SampleBuffer
并将其排队以显示在AVSampleBufferDisplayLayer
上。然后我调用我的方法 imageFromLayer:将快照作为UIImage
获取。 (然后我在 UIImageView imageDisplay 中显示UIImage,或者将其保存到设备的本地相机胶卷以验证UIImage
的外观。两种方法都产生相同的效果结果。)
-(void) h264VideoFrame:(CMSampleBufferRef)sample
{
[self.AVSampleDisplayLayer enqueueSampleBuffer:sample];
dispatch_sync(dispatch_get_main_queue(), ^(void) {
UIImage* snapshot = [self imageFromLayer:self.AVSampleDisplayLayer];
[self.imageDisplay setImage:snapshot];
});
}
在这里,我只需获取AVSampleBufferDisplayLayer
的内容,然后尝试将其转换为UIImage
。如果我将整个屏幕作为图层传递给此方法,则除了AVDisplayLayer
之外,所有其他UI元素(如标签/按钮/图像)都会显示。如果我只传入AVDisplayLayer
,我会得到一个稳定的蓝色图像(因为背景颜色为蓝色)。
- (UIImage *)imageFromLayer:(CALayer *)layer
{
UIGraphicsBeginImageContextWithOptions([layer frame].size, YES, 1.0);
[layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
//UIImageWriteToSavedPhotosAlbum(outputImage, self, nil, nil);
UIGraphicsEndImageContext();
return outputImage;
}
我已尝试使用UIImage snapshot = [self imageFromLayer: self.AVSampleDisplayLayer.presentationLayer];
和.modelLayer
,但这并没有帮助。我已经尝试排队采样缓冲并在拍摄快照之前等待,我已经尝试弄乱AVDisplayLayer
的不透明度和xPosition ...我甚至尝试为其设置不同的值CMTimebase
的{{1}}。任何提示都表示赞赏!
答案 0 :(得分:0)
我通过从AVSampleDisplayLayer
切换到VTDecompressionSession
来解决此问题。在VTDecompression didDecompress
回调方法中,我将解压缩的图片(CVImageBufferRef
)发送到以下方法,以获取视频流的屏幕截图并将其转换为UIImage
。
-(void) screenshotOfVideoStream:(CVImageBufferRef)imageBuffer
{
CIImage *ciImage = [CIImage imageWithCVPixelBuffer:imageBuffer];
CIContext *temporaryContext = [CIContext contextWithOptions:nil];
CGImageRef videoImage = [temporaryContext
createCGImage:ciImage
fromRect:CGRectMake(0, 0,
CVPixelBufferGetWidth(imageBuffer),
CVPixelBufferGetHeight(imageBuffer))];
UIImage *image = [[UIImage alloc] initWithCGImage:videoImage];
[self doSomethingWithOurUIImage:image];
CGImageRelease(videoImage);
}