Frage

Ich habe eine App, die eine Reihe von JPGs generiert, die ich in ein WebM -Video verwandeln muss. Ich versuche, meine RGB -Daten von den JPEGs in das VPXCC -Beispiel zu bringen. Ich kann die grundlegenden Formen aus den ursprünglichen JPGs im Ausgabevideo sehen, aber alles ist grün getönt (selbst Pixel, die schwarz sein sollten, sind ungefähr auf halbem Weg grün) und jeder andere Scanline enthält etwas Müll.

Ich versuche es zu füttern, VPX_IMG_FMT_YV12 -Daten, von denen ich annehme, dass sie so strukturiert sind:

Für jeden Rahmen 8-Bit-Y-Daten 8-Bit-Durchschnittswerte jedes 2x2-V-Blocks 8-Bit-Durchschnittswerte jedes 2x2 U-Blocks

Hier ist ein Quellbild und ein Screenshot des Videos, das herauskommt:

Bilder

Es ist durchaus möglich, dass ich die RGB-> YV12-Konvertierung falsch durchführe, aber selbst wenn ich nur die 8-Bit-Y-Daten codiere und die U- und V-Blöcke auf 0 setze, sieht das Video ungefähr gleich aus. Ich leite meine RGB -Daten im Grunde über diese Gleichung aus:

// (R, G, and B are 0-255)
float y = 0.299f*R + 0.587f*G + 0.114f*B;
float v = (R-y)*0.713f;
float u = (B-v)*0.565f;

.. und dann, um die 2x2 gefilterten Werte für u und v zu produzieren, die ich in vpxenc schreibe, mache ich einfach (a + b + c + d) / 4, wobei a, b, c, d die u oder v -Werte von sind Jeder 2x2 Pixelblock.

Also frage ich mich:

  1. Gibt es einen einfacheren Weg (im Code), RGB -Daten zu übernehmen und sie an vpx_codec_encode zu füttern, um ein schönes WebM -Video zu erhalten?

  2. Ist meine RGB-> YV12-Konvertierung irgendwo falsch?

Jede Hilfe wäre sehr geschätzt.

War es hilfreich?

Lösung

FreeFallr: Sicher. Hier ist der Code. Beachten Sie, dass die RGB-> YUV an Ort und Stelle konvertiert wird und die YV12-Ausgabe in PUFIFLEPLANE/PDWODSAMPLEDUPLANE/PDWOWSAMPLEDVPLANE einfügt. Dieser Code hat gut aussehende Webm -Videos erstellt, als ich das VPXCC -Beispiel so geändert habe, dass diese Daten verwendet werden.

void RGB_To_YV12( unsigned char *pRGBData, int nFrameWidth, int nFrameHeight, void *pFullYPlane, void *pDownsampledUPlane, void *pDownsampledVPlane )
{
    int nRGBBytes = nFrameWidth * nFrameHeight * 3;

    // Convert RGB -> YV12. We do this in-place to avoid allocating any more memory.
    unsigned char *pYPlaneOut = (unsigned char*)pFullYPlane;
    int nYPlaneOut = 0;

    for ( int i=0; i < nRGBBytes; i += 3 )
    {
        unsigned char B = pRGBData[i+0];
        unsigned char G = pRGBData[i+1];
        unsigned char R = pRGBData[i+2];

        float y = (float)( R*66 + G*129 + B*25 + 128 ) / 256 + 16;
        float u = (float)( R*-38 + G*-74 + B*112 + 128 ) / 256 + 128;
        float v = (float)( R*112 + G*-94 + B*-18 + 128 ) / 256 + 128;

        // NOTE: We're converting pRGBData to YUV in-place here as well as writing out YUV to pFullYPlane/pDownsampledUPlane/pDownsampledVPlane.
        pRGBData[i+0] = (unsigned char)y;
        pRGBData[i+1] = (unsigned char)u;
        pRGBData[i+2] = (unsigned char)v;

        // Write out the Y plane directly here rather than in another loop.
        pYPlaneOut[nYPlaneOut++] = pRGBData[i+0];
    }

    // Downsample to U and V.
    int halfHeight = nFrameHeight >> 1;
    int halfWidth = nFrameWidth >> 1;

    unsigned char *pVPlaneOut = (unsigned char*)pDownsampledVPlane;
    unsigned char *pUPlaneOut = (unsigned char*)pDownsampledUPlane;

    for ( int yPixel=0; yPixel < halfHeight; yPixel++ )
    {
        int iBaseSrc = ( (yPixel*2) * nFrameWidth * 3 );

        for ( int xPixel=0; xPixel < halfWidth; xPixel++ )
        {
            pVPlaneOut[yPixel * halfWidth + xPixel] = pRGBData[iBaseSrc + 2];
            pUPlaneOut[yPixel * halfWidth + xPixel] = pRGBData[iBaseSrc + 1];

            iBaseSrc += 6;
        }
    }
}

Andere Tipps

Macht nichts. Das von mir verwendete Schema war korrekt, aber ich hatte einen Fehler im U/V -Downsampling -Code.

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