This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

PAL YUV420 Planar Format to PAL YUV422 Interleaved Format

Hi,

I’m trying to migrate software from DM642 platform to DM6437.

I realized that for presenting an image to TV I can’t do how I did before because of DM6437 VPORT don’t supports planar format like DM642. I have been seen SPRAAN4A document (“How to Use the EDMA3 Driver on a TMS320DM643x Device”), here there is an example on page 4 about how to convert an image from YUV422 format to YUV420 format

Do someone have a complementary example, because I need to pass from PAL YUV420 Planar Format to PAL YUV422 Interleaved Format 

Thanks in advance

  • Unfortunately I am not aware of a complementary example, but this requires moving of data around so it would not be too difficult to extend lessons learned from the App Note and implement Planar to interleaved conversion.  Actually, you MAY be able to use resizer (accepts planar data) to convert planar data to interleaved.

  • The resizer does not perform a planar to interleaved conversion, though it accepts planar data, it does so by performing individual resizings on each planar buffer. You could probably implement this more elegantly with the EDMA, but below is some C Pseudo code for how you could do this from the CPU both a 422 and 420 conversion (no guarantees but I think this should do it).

    Bernie's Pseudo Code said:

    /****** 4:2:2 planar to 4:2:2 interleaved ******/
    //first invalidate the cache with a BCACHE call over your three planar buffers
    BCACHE_inv(crcharinput, (HEIGHT*WIDTH)/2, 1);
    BCACHE_inv(cbcharinput, (HEIGHT*WIDTH)/2, 1);
    BCACHE_inv(ycharinput, (HEIGHT*WIDTH), 1);
       
        for (i=0;i<((HEIGHT*WIDTH)/2);i++)//we go through two pixels at a time (4 bytes) thus for half image size
        {

            *outBuf = crcharinput[i];     //grab the Cr value /** forum issue: the lightbulb is [ i ] **/
            outBuf++;                     //increment the buffer
            *outBuf = ycharinput[(i*2)];  //grab the Y value (i*2 because we get two Y per loop)
            outBuf++;                     //increment the buffer
            *outBuf = cbcharinput[i];     //grab the Cb value
            outBuf++;                     //increment the buffer
            *outBuf = ycharinput[(i*2)+1];//grab the next Y value
            outBuf++;                     //increment the buffer


        }

    //now write back and invalidate the cache over the new output buffer
    BCACHE_wbInv(outBuf, HEIGHT*WIDTH*2, 1);

    Bernie's Pseudo Code said:

    /******* 4:2:0 planar to 4:2:2 interleaved *******/
    //first invalidate the cache with a BCACHE call over your three planar buffers
    BCACHE_inv(crcharinput, (HEIGHT*WIDTH)/4, 1);
    BCACHE_inv(cbcharinput, (HEIGHT*WIDTH)/4, 1);
    BCACHE_inv(ycharinput, (HEIGHT*WIDTH), 1);
       
        for (i=0;i<((HEIGHT*WIDTH)/2);i++)//we go through two pixels at a time (4 bytes) thus for half image size
        {

            *outBuf = crcharinput[ceil(i/2)]; //grab the Cr value (ceil(i/2) so we grab the same chroma for each pair of loops)
            outBuf++;                         //increment the buffer
            *outBuf = ycharinput[(i*2)];      //grab the Y value (i*2 because we get two Y per loop)
            outBuf++;                         //increment the buffer
            *outBuf = cbcharinput[ceil(i/2)]; //grab the Cb value
            outBuf++;                         //increment the buffer
            *outBuf = ycharinput[(i*2)+1];    //grab the next Y value
            outBuf++;                         //increment the buffer


        }

    //now write back and invalidate the cache over the new output buffer
    BCACHE_wbInv(outBuf, HEIGHT*WIDTH*2, 1);

    EDIT: The 4:2:0 code is bad, it will end up giving funky chroma, the chroma must be scaled vertically not horizontally, working on a fix...

  • I think the 420 pseudo code below makes more sense, of course I have not tried any of these, and I don't do much 420 work, but hopefully they can help as a start, there are probably fancier ways of handling this sort of conversion...

    Bernie's Pseudo Code said:

    //4:2:0 planar to 4:2:2 interleaved
    //first invalidate the cache with a BCACHE call over your three planar buffers
    BCACHE_inv(crcharinput, (HEIGHT*WIDTH)/4, 1);
    BCACHE_inv(cbcharinput, (HEIGHT*WIDTH)/4, 1);
    BCACHE_inv(ycharinput, (HEIGHT*WIDTH), 1);

    i=0;
    for (y=0;y<HEIGHT;y++){
      for (x=0;x<WIDTH/2;x++){
            i++;
            *outBuf = crcharinput[x+(ceil(y/2)*WIDTH)]; //grab the Cr value (the ceil(y/2) should increment every other line so we scale vertically)
            outBuf++;                         //increment the buffer
            *outBuf = ycharinput[i*2];        //grab the Y value (i*2 because we get two Y per loop)
            outBuf++;                         //increment the buffer
            *outBuf = cbcharinput[x+(ceil(y/2)*WIDTH)]; //grab the Cb value
            outBuf++;                         //increment the buffer
            *outBuf = ycharinput[(i*2)+1];    //grab the next Y value
            outBuf++;                         //increment the buffer
        }
    }
    //now write back and invalidate the cache over the new output buffer
    BCACHE_wbInv(outBuf, HEIGHT*WIDTH*2, 1);

  • Thank you very much

    I will try to perform the data sorting with EDMA3 transfers because I need the better throughput of my program.