Pregunta

Se me ha asignado la tarea ingenio para escribir un programa que toma un archivo YUV cruda muestra y mostrarlo en un programa de cacao OpenGL.

Soy pasante en mi trabajo y tengo poca o ninguna idea de cómo empezar. He estado leyendo Wikipedia y Artículos de YUV, pero no pude encontrar ninguna buena código fuente sobre cómo abrir un archivo YUV prima, extraer los datos y convertirla en RGB y lo mostrará en la ventana de vista.

En esencia, Necesito ayuda con los siguientes aspectos de la tarea -cómo para extraer los datos YUV a partir del archivo de muestra YUV -cómo para convertir los datos YUV en espacio de color RGB -cómo para visualizar el espacio de color RGB en OpenGL. (Éste creo que puedo averiguar con el tiempo, pero realmente necesitan ayuda con los dos primeros puntos)

Por favor, dime ya sea las clases de usar, o que me señale los lugares donde puedo aprender acerca de display gráfico YUV / vídeo

¿Fue útil?

Solución

Esta respuesta no es correcta, ver las otras respuestas y comentarios. Respuesta original dejó para la posteridad a continuación.


No se puede visualizar directamente. Tendrá que convertirla en una textura RGB. Como puede haber reunido desde Wikipedia , hay un montón de variaciones en el espacio de color YUV. Asegúrese de que está utilizando la correcta.

Para cada píxel, la conversión de YUV a RGB es una transformación lineal sencillo. Que acaba de hacer lo mismo a cada píxel de forma independiente.

Una vez que haya convertido la imagen a RGB, se puede visualizar mediante la creación de una textura. Es necesario llamar glGenTextures() a asignar un manejador de textura, glBindTexture() para obligar a la textura al contexto render, y glTexImage2D() para cargar los datos de textura a la GPU. Para hacerlo, de nuevo llama glBindTexture(), seguido por la prestación de un quad con coordenadas de textura configurado correctamente.

// parameters: image:  pointer to raw YUV input data
//             width:  image width (must be a power of 2)
//             height: image height (must be a power of 2)
// returns: a handle to the resulting RGB texture
GLuint makeTextureFromYUV(const float *image, int width, int height)
{
    float *rgbImage = (float *)malloc(width * height * 3 * sizeof(float));  // check for NULL
    float *rgbImagePtr = rgbImage;

    // convert from YUV to RGB (floats used here for simplicity; it's a little
    // trickier with 8-bit ints)
    int y, x;
    for(y = 0; y < height; y++)
    {
        for(x = 0; x < width; x++)
        {
            float Y = *image++;
            float U = *image++;
            float V = *image++;
            *rgbImagePtr++ = Y                + 1.13983f * V;  // R
            *rgbImagePtr++ = Y - 0.39465f * U - 0.58060f * V;  // G
            *rgbImagePtr++ = Y + 2.03211f * U;                 // B
        }
    }

    // create texture
    GLuint texture;
    glGenTextures(1, &texture);

    // bind texture to render context
    glBindTexture(GL_TEXTURE_2D, texture);

    // upload texture data
    glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGB, GL_FLOAT, rgbImage);

    // don't use mipmapping (since we're not creating any mipmaps); the default
    // minification filter uses mipmapping.  Use linear filtering for minification
    // and magnification.
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // free data (it's now been copied onto the GPU) and return texture handle
    free(rgbImage);
    return texture;
}

Para hacer:

glBindTexture(GL_TEXTURE_2D, texture);

