我正在使用 OpenGL ES 和 ffmpeg 为 Apple TV 编写媒体播放器框架。在 OpenGL ES 上渲染需要转换为 RGBA,使用 swscale 的软转换速度慢得让人难以忍受,所以根据互联网上的信息我想出了两个想法:使用霓虹灯(如这里)或使用片段着色器和 GL_LUMINANCE 和 GL_LUMINANCE_ALPHA。
因为我对 OpenGL 几乎一无所知,所以第二个选项仍然不起作用:)
你能给我任何指示如何进行吗?先感谢您。
学习 OpenGL ES2.0 着色器绝对值得:
YCbCr
如果您的视频具有 4:2:0 的采样色度,则使用可以为您节省 25% 的总线带宽。Y
和C{b,r}
纹理使用相同的顶点坐标,实际上将色度纹理拉伸到同一区域。)YCbCr
纹理推送到 GPU 非常快(没有数据复制或混合)。CVOpenGLESTextureCache*
与 NEON 相比,您将保存 1-2 个数据副本。我在我的超快速 iPhone 相机应用程序 SnappyCam 中使用这些技术取得了很好的效果。
你在正确的实现轨道上:使用GL_LUMINANCE
纹理Y
,GL_LUMINANCE_ALPHA
如果你CbCr
是交错的。否则,如果所有组件都是非交错的,则使用三个GL_LUMINANCE
纹理。YCbCr
为 4:2:0 双平面YCbCr
(CbCr
交错的地方)创建两个纹理很简单:
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。
使用 NEON 将 YUV 转换为 RGB 非常慢。使用着色器卸载到 GPU。