Domanda

mi è stato assegnato ingegno il compito di scrivere un programma che prende un file YUV grezzo campione e visualizzarli in un programma Cocoa OpenGL.

Sono stagista presso il mio lavoro e mi hanno poca o nessuna idea di come iniziare. Ho letto wikipedia e articoli su YUV, ma non sono riuscito a trovare alcun codice buona fonte su come aprire un file YUV grezzo, estrarre i dati e convertirli in RGB e visualizzarlo nella finestra di visualizzazione.

In sostanza, ho bisogno di aiuto con i seguenti aspetti del compito -come per estrarre i dati dal file YUV YUV campione -come per convertire i dati YUV in spazio colore RGB -come per visualizzare lo spazio colore RGB in OpenGL. (Questo penso di poter capire con il tempo, ma ho davvero bisogno di aiuto con i primi due punti)

Si prega di uno mi dica le classi da utilizzare, o indicarlo in posti dove posso imparare su YUV display grafico / video

È stato utile?

Soluzione

Questa risposta non è corretta, vedere le altre risposte e commenti. risposta originale a sinistra in basso per i posteri.


Non è possibile visualizzare direttamente. Avrai bisogno di convertirlo in una texture RGB. Come avrete capito dal Wikipedia , ci sono un sacco di variazioni sul spazio colore YUV. Assicurarsi che si sta utilizzando quella giusta.

Per ogni pixel, la conversione da YUV a RGB è una trasformazione lineare semplice. Devi solo fare la stessa cosa per ogni pixel in modo indipendente.

Una volta convertito in RGB, è possibile visualizzarlo con la creazione di una texture. È necessario chiamare glGenTextures() per allocare una maniglia tessitura, glBindTexture() di impegnare la consistenza al contesto di rendering, e glTexImage2D() per caricare i dati delle texture alla GPU. Per renderlo, ancora una volta chiama glBindTexture(), seguito dal rendering di un quad con trama coordinate impostato correttamente.

// 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;
}

Per il rendering:

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();

E non dimenticare di chiamare glEnable(GL_TEXTURE_2D) ad un certo punto durante l'inizializzazione, e chiamare glDeleteTextures(1, &texture) durante l'arresto.

Altri suggerimenti

L'ho fatto con cornici YUV catturate da una telecamera CCD. Purtroppo, ci sono una serie di diversi formati YUV. Credo quello che Apple utilizza per il formato GL_YCBCR_422_APPLE trama è tecnicamente 2VUY422. Per convertire un'immagine da un fotogramma YUV422 generato da una telecamera Firewire IIDC a 2VUY422, ho usato il seguente:

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);
    }
}

Per la visualizzazione efficiente di una sorgente video YUV, si potrebbe desiderare di utilizzare stoccaggio client Extension di Apple, che è possibile impostare utilizzando qualcosa di simile al seguente:

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);    

Questo consente di cambiare rapidamente i dati memorizzati nel vostro lato client video di tessitura prima di ogni frame da visualizzare sullo schermo.

Per disegnare, è quindi possibile utilizzare il codice come il seguente:

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();

Il commento di Adam Rosenfield non è corretta. Su Mac, è possibile visualizzare YCbCr (l'equivalente digitale di YUV) texture utilizzando il formato consistenza GL_YCBCR_422_APPLE, come specificato nel APPLE_ycbcr_422 estensione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top