gpt4 book ai didi

objective-c - 从 IDeckLinkVideoInputFrame 创建 CVPixelBufferRef

转载 作者:行者123 更新时间:2023-12-03 16:32:14 31 4
gpt4 key购买 nike

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

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

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,如下所示:

void *videoData;
int64_t frameTime;
int64_t frameDuration;

videoFrame->GetBytes(&videoData);
videoFrame->GetStreamTime(&frameTime, &frameDuration, 3000);

CMTime presentationTime = CMTimeMake(frameDuration, 3000);

CVPixelBufferRef buffer = NULL;

CVPixelBufferPoolCreatePixelBuffer(NULL, adaptor.pixelBufferPool, &buffer);
CVPixelBufferLockBaseAddress(buffer, 0);

void *rasterData = CVPixelBufferGetBaseAddress(buffer);
memcpy(rasterData, videoData, (videoFrame->GetRowBytes()*videoFrame->GetHeight()));

CVPixelBufferUnlockBaseAddress(buffer, 0);

if (buffer)
{
if(![adaptor appendPixelBuffer:buffer withPresentationTime:presentationTime]) {
NSLog(@"ERROR appending pixelbuffer: %@", writer.error);
[writerVideoInput markAsFinished];
if(![writer finishWriting])
NSLog(@"ERROR finishing writing: %@", [writer.error localizedDescription]);
}
else {
NSLog(@"SUCCESS");
if(buffer)
CVPixelBufferRelease(buffer);
}
}

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

有人能看出我在这里做错了什么吗?或者有人有使用 AVFoundation 使用 BlackMagic Decklink SDK 捕获和压缩帧的经验吗?

最佳答案

当您看到“绿色”并且在 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);

关于objective-c - 从 IDeckLinkVideoInputFrame 创建 CVPixelBufferRef,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16892259/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com