Domanda

Ho un app che genera un mucchio di jpgs che ho bisogno di trasformare in un video WebM. Sto cercando di ottenere i miei dati RGB dal file JPEG nel campione vpxenc. Riesco a vedere le forme di base dei file JPG originali del video in uscita, ma tutto è colorato verde (anche pixel che dovrebbero essere neri sono circa a metà strada verde) e ogni altra linea di scansione ha qualche spazzatura in esso.

Sto cercando di alimentarlo VPX_IMG_FMT_YV12 dati, che sto assumendo è strutturato in questo modo:

per ogni fotogramma Y dati a 8 bit medie su 8 bit di ogni blocco 2x2 V medie su 8 bit di ciascun 2x2 blocco U

Ecco un immagine di origine e uno screenshot del video che è venuta fuori:

Immagini

E 'del tutto possibile che io sto facendo la conversione RGB-> YV12 in modo non corretto, ma anche se ho codificare solo i dati Y 8 bit e impostare la U e blocchi V a 0, gli sguardi di video circa lo stesso. Sono fondamentalmente in esecuzione i miei dati RGB tramite questa equazione:

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

.. e poi per produrre il 2x2 valori filtrati per U e V che scrivo in vpxenc, solo che (a + b + c + d) / 4, dove a, b, c, d sono U o valori V di ciascun blocco 2x2 pixel.

Quindi mi chiedo:

  1. C'è un modo più semplice (in codice) di prendere i dati RGB e dei mangimi per vpx_codec_encode per ottenere un bel video WebM?

  2. Il mio RGB-> conversione YV12 da qualche parte che non va?

Qualsiasi aiuto sarebbe molto apprezzato.

È stato utile?

Soluzione

freefallr: Certo. Ecco il codice. Si noti che è la conversione del RGB-> YUV in atto così come mettere l'uscita YV12 in pFullYPlane / pDownsampledUPlane / pDownsampledVPlane. Questo codice prodotto bel guardare i video WebM quando ho modificato il loro campione vpxenc di utilizzare questi dati.

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

Altri suggerimenti

mente

Mai. Il regime usavo era corretto, ma ho avuto un errore nel / V codice sottocampionamento U.

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