6
\$\begingroup\$

The input pointer *data contains the data that needs to be split into different arrays and put in yuvInput. Each pixel is 32 bytes 4 * 8. Note the (j*4) to break it up per pixel segment. The 4th byte is the alpha channel which gets skipped (the reason there is no idx+3).

This method needs optimization. If anyone is willing to help, please do.

void SplitYUVPlanes(int width, int height, unsigned char *data, int size, unsigned char *yuvInput[3])
{
    // live input *data is YUV444 Packed
    // Conversion from 444 Packed -> 444 Planar
    int index = 0;
    int srcStride = size;

    // need to flip image from bottom-up to top-down
    int revheight = height - 1;

    unsigned char* pLuma = yuvInput[0];
    unsigned char* pChromaU = yuvInput[1];
    unsigned char* pChromaV = yuvInput[2];

    for (int i = 0; i < height; ++i)
    {
        // read bottom line first
        int line = (revheight - i) * srcStride;

        for (int j = 0; j < width; ++j)
        {
            int idx = line + (j * 4);
            pLuma[index] = data[idx + 2]; //Y
            pChromaV[index] = data[idx + 1]; //V
            pChromaU[index] = data[idx + 0]; //U
            index++;
        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ Your issue is locality of reference. you are very limited. one thing you can do is read as much data at once, and then write that. for instance, you can read 8 bytes in a 64 bit integer first, and then write once in a 64 bit integer. To read more than 64 bit you will have to be architecture dependent. \$\endgroup\$ – UmNyobe Feb 12 '14 at 10:10
2
\$\begingroup\$

Your multiplication expressions aren't ideal; instead (which might be faster) you could add 4 and subtract srcStride from the previous value at the top of each loop.

Apart from that (and this is just a guess) I guess some other things might in theory make this faster.

  1. Have three loops: write to Luma in the 1st loop, then write to ChromaV in the 2nd loop, and write to ChromaU in the 3rd loop.
  2. Calibrate the length of (number of bytes moved in) each loop, so that the chunk of input data stays in cache for each of the three loops
  3. Use some kind of read-ahead, to ensure that the byte is read before it needs to be written, for example:
    • Read 1st byte
    • Read 2nd byte
    • Read 3rd byte
    • Read 4th byte
    • Write 1st byte
    • Read 5th byte
    • Write 2nd byte
    • etc.
  4. Read 4 or 8 bytes at a time, for example into a struct which contains 4 or 8 byte-fields and is a union with an int32 or int64 field.
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.