AVSampleBufferDisplayLayer 中的视频流未显示在屏幕截图中
Video stream in AVSampleBufferDisplayLayer doesn't show up in screenshot
我一直在使用新的视频工具箱方法获取 H.264 视频流并使用 AVSampleBufferDisplayLayer
在视图控制器中显示它。这一切都按预期工作,流看起来很棒。 但是,当我尝试截取整个视图时,AVSampleBufferDisplayLayer
(即解压缩的视频流)的内容不会显示在快照中。 快照显示所有其他 UI buttons/labels/etc。但屏幕截图仅显示 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 元素(如 labels/buttons/images )都会显示出来。如果我只传入 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
设置不同的值AVDisplayLayer
。任何提示表示赞赏!
另外,根据 this post, and this post 其他人在 iOS 8.
中的快照也遇到了类似的问题
我通过从 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);
}
我一直在使用新的视频工具箱方法获取 H.264 视频流并使用 AVSampleBufferDisplayLayer
在视图控制器中显示它。这一切都按预期工作,流看起来很棒。 但是,当我尝试截取整个视图时,AVSampleBufferDisplayLayer
(即解压缩的视频流)的内容不会显示在快照中。 快照显示所有其他 UI buttons/labels/etc。但屏幕截图仅显示 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 元素(如 labels/buttons/images )都会显示出来。如果我只传入 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
设置不同的值AVDisplayLayer
。任何提示表示赞赏!
另外,根据 this post, and this post 其他人在 iOS 8.
中的快照也遇到了类似的问题我通过从 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);
}