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);
}