Display-YUV in OpenGl

Ich habe Probleme bei der Anzeige eines raw-YUV-Datei, die es im NV12-format.

Kann ich die Anzeige eines ausgewählten Rahmens, aber es ist immer noch hauptsächlich schwarz und weiß mit bestimmten Schattierungen von rosa und grün.

Hier ist, wie meine Ausgabe sieht so aus
Display-YUV in OpenGl

Sowieso, hier ist, wie mein Programm funktioniert. (Dies erledigen Sie in cocoa/objective-c, aber ich brauche Ihre fachliche Beratung, Programm Algorithmus, der nicht auf die syntax.)

Vor der Ausführung des Programms, die YUV-Datei gespeichert ist, in eine binäre Datei namens "test.yuv". Die Datei ist im NV12-format, d.h. die Y-plan gespeichert ist, dann die UV-plan ist interlaced. Meine Datei extrahieren ist kein problem, denn ich habe eine Menge Prüfungen auf Sie.

Während der initiation, die ich erstellen Sie eine lookup-Tabelle, wird das konvertieren von binary/8 Bissen/ein byte/chars in respektiert, Y, U, V float-Werte

Für die Y-Ebene dies ist mein code

-(void)createLookupTableY //creates a lookup table for converting a single byte into a float between 0 and 1
{
    NSLog(@"YUVFrame: createLookupTableY");
    lookupTableY = new float [256];

    for (int i = 0; i < 256; i++)
    {
        lookupTableY[i] = (float) i /255;
        //NSLog(@"lookupTableY[%d]: %f",i,lookupTableY[i]);//prints out the value of each float
    }
}

Die U-Ebene-lookup-Tabelle

-(void)createLookupTableU //creates a lookup table for converting a single byte into a float between 0 and 1
{
    NSLog(@"YUVFrame: createLookupTableU");
    lookupTableU = new float [256];

    for (int i = 0; i < 256; i++)
    {
        lookupTableU[i] =  -0.436 + (float) i / 255* (0.436*2);
        NSLog(@"lookupTableU[%d]: %f",i,lookupTableU[i]);//prints out the value of each float
    }
}

Und der V-look-up-Tabelle

-(void)createLookupTableV //creates a lookup table for converting a single byte into a float between 0 and 1
{
    NSLog(@"YUVFrame: createLookupTableV");
    lookupTableV = new float [256];

    for (int i = 0; i < 256; i++)
    {
        lookupTableV[i] =  -0.615 + (float) i /255 * (0.615*2);
        NSLog(@"lookupTableV[%d]: %f",i,lookupTableV[i]);//prints out the value of each float
    }
}

nach diesem Punkt, ich nutze die Y & UV-planen und speichern Sie Sie in zwei Puffer, yBuffer & uvBuffer

ich an dieser Stelle versuchen, zu konvertieren, YUV-Daten gespeichert und es in ein RGB-buffer-array, genannt "frameImage"

-(void)sortAndConvert//sort the extracted frame data into an array of float
{
    NSLog(@"YUVFrame: sortAndConvert");
    int frameImageCounter = 0;
    int pixelCounter = 0;
    for (int y = 0; y < YUV_HEIGHT; y++)//traverse through the frame's height
    {
        for ( int x = 0; x < YUV_WIDTH; x++)//traverse through the frame's width
        {

            float Y = lookupTableY [yBuffer [y*YUV_WIDTH + x] ];
            float U = lookupTableU [uvBuffer [ ((y / 2) * (YUV_WIDTH / 2) + (x/2)) * 2  ] ]; 
            float V = lookupTableV [uvBuffer [  ((y / 2) * (YUV_WIDTH / 2) + (x/2)) * 2 + 1] ];

            float RFormula = Y + 1.13983f * V;
            float GFormula = Y - 0.39465f * U - 0.58060f * V;
            float BFormula = Y + 2.03211f * U;

             frameImage [frameImageCounter++] = [self clampValue:RFormula];
             frameImage [frameImageCounter++] = [self clampValue:GFormula];
             frameImage [frameImageCounter++] = [self clampValue:BFormula];

        }
    }

}

dann habe ich versucht das Image zeichnen in OpenGl

-(void)drawFrame:(int )x
{

    GLuint texture;

    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, YUV_WIDTH, YUV_HEIGHT, 0, GL_RGB, GL_FLOAT, frameImage);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, texture);
    glRotatef( 180.0f, 1.0f, 0.0f, 0.0f );

    glBegin( GL_QUADS );
    glTexCoord2d(0.0,0.0); glVertex2d(-1.0,-1.0);
    glTexCoord2d(1.0,0.0); glVertex2d(+1.0,-1.0);
    glTexCoord2d(1.0,1.0); glVertex2d(+1.0,+1.0);
    glTexCoord2d(0.0,1.0); glVertex2d(-1.0,+1.0);
    glEnd();

    glFlush();
}

also im Grunde dieser mein Programm in einer nussschale. im wesentlichen lese ich die binary YUV-Dateien speichert alle Daten in ein char-array Puffer. ich habe dann übersetzen Sie diese Werte in Ihr respektiert YUV-float-Werte.

Dies ist, wo ich denke, der Fehler könnte sein: in der Y-lookup-Tabelle, die ich standardisieren der Y-Ebene auf [0,1], in der U-Ebene I standardisierte Werte zwischen [-0.435,0.436], und in der V Ebene I standardisierte it-bewteen [-0.615,0.615]. Ich Tat dies, weil diejenigen, die die YUV-Wert reicht laut wikipedia.

