iOS - Comment dessiner une YUV image à l'aide d'openGL

Actuellement, je suis en train d'essayer de dessiner une image en utilisant openGL (l'image est mise à jour très souvent, et donc doit être redessiné). Auparavant, j'ai été la conversion de mon image de YUV RVB, puis à l'aide de cette nouvelle image pour dessiner avec openGL. Tout a bien fonctionné, mais le processus de conversion n'a pas été particulièrement rapide.

Je suis en train d'essayer de modifier le code afin que la conversion est pris en charge dans les shaders openGL. Après avoir regardé autour, j'ai trouvé un couple de fragments de code (en particulier les shaders et la majeure partie de mes renderImage fonction) qui m'ont aidé à obtenir une ligne de base, mais je n'arrive pas à réellement obtenir l'image pour dessiner correctement tout ce que je vois est une image noire.

Il est très probable que je suis absent quelque chose d'extrêmement simple et important - Mon expérience avec openGL est plutôt limitée. Si quelqu'un peut jeter un oeil et voir si ils reconnaissent quelque chose de mal, s'il vous plaît laissez-moi savoir.

Je précise, je suis en train de soutien iOS 4.x, de sorte CVOpenGLESTextureCacheCreateTexturefromimage ne devrait pas être utilisable (et je ne suis pas vraiment positif comment le programme d'installation de l'utiliser même si je le voulais).

Toute aide serait appréciée. Le Code ci-dessous -

Mon Vertex shader:

attribute vec4 position;
attribute vec4 inputTextureCoordinate;

varying vec2 textureCoordinate;

void main()
{
    gl_Position = position;
    textureCoordinate = inputTextureCoordinate.xy;
}

Fragment Shader:

#ifdef GL_ES
precision mediump float;
#endif

varying vec2 textureCoordinate;

uniform sampler2D videoFrame;
uniform sampler2D videoFrameUV;

const mat3 yuv2rgb = mat3(
                          1, 0, 1.2802,
                          1, -0.214821, -0.380589,
                          1, 2.127982, 0
                          );

void main() {
    vec3 yuv = vec3(
                    1.1643 * (texture2D(videoFrame, textureCoordinate).r - 0.0625),
                    texture2D(videoFrameUV, textureCoordinate).r - 0.5,
                    texture2D(videoFrameUV, textureCoordinate).a - 0.5
                    );
    vec3 rgb = yuv * yuv2rgb;

    gl_FragColor = vec4(rgb, 1.0);
}

La renderImage fonction:

-(void)renderImage:(ImageBuffer *)image
{
    if (image)
    {        
        int bufferHeight = image->GetHeight();
        int bufferWidth = image->GetWidth();

        if(!imageTexture){
            //Dealing with the Y portion of the YCbCr
            glActiveTexture(GL_TEXTURE0);
            glGenTextures(1, &imageTexture);
            //Bind Y texture
            glBindTexture(GL_TEXTURE_2D, imageTexture);
            glUniform1i(uniforms[UNIFORM_VIDEOFRAME], 0);
            //For fitting
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            //This is necessary for non-power-of-two textures
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

            glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, bufferWidth, bufferHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, image->GetPlanePointer(0));

            //Dealing with the CbCr potion of the YCbCr
            glActiveTexture(GL_TEXTURE1);
            glGenTextures(1, &imageTextureUV);
            //Bind CbCr texture
            glBindTexture(GL_TEXTURE_2D, imageTextureUV);
            glUniform1i(uniforms[UNIFORM_VIDEOFRAMEUV], 1);
            //For fitting
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            //This is necessary for non-power-of-two textures
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

            glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, bufferWidth/2, bufferHeight/2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, image->GetPlanePointer(1));

        }

        [self drawFrame];
    }
}

Et enfin, l'étirage de la fonction:

- (void)drawFrame
{
[self setFramebuffer];
//Replace the implementation of this method to do your own custom drawing.
static const GLfloat squareVertices[] = {
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f
};
static const GLfloat textureVertices[] = {
//       1.0f, 1.0f,
//       1.0f, 0.0f,
//       0.0f,  1.0f,
//       0.0f,  0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f
//       0.0f, 0.8f,
//       1.0f, 0.8f,
//       0.0f, 0.2f,
//       1.0f, 0.2f
};
static float transY = 0.0f;
if ([context API] == kEAGLRenderingAPIOpenGLES2) {
//Use shader program.
glUseProgram(program);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, imageTexture);
//Update attribute values.
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_FLOAT, 0, 0, textureVertices);
glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, imageTextureUV);
//Update attribute values.
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_FLOAT, 0, 0, textureVertices);
glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);
//Validate program before drawing. This is a good check, but only really necessary in a debug build.
//DEBUG macro must be defined in your debug configurations if that's not already the case.
#if defined(DEBUG)
if (![self validateProgram:program]) {
NSLog(@"Failed to validate program: %d", program);
return;
}
#endif
} else {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, (GLfloat)(sinf(transY)/2.0f), 0.0f);
transY += 0.075f;
glVertexPointer(2, GL_FLOAT, 0, squareVertices);
glEnableClientState(GL_VERTEX_ARRAY);
} 
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
[self presentFramebuffer];
}
A votre programme de shaders été compilé avant -renderImage: est appelé? Vous pourriez avoir besoin de mettre un glUseProgram(program); avant votre glUniform1i() appels assurez-vous que le programme est actif et que vous êtes à la définition de la texture uniformes sur le correctement. Aussi, assurez-vous que vous avez défini le contexte actuel avant de le faire. Ce sont deux choses qui ont déclenché moi dans le passé.
ouais, je ne les différentes configuration de base dans une fonction distincte appelé plus tôt - le contexte, la compilation des shaders, et de lier le programme devrait être fait avant renderImage() est appelée. J'ai déplacé un glUseProgram() appel avant que le glUniform1i() appelle, mais ne semble pas changer quoi que ce soit malheureusement.
Pardon pour mon ignorance de ce qui est exposé dans iOS OpenGL ES, mais le GPU PowerVR matériel peut décoder certains YUV textures (au moins selon pandorawiki.org/...). Il n'y a pas d'OpenGL ES extension?

OriginalL'auteur Doc | 2012-09-14