我正在使用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捕获和压缩帧的经验?
答案 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);