从IDeckLinkVideoInputFrame创建CVPixelBufferRef

时间:2013-06-03 07:55:22

标签: objective-c cocoa avfoundation video-capture objective-c++

我正在使用BlackMagic DeckLink SDK尝试从BM设备捕获帧。

我正在尝试从IDeckLinkVideoInputFrame回调中的DeckLinkController::VideoInputFrameArrived获取像素数据并将其转换为CVPixelBufferRef,以便能够使用AVFoundation {{1}将其写入磁盘}和AVAssetWriterInputPixelBufferAdaptor。我正在使用的代码似乎正在工作,除了写入磁盘的所有帧都是绿色的事实。 (BlackMagic在屏幕上生成预览的示例代码确实显示了图像,因此设备和设备设置应该没问题。)

AVAssetWriter的设置如下:

AVAssetWriter

作为参考,这些输出设置和压缩选项应该是正确的,但我尝试了几种不同的选择。

当一个帧从设备进入时,我将其转换为writer = [[AVAssetWriter assetWriterWithURL:destinationUrl fileType:AVFileTypeAppleM4V error:&error] retain]; if(error) NSLog(@"ERROR: %@", [error localizedDescription]); NSMutableDictionary * outputSettings = [[NSMutableDictionary alloc] init]; [outputSettings setObject: AVVideoCodecH264 forKey: AVVideoCodecKey]; [outputSettings setObject: [NSNumber numberWithInt:1920] forKey: AVVideoWidthKey]; [outputSettings setObject: [NSNumber numberWithInt:1080] forKey: AVVideoHeightKey]; NSMutableDictionary * compressionProperties = [[NSMutableDictionary alloc] init]; [compressionProperties setObject: [NSNumber numberWithInt: 1000000] forKey: AVVideoAverageBitRateKey]; [compressionProperties setObject: [NSNumber numberWithInt: 16] forKey: AVVideoMaxKeyFrameIntervalKey]; [compressionProperties setObject: AVVideoProfileLevelH264Main31 forKey: AVVideoProfileLevelKey]; [outputSettings setObject: compressionProperties forKey: AVVideoCompressionPropertiesKey]; writerVideoInput = [[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:outputSettings] retain]; NSMutableDictionary * pixBufSettings = [[NSMutableDictionary alloc] init]; [pixBufSettings setObject: [NSNumber numberWithInt: kCVPixelFormatType_422YpCbCr8_yuvs] forKey: (NSString *) kCVPixelBufferPixelFormatTypeKey]; [pixBufSettings setObject: [NSNumber numberWithInt: 1920] forKey: (NSString *) kCVPixelBufferWidthKey]; [pixBufSettings setObject: [NSNumber numberWithInt: 1080] forKey: (NSString *) kCVPixelBufferHeightKey]; writerVideoInput.expectsMediaDataInRealTime = YES; writer.shouldOptimizeForNetworkUse = NO; adaptor = [[AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerVideoInput sourcePixelBufferAttributes:pixBufSettings] retain]; [writer addInput:writerVideoInput]; ,如下所示:

CVPixelBufferRef

此代码将帧附加到AVAssetWriterInputPixelBufferAdaptor,但所有帧都是绿色。

有人能看到我在这里做错了什么,或者有没有人使用过BlackFagic Decklink SDK使用AVFoundation捕获和压缩帧的经验?

1 个答案:

答案 0 :(得分:3)

当您看到“绿色”并且正在YUV颜色空间中工作时,您会在缓冲区中看到值0。由于AVWriter正在编写帧,因此“缓冲区”包含的值为0.我看到了几种可能发生的方法。

1)您附加的缓冲区很可能初始化为0,因此您的副本可能会失败。在你的代码中,如果(videoFrame-> GetRowBytes()* videoFrame-> GetHeight())以某种方式评估为0.这似乎是不可能的,但我会检查它。

2)CVPixelBufferGetBaseAddress返回错误的指针,PixelBuffer本身格式错误或可能无效(但由于API中的安全措施而未崩溃)。

3)'videoData',无论出于什么原因,它本身都是0.当DeckLinkCaptureDelegate不喜欢输入格式时,返回其中没有任何内容的帧(通常这是因为传递给EnableVideoInput的BMDDisplayMode与你的不一致视频来源。

int flags=videoFrame->GetFlags();
if (flags & bmdFrameHasNoInputSource)
{
    //our input format doesn't match the source
}

除了更改源模式并再次尝试之外,快速检查是将memcpy行更改为以下内容:

memset(rasterData, 0x3f, 1920*1080*2);

如果你仍然看到绿色框架,那么请仔细看看#2。如果您看到不同颜色的帧,那么您的问题是#1或#3,并且很可能视频输入的分辨率与您选择的BMDDisplayMode不匹配。

还有一点需要注意。我认为你创建演示时间的行是错误的。它应该是(注意将frameDuration更改为frameTime:

CMTime presentationTime = CMTimeMake(frameTime, 3000);