android - opengl es yuv 到 rgb 转换仅显示绿色和粉红色

标签 android ios opengl-es ffmpeg yuv

我正在使用 opengl 着色器将 yuv 转换为 rgb。但它只显示绿色和粉红色。我正在使用 ffmpeg 解码电影。我是这方面的初学者,所以不知道如何解决。 ffmpeg 给我三个 yuv 缓冲区。我直接将这些缓冲区分配给三个纹理。

这是我正在使用的着色器。

static const char* VERTEX_SHADER =
"attribute vec4 vPosition;                      \n"
"attribute vec2 a_texCoord;                     \n"
"varying vec2 tc;                               \n"
"uniform mat4 u_mvpMat;                         \n"
"void main()                                    \n"
"{                                              \n"
"   gl_Position = u_mvpMat * vPosition;         \n"
"   tc = a_texCoord;                            \n"
"}                                              \n";

static const char* YUV_FRAG_SHADER =
"#ifdef GL_ES                                   \n"
"precision highp float;                         \n"
"#endif                                         \n"
"varying vec2 tc;                               \n"
"uniform sampler2D TextureY;                    \n"
"uniform sampler2D TextureU;                    \n"
"uniform sampler2D TextureV;                    \n"
"uniform float imageWidth;                      \n"
"uniform float imageHeight;                     \n"

"void main(void)                                \n"
"{                                              \n"
    "float nx, ny;                              \n"
    "vec3 yuv;                                  \n"
    "vec3 rgb;                                  \n"
    "nx = tc.x;                                 \n"
    "ny = tc.y;                                 \n"

    "yuv.x = texture2D(TextureY, tc).r;         \n"
    "yuv.y = texture2D(TextureU, vec2(nx/2.0, ny/2.0)).r - 0.5;   \n"
    "yuv.z = texture2D(TextureV, vec2(nx/2.0, ny/2.0)).r - 0.5;   \n"

    // Using BT.709 which is the standard for HDTV
    "rgb = mat3( 1,              1,      1,     \n"
                "0,       -0.18732, 1.8556,     \n"
                "1.57481, -0.46813,      0)*yuv;\n"

    // BT.601, which is the standard for SDTV is provided as a reference
    //"rgb = mat3( 1,            1,     1,        \n"
    //            "0,     -0.34413, 1.772,        \n"
    //            "1.402, -0.71414,     0) * yuv; \n"
    "gl_FragColor = vec4(rgb, 1.0);             \n"
"}                                              \n";

输出:

enter image description here

我做错了什么?这个你能帮我吗。

谢谢。

更新:

在调试ffmpeg解码时,我发现ffmpeg解码器给出了PIX_FMT_YUV420P输出格式。我是否必须进行一些调整才能获得正确的图像颜色?

最佳答案

我不确定这个转换:

"rgb = mat3( 1,              1,      1,     \n"
            "0,       -0.18732, 1.8556,     \n"
            "1.57481, -0.46813,      0)*yuv;\n"

刷新我对 GLSL 中矩阵 * 向量运算的内存 using this page as reference ,我认为你要么需要转置系数矩阵,要么将 yuv 移到操作的前面,即 yuv * mat3(...)。执行 mat3(...) * yuv 的操作意味着:

r = y * 1 + u * 1 + v * 1
g = y * 0 + u * -0.18732 + v * 1.8556
b = y * 1.57481 + u * -0.46813 + v * 0

而且这些转换是非常不正确的。

作为另一个引用,这里有一个小型的、完整的示例 GLSL 着色器程序,它可以转换 YUV -> RGB,这可能具有一定的指导意义:http://www.fourcc.org/source/YUV420P-OpenGL-GLSLang.c

关于android - opengl es yuv 到 rgb 转换仅显示绿色和粉红色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21513743/

相关文章:

android - 定时无模式对话框

android - 如果OnItemClickListener 是Android 中的一个接口(interface),我们如何根据它创建一个对象呢?

ios - 无粘贴:canPerformAction:withSender中的操作:

ios - iPhone 应用签名 : A valid signing identity matching this profile could not be found in your keychain

android - OpenGL ES Android 加载屏幕

android - 将触摸区域限制为 libgdx 中的纹理区域

android - 在模拟器中找不到处理地理 Intent 的 Activity

java - 检测电子邮件并通过邮件回复

ios - Crashlytics 中无崩溃 session 的百分比是错误的

java - 在 Android 上的 OpenGL ES 中交错的每个顶点数据的偏移量