【问题标题】:Video stream in AVSampleBufferDisplayLayer doesn't show up in screenshotAVSampleBufferDisplayLayer 中的视频流未显示在屏幕截图中
【发布时间】:2015-04-30 17:16:24
【问题描述】:

我一直在使用新的 Video Toolbox 方法来获取 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。如果我将整个屏幕作为层传递给此方法,则所有其他 UI 元素(如标签/按钮/图像)都将显示,AVDisplayLayer 除外。如果我只传入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 ...我什至尝试为AVDisplayLayerCMTimebase 设置不同的值.任何提示表示赞赏!

另外,根据this postthis post 的说法,其他人在 iOS 8 中也遇到了类似的快照问题。

【问题讨论】:

    标签: ios ios8 uiimage screenshot cmsamplebufferref


    【解决方案1】:

    我通过从 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);
    }
    

    【讨论】:

    • 您能否分享 VTDecompressionSession 的示例以截取屏幕截图..我正在使用相同的 AVSampleBufferDisplayLayer 和屏幕截图功能在设备上无法正常工作。
    • 那是很久以前的事了,所以很遗憾我没有代码了。我只记得在VTDecompression::didDecompress 回调中使用screenshotOfVideoStream 方法(上图)。抱歉,我无法提供更多帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-26
    • 1970-01-01
    • 2013-01-11
    相关资源
    最近更新 更多