11

我正在使用 OpenGL ES 和 ffmpeg 为 Apple TV 编写媒体播放器框架。在 OpenGL ES 上渲染需要转换为 RGBA,使用 swscale 的软转换速度慢得让人难以忍受,所以根据互联网上的信息我想出了两个想法:使用霓虹灯(如这里)或使用片段着色器和 GL_LUMINANCE 和 GL_LUMINANCE_ALPHA。

因为我对 OpenGL 几乎一无所知,所以第二个选项仍然不起作用:)

你能给我任何指示如何进行吗?先感谢您。

4

2 回答 2

21

学习 OpenGL ES2.0 着色器绝对值得:

  1. 您可以在 GPU 和 CPU 之间进行负载平衡(例如,在 GPU 渲染当前帧时对后续帧进行视频解码)。
  2. 在任何情况下,视频帧都需要进入 GPU:YCbCr如果您的视频具有 4:2:0 的采样色度,则使用可以为您节省 25% 的总线带宽。
  3. 您可以使用 GPU 硬件插值器免费获得 4:2:0 色度上采样。(您的着色器应配置为对纹理YC{b,r}纹理使用相同的顶点坐标,实际上将色度纹理拉伸到同一区域。)
  4. 在 iOS5上,使用纹理缓存(请参阅API 函数)将YCbCr纹理推送到 GPU 非常快(没有数据复制或混合)。CVOpenGLESTextureCache*与 NEON 相比,您将保存 1-2 个数据副本。

在我的超快速 iPhone 相机应用程序 SnappyCam 中使用这些技术取得了很好的效果。

你在正确的实现轨道上:使用GL_LUMINANCE纹理YGL_LUMINANCE_ALPHA如果你CbCr是交错的。否则,如果所有组件都是非交错的,则使用三个GL_LUMINANCE纹理。YCbCr

为 4:2:0 双平面YCbCrCbCr交错的地方)创建两个纹理很简单:

    glBindTexture(GL_TEXTURE_2D, texture_y);
    glTexImage2D(
        GL_TEXTURE_2D, 
        0, 
        GL_LUMINANCE,        // Texture format (8bit)
        width,
        height,
        0,                   // No border
        GL_LUMINANCE,        // Source format (8bit)
        GL_UNSIGNED_BYTE,    // Source data format
        NULL
    );
    glBindTexture(GL_TEXTURE_2D, texture_cbcr);
    glTexImage2D(
        GL_TEXTURE_2D, 
        0, 
        GL_LUMINANCE_ALPHA, // Texture format (16-bit)
        width / 2,
        height / 2,
        0,                  // No border
        GL_LUMINANCE_ALPHA, // Source format (16-bits)
        GL_UNSIGNED_BYTE,   // Source data format
        NULL
    );

然后您将在其中使用glTexSubImage2D()或 iOS5 纹理缓存来更新这些纹理。

我还建议使用varying跨越纹理坐标空间的 2D,以(x: [0,1], y: [0,1])避免在片段着色器中读取任何相关的纹理。最终结果是超快的,并且根据我的经验根本不会加载 GPU。

于 2011-12-28T09:11:14.587 回答
0

使用 NEON 将 YUV 转换为 RGB 非常慢。使用着色器卸载到 GPU。

于 2012-10-03T01:25:34.413 回答