【问题标题】:YUV to RGB by Shader on iPhoneiPhone 上 Shader 将 YUV 转为 RGB
【发布时间】:2012-05-20 23:34:58
【问题描述】:

目前我正在使用 FFMPEG 开发视频播放器。 我正在尝试通过 Shader 将 YUV420P 转换为 RGB 以减少性能损失,我可以看到它工作正常。问题是我尝试更改图像大小时引起的。

案例 1. YUV to RGB 是完美的。但图像并不完全适合纹理边界。 例如,如果我播放 640x360 视频,右侧 (640-512) 部分被裁剪,底部 (512-360) 填充绿色矩形。

FRAME_X=512; //This is texture size
FRAME_Y=512;

    avpicture_fill((AVPicture *) f, [currentVideoBuffer.data mutableBytes],
               enc->pix_fmt,
               FRAME_X, FRAME_Y);

    av_picture_copy((AVPicture *) f, (AVPicture *) avFrame,
                enc->pix_fmt,
                enc->width, enc->height);

....

int yuvWidth= FRAME_X ;
int  yuvHeight= FRAME_Y;
glBindTexture ( GL_TEXTURE_2D, textureIdY );
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 
yuvWidth, yuvHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, y_channel);


glBindTexture ( GL_TEXTURE_2D, textureIdU );
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE,
yuvWidth/2, yuvHeight/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, u_channel);

glBindTexture ( GL_TEXTURE_2D, textureIdV );
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 
yuvWidth/2, yuvHeight/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, v_channel);

案例 2。如果我将实际图像大小设置为纹理大小,则图像完全适合纹理,但图像颜色有点奇怪。它有太多的绿色。

有人给我一些线索吗? 提前致谢。

【问题讨论】:

    标签: ffmpeg shader yuv


    【解决方案1】:

    首先,您需要为两个非幂次纹理设置正确的环绕模式。

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    

    然后,尝试将过滤模式设置为 GL_LINEAR

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);  
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);  
    

    还有着色器。

    1. 顶点着色器

      attribute vec4 position;  
      attribute vec2 texcoord;  
      uniform mat4 modelViewProjectionMatrix;  
      varying vec2 v_texcoord;
      
      void main()  
      {  
        gl_Position = modelViewProjectionMatrix * position;  
        v_texcoord = texcoord.xy;  
      }  
      
    2. 设置顶点

      vertices[0] = -1.0f;  // x0
      vertices[1] = -1.0f;  // y0
      vertices[2] =  1.0f;  // ..
      vertices[3] = -1.0f;
      vertices[4] = -1.0f;
      vertices[5] =  1.0f;
      vertices[6] =  1.0f;  // x3
      vertices[7] =  1.0f;  // y3
      
    3. 加载适当的 viewProj 矩阵,对于 2d 图像(精灵),最好使用正射投影。

      GLfloat modelviewProj[16];  
      mat4f_LoadOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, modelviewProj);  
      glUniformMatrix4fv(_uniformMatrix, 1, GL_FALSE, modelviewProj);  
      
    4. 接下来,确保你使用正确的文本坐标,像这样

      GLfloat texCoords[] = {  
        0.0f, 1.0f,  
        1.0f, 1.0f,  
        0.0f, 0.0f,  
        1.0f, 0.0f,  
      };  
      
    5. 最后,片段着色器是这样的:

      varying highp vec2 v_texcoord;  
      uniform sampler2D s_texture_y;  
      uniform sampler2D s_texture_u;  
      uniform sampler2D s_texture_v;
      
      void main()  
      {  
        highp float y = texture2D(s_texture_y, v_texcoord).r;  
        highp float u = texture2D(s_texture_u, v_texcoord).r - 0.5;  
        highp float v = texture2D(s_texture_v, v_texcoord).r - 0.5;  
        highp float r = y +             1.402 * v;  
        highp float g = y - 0.344 * u - 0.714 * v;  
        highp float b = y + 1.772 * u;       
        gl_FragColor = vec4(r,g,b,1.0);  
      }  
      

    您可以将我的代码作为在 iOS 上使用 FFmpeg 和 OpenGLES 的示例:https://github.com/kolyvan/kxmovie

    【讨论】:

    • 哦,说谢谢已经太迟了。刚才看到你的回答了。谢谢。
    猜你喜欢
    • 2013-06-10
    • 1970-01-01
    • 1970-01-01
    • 2014-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多