【问题标题】:Converting raw data to displayable video for iOS将原始数据转换为 iOS 的可显示视频
【发布时间】:2013-03-21 06:01:09
【问题描述】:

我有一个有趣的问题需要研究,与非常低级的视频流相关。

有没有人将原始字节流(分隔为每个像素信息,但不是标准的视频格式)转换为低分辨率视频流的经验?我相信我可以将数据映射为每像素字节的 RGB 值,因为与原始数据中的值对应的颜色值将由我们确定。我不确定从那里去哪里,或者每个像素需要什么 RGB 格式。

我查看过 FFMPeg,但它的文档非常庞大,我不知道从哪里开始。

我的具体问题包括,是否可以使用该像素数据创建 CVPixelBuffer?如果我要这样做,我需要将每像素数据转换为哪种格式?

另外,我是否应该更深入地研究 OpenGL,如果是的话,在哪里可以找到有关该主题的信息的最佳位置?

CGBitmapContextCreate 怎么样?例如,如果我使用this 之类的东西,典型的像素字节需要是什么样的?这是否足以将帧速率保持在 20fps 以上?

编辑

我认为在你们两个的出色帮助下,再加上我自己的一些研究,我已经制定了如何构建原始 RGBA 数据的计划,然后从该数据构建一个 CGImage,进而创建一个 CVPixelBuffer从这里CVPixelBuffer from CGImage的那个CGImage。

但是,要在数据输入时实时播放,我不确定我会看到什么样的 FPS。我是否将它们绘制到 CALayer,或者是否有一些与 AVAssetWriter 类似的类,我可以在附加 CVPixelBuffers 时使用它来播放它。我的经验是使用 AVAssetWriter 将构建的 CoreAnimation 层次结构导出到视频,因此视频总是在开始播放之前构建,而不是显示为实时视频。

【问题讨论】:

  • 深入了解 AVFoundation,尤其是 AVAssetWriter。阅读该文档后,一个好的起点可能是“How do I export an UIImage array as a movie”。
  • 我已经用 AVAssetWriter 做了很多工作,但我目前的问题是我不知道如何构造原始像素数据。
  • 确实是这个问题。您必须弄清楚如何使用从流中接收到的原始数据构建像素缓冲区。这将取决于传入数据的格式、编码等。完成后,请检查@Till 推荐的帖子和 AVAssetWritter。这可能有助于 CVPixelBufferRef buffer = (CVPixelBufferRef)[self pixelBufferFromCGImage:theImage size:CGSizeMake(image.size.width, image.size.height)]; if (buffer) { if(![适配器 appendPixelBuffer:buffer withPresentationTime:CMTimeMake(frame, fps)]){
  • 我在评论中添加了更多信息,然后由于篇幅原因不得不将其添加到答案中。谢谢你们,我越来越近了,但我还有几个问题。

标签: ios video encoding opengl-es core-video


【解决方案1】:

我以前做过,而且我知道您不久前找到了我的 GPUImage 项目。正如我在那里回答的问题一样,GPUImageRawDataInput 是您想要的,因为它可以将 RGBA、BGRA 或 RGB 数据直接快速上传到 OpenGL ES 纹理中。从那里,可以过滤帧数据、显示到屏幕上或记录到电影文件中。

根据我的个人经验,您建议的通过 CGImage 到 CVPixelBuffer 的路径不会产生非常好的性能。通过 Core Graphics 获取实时视频时开销太大。您想在这里直接进入OpenGL ES以获得最快的显示速度。

我什至可以改进我的代码,使其比现在更快。我目前使用glTexImage2D() 从本地字节更新纹理数据,但是使用iOS 5.0 中引入的纹理缓存来加速在保持其大小的纹理中刷新数据可能会更快。设置缓存会产生一些开销,这会使一次性上传速度稍慢一些,但使用它们快速更新数据应该会更快。

【讨论】:

  • 无法告诉您我多么感谢您的帮助。我在那边回答,但为了防止其他人来看,我只是想确保我正确理解了这门课。我猜我在 GPUImageRawDataInput 上每帧调用 uploadBytes?从那里我添加我使用的 GPUImageFilter 作为 RawDataInput 的目标,然后添加 GPUImageView 作为我使用的过滤器的目标?如果我想跳过过滤器,我可以将 RawDataInput 添加为 GPUImageView 的目标,还是以某种方式使用 RawDataOutput?
  • @MattFoley - 是的,您需要在每个新帧进入时使用-uploadBytes:。您还需要使用-processData 跟随它以使其传播到其余部分上传后的管道。如果您只关心显示,您可以直接从原始数据输入转到 GPUImageView。
  • 嗨,布拉德,一年后,我仍在利用空闲时间开发这个软件。你提到如果显示是最重要的,我只需要调用“processData:”。我很高兴地说,我们已经播放原始数据已经有一段时间了,但目前我正在努力将 GPUImageMovieWriter 与你帮助我的 GPUImageRawDataInput 集成,并在 AVAssetWriter 上运行到“12902”状态时开始录制。这是我的代码:pastebin.com/LD6ZcJtN 我还缺少额外的步骤吗?感谢布拉德所做的一切!
  • 添加到此评论中,我发现我正在录制的视频大小存在更深层次的问题。我收到设备控制台的以下输出,抱怨 80x80 不满足未通过管道传输到 Xcode 的 h264 编解码器的最小尺寸要求:pastebin.com/bVQ7PJ12
【解决方案2】:

我的 2 美分:

我制作了一个 opengl 游戏,可以让用户录制 3d 场景。回放是通过重播场景完成的(而不是播放视频,因为实时编码不会产生舒适的 FPS。

有一种技术可以提供帮助,不幸的是我没有时间实施它: http://allmybrain.com/2011/12/08/rendering-to-a-texture-with-ios-5-texture-cache-api/

这种技术应该可以减少从 OpenGL 获取像素的时间。您可能会获得可接受的视频编码率。

【讨论】:

    猜你喜欢
    • 2022-11-02
    • 2014-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-17
    • 1970-01-01
    • 2013-10-26
    • 2017-10-17
    相关资源
    最近更新 更多