我正在使用 OpenGL ES 和 ffmpeg 为 Apple TV 编写媒体播放器框架。 在 OpenGL ES 上渲染需要转换为 RGBA,使用 swscale 的软转换速度慢得令人难以忍受,因此根据互联网上的信息,我想到了两个想法:使用 NEON (如 here)或使用片段着色器和 GL_LUMINANCE 和 GL_LUMINANCE_ALPHA。
因为我对 OpenGL 几乎一无所知,所以第二个选项仍然不起作用:)
你能告诉我如何进行吗? 提前谢谢你。
最佳答案
绝对值得学习 OpenGL ES2.0 着色器:
- 您可以在 GPU 和 CPU 之间实现负载平衡(例如,在 GPU 渲染当前帧的同时对后续帧进行视频解码)。
- 视频帧在任何情况下都需要进入 GPU:如果您的视频具有 4:2:0 采样色度,使用
YCbCr
可为您节省 25% 的总线带宽。 - 您可以使用 GPU 硬件插值器免费获得 4:2:0 色度上采样。 (您的着色器应该配置为对
Y
和C{b,r}
纹理使用相同的顶点坐标,实际上将色度纹理拉伸(stretch)到同一区域。 ) - 在 iOS5 上,使用纹理缓存(请参阅
CVOpenGLESTextureCache*
API 函数)将YCbCr
纹理推送到 GPU 的速度很快(没有数据复制或混合)。与 NEON 相比,您将节省 1-2 个数据副本。
我正在使用这些技术取得很好的效果 in my super-fast iPhone camera app, SnappyCam .
您的实现方向正确:如果您的 CbCr
是交错的。否则,如果所有 YCbCr
组件都是非交错的,则使用三个 GL_LUMINANCE
纹理。
为 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 纹理缓存来更新这些纹理。
我还建议使用跨越纹理坐标空间的 2D varying
(x: [0,1], y: [0,1])
所以您避免在片段着色器中读取任何依赖纹理。根据我的经验,最终结果是超快的,并且根本不会加载 GPU。
关于ios - YUV 到 Apple A4 上的 RGBA,我应该使用着色器还是 NEON?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8451149/