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

2024-03-20

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

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

AVAssetWriterError: Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSUnderlyingError=0x12fd2c670 {Error Domain=NSOSStatusErrorDomain Code=-12780 "(null)"}, NSLocalizedFailureReason=An unknown error occurred (-12780), NSLocalizedDescription=The operation could not be completed}

我对像素格式非常陌生,如果我以某种方式创建了无效的像素缓冲区,我不会感到惊讶,但它在模拟器(即 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,资产编写者的错误就是我在上面粘贴的内容。

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

再说一遍,这个does在模拟器上工作,所以我知道我的像素缓冲区确实包含正确的数据。

另外,我验证了我可以写入文件目标。我尝试在该位置创建一个虚拟文件,并且成功了。

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

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

The image is currently always 3-channel YCbCr, with 4:2:0 chroma.

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

我究竟做错了什么?


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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 AVFoundation 不接受 iOS 设备上的平面像素缓冲区? 的相关文章

  • 如何在 SwiftUI 中将变量从一个视图传递到另一个视图

    我正在尝试将一个变量从一个视图传递到 SwiftUI 中的另一个视图 我有一个重置按钮 我想在另一个视图中将变量设置为零 我尝试在视图一中创建一个新结构并在视图2中访问该变量 View 1 State var count MyNumber
  • 如何在UiView中添加UIImagePickerController

    如何在TabBarApplication中的UiView中添加UIImagePickerController 无论您是否在选项卡中 此代码都会进入您视图的 ViewController 类 当您需要时创建一个选择器 UIImagePicke
  • SwiftUI:如何让项目的拖放重新排序起作用?

    我有以下 SwiftUI 视图 struct ContentView View State var model Model var body some View ScrollView LazyVGrid columns columns sp
  • iOS-将图像转为视频时,CVPixelBufferCreate内存无法正确释放

    我正在将图像制作成视频 但总是因为内存警告而崩溃 分配太多CVPixelBufferCreate 我不知道如何正确处理 我看过很多类似的主题 但没有一个能解决我的问题 这是我的代码 void writeImagesArray NSArray
  • 将 .p12 证书存储在钥匙串中以供稍后使用

    我正在尝试按照 Apple 文档处理此处的客户端 p12 证书 https developer apple com library ios documentation Security Conceptual CertKeyTrustProg
  • 如何在 UITextView 中禁用放大功能

    我想摆脱 UITextView 中的放大和文本选择 但我需要电话号码 链接和地址检测器 我在用 void addGestureRecognizer UIGestureRecognizer gestureRecognizer if gestu
  • sizeToFit 运行异常

    我有一段代码 每次发生后端数据库更改时都会执行 本质上我在父视图中有一个标签 标签由许多状态消息之一更新 每个状态消息位于不同的行上 并以换行符 n 结尾 每条状态消息只能在一行上 并且不能过多 我遇到的问题是 当视图首次重新加载时 一切正
  • UIAlertAction 处理程序在延迟后运行

    我正在尝试将 UIAlertViews 更改为 UIAlertControllers 我为此设置了这个操作 UIAlertAction undoStopAction UIAlertAction actionWithTitle Undo St
  • 如何在 iOS 上更改设备音量 - 而不是音乐音量

    我想更改 iOS iPhone 上的设备音量 我知道我可以使用以下几行更改音乐库的音量 implement at first MediaPlayer framework MPMusicPlayerController musicPlayer
  • 如何设置 UINavigationbar 的渐变颜色?

    我想设置UINavigationbar backgroundColor渐变颜色 我想通过颜色数组设置它以创建渐变 理想情况下 作为内部的可访问方法UINavigationBar将其颜色更改为此渐变 有什么建议么 除了手动设置图像作为导航栏的
  • 为什么我无法更改 UIBarButtonItem 的标题?

    我想改变UIBarButtonItem s title 但这段代码不起作用 void viewDidLoad self smay void smay AppDelegate apd AppDelegate UIApplication sha
  • 如何使用呼叫目录扩展来识别应用程序中的来电?

    我正在研究callKit框架 我发现通过使用呼叫目录扩展 我们可以识别来电电话号码 我的问题是如何在 iOS 应用程序中实现呼叫目录扩展来识别来电详细信息 我在 Objective C 工作 让一个数 919876xxxxx 使用此方法添加
  • 使用基于 Cookie 的身份验证的 Capacitor iOS

    我正在使用 Capacitor v3 NextJS 静态导出和 Django 后端基于生产网站构建 iOS 应用程序 当前的后端身份验证方案通过 cookie 使用 Django 会话 并通过 cookie 设置 CSRF 令牌 应用程序可
  • 移动设备上的 TensorFlow(Android、iOS、Windows Phone)

    我目前正在寻找不同的深度学习框架 特别是用于训练和部署卷积神经网络 要求是 它可以在带有 GPU 的普通 PC 上进行训练 但训练后的模型必须部署在三个主要的移动操作系统上 即 Android iOS 和 Windows Phone Ten
  • iOS Twitter NSURLErrorDomain 代码=-1012

    我正在尝试通过在我的应用程序中注册 Twitter 来获取用户的联系方式 我发现this https github com malcommac DMTwitterOAuthgithub上的项目看起来非常好 我只遇到一个问题 如果我使用来自
  • 如何在多个视图中显示相同的导航栏?

    我可以为一个视图重现以下导航栏 但是 一旦我单击按钮后移至下一个视图 我就会丢失最右边的两个图标 搜索 个人资料 据我所知 从故事板设置导航项目通常是按视图进行的 我可以为每个视图复制这些项目 但我想知道是否有更好的方法来完成一次 是否有教
  • dyld:无法加载插入的库,但可以在模拟器和另一部 iPhone 上使用

    所以我在过去的几个小时里在我的应用程序上编码 在某个时候我决定在我的 iPhone 8 13 3 1 上启动我的应用程序而不是使用模拟器 13 3 它立即崩溃并出现以下错误 dyld warning could not load inser
  • 游戏中心玩家显示名称在沙盒中始终为“我”

    我使用用户的游戏中心显示名称和玩家 ID 来维护他们在我的服务器上的个人资料 当我进行测试时 一切似乎都正确执行 但我的沙箱帐户的用户显示名称显示为 Me 而不是附加到我的帐户的显示名称 Billybobbo 这应该在沙盒模式下发生吗 Co
  • 如何删除以前的 ViewController

    我是一名学生 对编程还很陌生 我正在尝试在业余时间学习 Objective C Swift 我使用 spriteKit 和 swift 制作了一个游戏 有多个菜单 场景 我正在尝试从一个视图控制器转换到另一个视图控制器 为此 我使用了以下代
  • Swift:UICollectionViewCell didSelectItemAtIndexPath 更改背景颜色

    我可以轻松更改单元格的背景颜色CellForItemAtIndexPath method func collectionView collectionView UICollectionView cellForItemAtIndexPath

随机推荐