Frage

Ich habe nämlich die Aufgabe zugewiesen wurde, ein Programm zu schreiben, das eine Probe rohe YUV-Datei nimmt und es in einem Cocoa OpenGL-Programm angezeigt werden.

Ich bin ein Praktikant bei meinen Job und ich habe wenig oder keine Ahnung, wie ich anfangen soll. Ich habe wikipedia & Artikel auf YUV zu lesen, aber ich konnte keine gute Quellcode finden, wie man eine rohe YUV-Datei öffnen, um die Daten extrahieren und sie in RGB umwandeln und im Ansichtsfenster angezeigt werden soll.

Im Grunde muss ich mit den folgenden Aspekten der Aufgabe helfen -wie die YUV-Daten, die von der Probe YUV-Datei zu extrahieren -wie die YUV-Daten in RGB-Farbraum zu konvertieren -wie den RGB-Farbraum in OpenGL anzuzeigen. (Dies glaube ich mit der Zeit herausfinden kann, aber ich brauche wirklich Hilfe bei den ersten beiden Punkten)

Bitte sagen Sie mir entweder die Klassen zu verwenden, oder zeigen Sie mir Orte, an denen ich über YUV Grafik / Video-Display lernen

War es hilfreich?

Lösung

Diese Antwort ist nicht richtig, sehen die anderen Antworten und Kommentare. Ursprüngliche Antwort links unten für die Nachwelt.


Sie können es nicht direkt angezeigt werden soll. Sie müssen es in ein RGB-Textur konvertieren. Wie man es von Wikipedia gesammelt haben können, gibt es eine Reihe von Variationen auf dem YUV-Farbraum. Stellen Sie sicher, dass Sie den richtigen verwenden.

Für jedes Pixel ist die Umwandlung von YUV auf RGB eine einfache lineare Transformation. Sie tun nur das gleiche unabhängig zu jedem Pixel.

Wenn Sie das Bild in RGB konvertiert haben, können Sie es anzeigen, indem Sie eine Textur zu schaffen. Sie müssen glGenTextures() anrufen zuteilen eine Textur Griff, glBindTexture() zu binden, um die Textur auf den Kontext machen, und glTexImage2D() die Texturdaten auf die GPU zu laden. Machen es, rufen Sie wieder glBindTexture(), gefolgt von der Wiedergabe eines Quad mit Texturkoordinaten richtig eingerichtet.

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

So zu machen:

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

Und vergessen Sie nicht glEnable(GL_TEXTURE_2D) an einem gewissen Punkt während der Initialisierung zu rufen und rufen glDeleteTextures(1, &texture) beim Herunterfahren.

Andere Tipps

Ich habe das von einer CCD-Kamera aufgenommen mit YUV-Frames durchgeführt. Leider gibt es eine Reihe von verschiedenen YUV-Formaten. Ich glaube, dass die, die Apple für das GL_YCBCR_422_APPLE Textur-Format verwendet, ist technisch 2VUY422. Um ein Bild von einem YUV422 Rahmen zu konvertieren, erzeugt durch eine IIDC Firewire Kamera 2VUY422, habe ich folgende Zwecke verwendet:

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

Für eine effiziente Anzeige einer YUV-Videoquelle, können Sie einen href verwenden <= "http://developer.apple.com/documentation/graphicsimaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/opengl_texturedata.html#// apple_ref / doc / uid / TP40001987-CH407-SW24" rel = "noreferrer"> Apple Client Speichererweiterung , die Sie so etwas wie die folgende Verwendung einrichten können:

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

Auf diese Weise können Sie schnell die Daten vor jedem Frame in Ihrer clientseitigen Videotextur gespeichert ändern heraus auf dem Bildschirm angezeigt werden.

So zeichnen Sie dann Code wie folgt verwenden:

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

Adam Rosenfield Kommentar ist falsch. Auf Macs können Sie YCbCr (das digitale Äquivalent zu YUV) Texturen mit dem GL_YCBCR_422_APPLE Textur-Format angezeigt werden, wie in der APPLE_ycbcr_422 Erweiterung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top