gpt4 book ai didi

ios - 为什么 AVFoundation 不接受我在 iOS 设备上的平面像素缓冲区?

转载 作者:行者123 更新时间:2023-12-04 18:12:09 25 4
gpt4 key购买 nike

我一直在努力弄清楚我的代码有什么问题。我正在创建平面 CVPixelBufferRef 以写入 AVAssetWriter。这个像素缓冲区是通过其他一些过程手动创建的(即,我没有从相机或类似的东西中获取这些样本)。在 iOS 模拟器上,附加样本和创建有效的输出影片没有问题。

但是在设备上,它在第一次采样时立即失败,并提供了一些无用的错误信息:

AVAssetWriterError: Error Domain=AVFoundationErrorDomain Code=-11800 “操作无法完成” UserInfo={NSUnderlyingError=0x12fd2c670 {Error Domain=NSOSStatusErrorDomain Code=-12780 “(null)”}, NSLocalizedFailureReason=An unknown发生错误 (-12780),NSLocalizedDescription=操作无法完成

我对像素格式非常陌生,如果我以某种方式创建了无效的像素缓冲区,我不会感到惊讶,但它在模拟器(即 OS X)上运行良好的事实让我感到困惑。

这是我的代码:

const int pixelBufferWidth = img->get_width();
const int pixelBufferHeight = img->get_height();

size_t planeWidths[3];
size_t planeHeights[3];
size_t planeBytesPerRow[3];
void* planeBaseAddresses[3];

for (int c=0;c<3;c++) {
int stride;
const uint8_t* p = de265_get_image_plane(img, c, &stride);

int width = de265_get_image_width(img,c);
int height = de265_get_image_height(img, c);

planeWidths[c] = width;
planeHeights[c] = height;
planeBytesPerRow[c] = stride;

planeBaseAddresses[c] = const_cast<uint8_t*>(p);
}

void* descriptor = calloc(1, sizeof(CVPlanarPixelBufferInfo_YCbCrPlanar));
CVPixelBufferRef pixelBufferRef;
CVReturn result = CVPixelBufferCreateWithPlanarBytes(NULL,
pixelBufferWidth,
pixelBufferHeight,
kCVPixelFormatType_420YpCbCr8Planar,
NULL,
0,
3,
planeBaseAddresses,
planeWidths,
planeHeights,
planeBytesPerRow,
&pixelBufferReleaseCallback,
NULL,
NULL,
&pixelBufferRef);


CMFormatDescriptionRef formatDescription = NULL;
CMVideoFormatDescriptionCreateForImageBuffer(NULL, pixelBufferRef, &formatDescription);

if (assetWriter == nil) {
// ... create output file path in Caches directory

assetWriter = [AVAssetWriter assetWriterWithURL:fileOutputURL fileType:AVFileTypeMPEG4 error:nil];

NSDictionary *videoSettings = @{AVVideoCodecKey : AVVideoCodecH264,
AVVideoWidthKey : @(pixelBufferWidth),
AVVideoHeightKey : @(pixelBufferHeight),
AVVideoCompressionPropertiesKey : @{AVVideoMaxKeyFrameIntervalKey : @1}};

assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings sourceFormatHint:formatDescription];
[assetWriter addInput:assetWriterInput];

NSDictionary *pixelBufferAttributes = @{(id)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_420YpCbCr8Planar),
(id)kCVPixelBufferWidthKey : @(pixelBufferWidth),
(id)kCVPixelBufferHeightKey : @(pixelBufferHeight)};

pixelBufferAdaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:assetWriterInput sourcePixelBufferAttributes:pixelBufferAttributes];

[assetWriter startWriting];
[assetWriter startSessionAtSourceTime:kCMTimeZero];
}

samplePresentationTime = CMTimeMake(frameIndex++, framesPerSecond);

BOOL success = [pixelBufferAdaptor appendPixelBuffer:pixelBufferRef withPresentationTime:samplePresentationTime];

success 始终是NO, Assets 作者的错误是我在上面粘贴的。

我还尝试手动创建样本缓冲区而不是使用 AVAssetWriterInputPixelBufferAdaptor 只是为了消除可能的问题,但结果是一样的。

同样,这在模拟器上确实有效,所以我知道我的像素缓冲区确实包含正确的数据。

另外,我验证了我可以写入文件目的地。我尝试在那个位置创建一个虚拟文件,它成功了。

我想避免将我的缓冲区转换为 RGB,因为我不应该这样做。我有 Y'CbCr 缓冲区作为开始,我只想将它们编码为支持 Y'CbCr 的 H.264 视频。

创建这些缓冲区的来源说明如下:

图像目前始终为 3 channel YCbCr,色度为 4:2:0。

我确认它总是进入处理 8 位 YUV channel 的循环逻辑。

我做错了什么?

最佳答案

因此,我无法正式确认这一点,但似乎 AVAssetWriter 不喜欢 iOS 上的 3 平面像素格式(即,kCVPixelFormatType_420YpCbCr8Planar)。在 OS X 上,它似乎适用于几乎任何东西。当我将我的 3 FlatBuffers 转换为双平面像素缓冲区格式时,这在 iOS 上有效。这不足为奇,因为相机以 kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange 像素格式原生捕捉,因此 AV Foundation 也可能使用该格式。

尽管 vImageConvert_PlanarToChunky8 有助于将 Cb 和 Cr 平面交错成一个平面,但如果我不必自己执行此显式转换步骤,那就太好了。

关于ios - 为什么 AVFoundation 不接受我在 iOS 设备上的平面像素缓冲区?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34099842/

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