YUV в RGB с помощью шейдера на iPhone

В настоящее время я разрабатываю видеоплеер с использованием FFMPEG. Я пытаюсь преобразовать YUV420P в RGB с помощью шейдера, чтобы уменьшить падение производительности, и я вижу, что он работает нормально. Проблема возникает, когда я пытаюсь изменить размер изображения.

Случай 1. Преобразование YUV в 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. Если я устанавливаю фактический размер изображения в размер текстуры, то изображение точно соответствует текстуре, но цвет изображения немного странный. В нем слишком много зеленого цвета.

Кто-нибудь дает мне некоторые подсказки для этого ?? Заранее спасибо.


person user1333656    schedule 12.05.2012    source источник


Ответы (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);  
    }  
    

Вы можете посмотреть мой код как пример использования FFmpeg и OpenGLES на iOS: https://github.com/kolyvan/kxmovie.

person Kolyvan    schedule 27.10.2012
comment
О, слишком поздно говорить спасибо. Я видел твой ответ прямо перед этим. Спасибо. - person user1333656; 06.03.2013