glBegin(GL_QUADS);
    glTexCoord2f(0.0f, 0.0f); glVertex3f( 0.0f,  0.0f, 0.0f);
    glTexCoord2f(1.0f, 0.0f); glVertex3f(64.0f,  0.0f, 0.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f(64.0f, 64.0f, 0.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f( 0.0f, 64.0f, 0.0f);
glEnd();

Y no se olvide de llamar glEnable(GL_TEXTURE_2D) en algún momento durante la inicialización, y llamar a glDeleteTextures(1, &texture) durante el apagado.

Otros consejos

He hecho esto con marcos YUV capturadas desde una cámara CCD. Por desgracia, hay un número de diferentes formatos YUV. Creo que el que Apple utiliza para el formato GL_YCBCR_422_APPLE textura es técnicamente 2VUY422. Para convertir una imagen a partir de un marco YUV422 generada por una cámara Firewire IIDC a 2VUY422, he utilizado la siguiente:

void yuv422_2vuy422(const unsigned char *theYUVFrame, unsigned char *the422Frame, const unsigned int width, const unsigned int height) 
{
    int i =0, j=0;
    unsigned int numPixels = width * height;
    unsigned int totalNumberOfPasses = numPixels * 2;
    register unsigned int y0, y1, y2, y3, u0, u2, v0, v2;

    while (i < (totalNumberOfPasses) )
    {
        u0 = theYUVFrame[i++]-128;
        y0 = theYUVFrame[i++];
        v0 = theYUVFrame[i++]-128;
        y1 = theYUVFrame[i++];
        u2 = theYUVFrame[i++]-128;
        y2 = theYUVFrame[i++];
        v2 = theYUVFrame[i++]-128;
        y3 = theYUVFrame[i++];

        // U0 Y0 V0 Y1 U2 Y2 V2 Y3

        // Remap the values to 2VUY (YUYS?) (Y422) colorspace for OpenGL
        // Y0 U Y1 V Y2 U Y3 V

        // IIDC cameras are full-range y=[0..255], u,v=[-127..+127], where display is "video range" (y=[16..240], u,v=[16..236])

        the422Frame[j++] = ((y0 * 240) / 255 + 16);
        the422Frame[j++] = ((u0 * 236) / 255 + 128);
        the422Frame[j++] = ((y1 * 240) / 255 + 16);
        the422Frame[j++] = ((v0 * 236) / 255 + 128);
        the422Frame[j++] = ((y2 * 240) / 255 + 16);
        the422Frame[j++] = ((u2 * 236) / 255 + 128);
        the422Frame[j++] = ((y3 * 240) / 255 + 16);
        the422Frame[j++] = ((v2 * 236) / 255 + 128);
    }
}

Para la visualización eficiente de una fuente de vídeo YUV, puede que desee utilizar de Apple extensión de almacenamiento del cliente , que puede configurar usando algo como lo siguiente:

glEnable(GL_TEXTURE_RECTANGLE_EXT);
glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 1);

glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_EXT, videoImageWidth * videoImageHeight * 2, videoTexture);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_SHARED_APPLE);
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);

glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);

glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, videoImageWidth, videoImageHeight, 0, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, videoTexture);    

Esto le permite cambiar rápidamente los datos almacenados dentro de su textura de vídeo del lado del cliente antes de cada cuadro que se mostrará en la pantalla.

Para dibujar, a continuación, puede utilizar código como el siguiente:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);         
glEnable(GL_TEXTURE_2D);

glViewport(0, 0, [self frame].size.width, [self frame].size.height);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
NSRect bounds = NSRectFromCGRect([self bounds]);
glOrtho( (GLfloat)NSMinX(bounds), (GLfloat)NSMaxX(bounds), (GLfloat)NSMinY(bounds), (GLfloat)NSMaxY(bounds), -1.0, 1.0);

glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 1);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, videoImageWidth, videoImageHeight, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, videoTexture);

glMatrixMode(GL_TEXTURE);
glLoadIdentity();

glBegin(GL_QUADS);
    glTexCoord2f(0.0f, 0.0f);
    glVertex2f(0.0f, videoImageHeight);

    glTexCoord2f(0.0f, videoImageHeight);
    glVertex2f(0.0f, 0.0f);

    glTexCoord2f(videoImageWidth, videoImageHeight);
    glVertex2f(videoImageWidth, 0.0f);

    glTexCoord2f(videoImageWidth, 0.0f);
    glVertex2f(videoImageWidth, videoImageHeight);      
glEnd();

Comentario de Adam Rosenfield es incorrecta. En Macs, puede mostrar YCbCr (el equivalente digital a YUV) texturas utilizando el formato de textura GL_YCBCR_422_APPLE, tal como se especifica en el extensión APPLE_ycbcr_422 .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top