Und den YUV-RGB-Formel ist die Formel aus Wikipedia. Ich habe auch versucht, verschiedene andere Formeln, und dieses ist die einzige Formel, das gibt das raue outlook des Rahmens. Wer könnte es Wagen zu raten, warum mein Programm ist nicht korrekt anzeigt, YUV-frame-Daten. Ich denke, es ist etwas zu tun mit meiner Standardisierung von Technik, aber es scheint in Ordnung für mich.

Ich habe schon viele Prüfungen, und ich bin 100% sicher, dass der Fehler verursacht wird, durch die look-up-Tabelle. Ich glaube nicht, dass meine Einstellung, die Formeln sind korrekt.

Einen Hinweis an alle, die das Lesen
diese. Für die längste Zeit, meinen Rahmen
wurde nicht richtig angezeigt, weil ich
war nicht in der Lage, extrahieren Sie die frame-Daten
richtig.

Als ich anfing zu Programmieren, war ich
unter dem Eindruck, dass in einem clip
sagen wir 30 Bilder, alle 30 Y planar-Daten
zuerst geschrieben in der Daten Datei,
danach folgt die UV-Ebene Daten.

Was ich herausgefunden habe, durch Versuch und
Fehler war, dass für ein YUV-Daten Datei,
speziell NV12, die Daten-Datei ist
gespeichert in der folgenden Weise

Y(1) UV(1) Y(2) UV(2) ... ...

@nschmidt

Änderte ich meinen code auf das, was Sie vorgeschlagen

float U = lookupTableU [uvBuffer [ (y * (YUV_WIDTH / 4) + (x/4)) * 2 ] ]
float V = lookupTableU [uvBuffer [ (y * (YUV_WIDTH / 4) + (x/4)) * 2 + 1] ]

und das ist das Ergebnis, dass ich
Display-YUV in OpenGl

hier ist die print Zeile aus der Konsole. ich bin drucken Sie die Werte für Y, U, V und
RGB-Wert, übersetzt und gespeichert in der frameImage-array

YUV:[0.658824,-0.022227,-0.045824] RGBFinal:[0.606593,0.694201,0.613655]

YUV:[0.643137,-0.022227,-0.045824] RGBFinal:[0.590906,0.678514,0.597969]

YUV:[0.607843,-0.022227,-0.045824] RGBFinal:[0.555612,0.643220,0.562675]

YUV:[0.592157,-0.022227,-0.045824] RGBFinal:[0.539926,0.627534,0.546988]

YUV:[0.643137,0.025647,0.151941] RGBFinal:[0.816324,0.544799,0.695255]

YUV:[0.662745,0.025647,0.151941] RGBFinal:[0.835932,0.564406,0.714863]

YUV:[0.690196,0.025647,0.151941] RGBFinal:[0.863383,0.591857,0.742314]

Update Juli 13, 2009

War das problem endlich gelöst, Dank der Empfehlung von nschmidt . Es stellt sich heraus, dass mein YUV-Datei war eigentlich in YUV 4:1:1-format. Ich war ursprünglich gesagt, dass es im YUV-NV12-format. Anyways, ich würde gerne meine Ergebnisse mit Ihnen.

Hier ist die Ausgabe

Display-YUV in OpenGl

und mein code für die Dekodierung ist wie folgt

        float Y = (float) yBuffer [y*YUV_WIDTH + x] ;
        float U = (float) uvBuffer [ ((y / 2) * (YUV_WIDTH  / 2) + (x/2))   ] ; 
        float V = (float) uvBuffer [  ((y / 2) * (YUV_WIDTH  / 2) + (x/2))  + UOffset] ;

        float RFormula = (1.164*(Y-16) + (1.596* (V - 128) ));
        float GFormula = ((1.164 * (Y - 16)) - (0.813 * ((V) - 128)) - (0.391 * ((U) - 128)));
        float BFormula = ((1.164 * (Y - 16)) + (2.018 * ((U) - 128)));


        frameImage [frameImageCounter] = (unsigned char)( (int)[self clampValue:RFormula]);
        frameImageCounter ++;
        frameImage [frameImageCounter] =  (unsigned char)((int)[self clampValue:GFormula]);
        frameImageCounter++;
        frameImage [frameImageCounter] = (unsigned char)((int) [self clampValue:BFormula]);
        frameImageCounter++;



GLuint texture;

glGenTextures(1, &texture);
glEnable(GL_TEXTURE_2D);

glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, YUV_WIDTH, YUV_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, frameImage);

//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE_SGIS);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE_SGIS);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);

glRotatef( 180.0f, 1.0f, 0.0f, 0.0f );

glBegin( GL_QUADS );
glTexCoord2d(0.0,0.0); glVertex2d(-1.0,-1.0);
glTexCoord2d(1.0,0.0); glVertex2d(+1.0,-1.0);
glTexCoord2d(1.0,1.0); glVertex2d(+1.0,+1.0);
glTexCoord2d(0.0,1.0); glVertex2d(-1.0,+1.0);
glEnd();

NSLog(@"YUVFrameView: drawRect complete");
glFlush();

im wesentlichen die, die ich verwendet, NSData für die raw-Datei Extraktion. gespeichert in ein char-array Puffer. Für YUV-zu-RGB-Konvertierung, ich habe die oben genannten Formel, danach habe ich gespannt die Werte auf [0:255]. dann habe ich eine 2DTexture in OpenGL für die Darstellung.

Also, wenn Sie die Umwandlung YUV-zu-RGB in der Zukunft, verwenden Sie die Formel von oben. Wenn mit dem YUV-RGB-Konvertierung Formel von der früheren post, dann müssen Sie zur Anzeige der textur im GL_Float aus die Werte für RGB sind eingespannt zwischen [0:1]

Schreibe einen Kommentar