2014-10-02 193 views
1

我在AVsampleBufferDisplayLayer上显示了一些视频,并希望捕获该图像并将其保存到相册中。由于AVSampleBufferDisplayLayer继承自CALayer,我认为在renderInContext中使用它是可以接受的。AVSampleBufferDisplayLayer的快照

[targetView.layer addSublayer:avLayer]; 


UIGraphicsBeginImageContext(targetView.bounds.size); 
CGContextRef context = UIGraphicsGetCurrentContext(); 
[avLayer renderInContext:context]; 
UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 

UIImageWriteToSavedPhotosAlbum(image, 
            self, 
            @selector(image:didFinishSavingWithError:contextInfo:), 
            NULL); 

但这会导致一个空白的白色图像被保存到相册中。 有关我可能会出错的想法吗?

回答

2

我对如何使当前的工作方法没有任何建议,但正确的方法是使用AVSampleBufferDisplayLayer,而不是使用VideoToolbox的VTDecompressionSession来解码H.264帧并将其传回作为一个回调中的CVPixelBuffers,然后你可以转换并保存到磁盘。

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

我不知道为什么VTD会支持截图,但AVSampleLayer不会。似乎它可能是苹果公司的一个错误/错误?

+1

当你无法访问'self'时,如何将CVImageBufferRef从C风格函数发送到目标C函数? – Md1079 2015-03-05 15:24:34

+1

当使用VTDecompression Session进行播放时,您如何将P帧添加到iFrame?你是否使用图层并将图层粘贴到图像上? – Md1079 2015-03-05 15:33:37

+0

关于你的第一个问题,在VTDecomp回调应该是这个样子 “无效decompressionSessionDecodeFrameCallback(void *的decompressionOutputRefCon,无效* sourceFrameRefCon,OSStatus状态,VTDecodeInfoFlags的infoflags,CVImageBufferRef ImageBuffer的,CMTime presentationTimeStamp,CMTime presentationDuration)” 要访问自我, cast像decompressionOutputRefCon这样: “THISCLASSNAME * streamManager =(__bridge THISCLASSNAME *)decompressionOutputRefCon;” 然后你可以调用这样的方法:“[streamManager screenshotOfVideoStream:imageBuffer];” – 2015-03-05 18:46:58