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.

Linux/AM5728: GC320 YUYV to RGBA conversion using dmabuf based app

Genius 11740 points

Replies: 3

Views: 603

Part Number: AM5728

Tool/software: Linux

Hi,

I am posting this for one of our customers.

"

I am capturing YUYV format camera frames from the VIP port on the AM5728. I am submitting those frames to the GC320 with the goal of format converting them to RGBA frames. The Galcore driver version is 5.0.11.33433. I am passing a V4L2 DMABUF directly to the GC320 and for debugging I save the raw YUYV file before and after the GC320 rendering. The input frame is 640x480 YUYV, and the output 640x480 RGBA. I've attached the images below. The image on the left is the YUYV from the camera ( reddish due to Ubuntu's image viewer ), and the image on the right is the RGBA frame converted by the GC320. It is apparent that the GC320 "Kind-Of" converts the image - the top half looks good. However, the bottom half of the image is some sort of artifact. This leads me to believe my configuration for the conversion using the GC320 API is wrong. I have studied the GC320 examples as part of the Arago/Yocto ti-gc320-test samples and have put my GC320 Conversion code below - I would greatly appreciate any help understanding what is wrong with it. 

"

(will send attachment in separate post)

GC320 Format function:

/**

* gc320 renderFormatConvertYUYVtoRGBA()

* Purpose: Perform a render cycle for converting frame from YUYV to RGBA

*

* @return Return bool success or failure

*/

gctBOOL Gc320::renderFormatConvertYUYVtoRGBA() {

 

    gceSTATUS status;

 

    // Destination Rectangle

    gcsRECT targetRect;

    gcsRECT sourceRect;

 

    // Destination Rectangle

    targetRect.left = 0;

    targetRect.top = 0;

    targetRect.right = FRAME_WIDTH; // These affect the output image ( destination rect )

    targetRect.bottom = FRAME_HEIGHT; // These affect the output image ( destination rect )

 

    // Source Rectangle

    sourceRect.left = 0;

    sourceRect.top = 0;

    sourceRect.right = FRAME_WIDTH; // These affect the input image ( source rect )

    sourceRect.bottom = FRAME_HEIGHT; // These affect the input image ( source rect )

 

    QElapsedTimer timer;

    timer.restart();

 

    // Set clipping rect for destination rectangle

    gcmONERROR(gco2D_SetClipping(m_Engine2d, &targetRect));

 

    // set kernel size

    gcmONERROR(gco2D_SetKernelSize(m_Engine2d, 1, 1));

 

    gcmONERROR(gco2D_FilterBlitEx2(m_Engine2d,

                (gctUINT32_PTR)&m_SrcPhysAddr, 1,

                (gctUINT32_PTR)&m_SrcStride, 1,

                gcvLINEAR, m_SrcFormat, gcvSURF_0_DEGREE,

                m_SrcWidth, m_SrcHeight, (gcsRECT_PTR)&sourceRect,

                (gctUINT32_PTR)&m_DstPhysAddr, 1, (gctUINT32_PTR)&m_DstStride, 1,

                gcvLINEAR, m_DstFormat, gcvSURF_0_DEGREE,

                m_DstWidth, m_DstHeight, (gcsRECT_PTR)&targetRect,

                gcvNULL));

 

    gcmONERROR(gco2D_Flush(m_Engine2d));

 

    // Commit the current command buffer to hardware and wait until the hardware is finished

    gcmONERROR(gcoHAL_Commit(m_Hal, gcvTRUE));

 

    qDebug() << "Rendered: " << timer.elapsed();

 

#if 1

 

    ////////////////////////////////////////////////////////////////////////////////

 

    // Save RGB24

    {

        // convert -depth 8 -size 640x480+0 RGBA:gc320.rgb gc320.png ; eog gc320.png

        qDebug() << QString("Writing the frame out to /home/root/gc320.rgb");

        QString filename = QString("/home/root/gc320.rgb");

        QFile d(filename);

        d.open(QFile::WriteOnly);

        QDataStream ds(&d);

        qDebug() << "Writing data now...";

        ds.writeRawData((const char*)m_DstVirtAddr,FRAME_WIDTH*FRAME_HEIGHT*4);

        d.flush();

        d.close();

        sync();

        qDebug() << "Done writing";

    }

 

    sleep(100);

 

#endif

 

    return gcvTRUE;

 

OnError:

    fprintf(stderr,"%s(%d) failed:%s\n",__FUNCTION__, __LINE__, gcoOS_DebugStatus2Name(status));

    return gcvFALSE;

 

}

Linux Kernel Version:

uname -r

4.4.41

GC320 Galcore Driver Version:

cd /lib/modules/4.4.41/extra ; insmod galcore.ko baseAddress=0x80000

000 physSize=0x80000000

[ 8014.626644] GC320 IRQ: 304

[ 8014.629403] Galcore version 5.0.11.33433

Regards,

--Gunter

3 Replies

  • Here is the attachment with the images at input and output of GC320.

    GC320 YUYV to RGBA.zip

    Regards,

    --Gunter

  • Hello,

    Please check this link:
    git.ti.com/.../YUV

    BR
    Margarita
  • In reply to Margarita Gashova:

    Hi Margarita,

    I am the customer with the original question.

    I did finally figure this out, but I think there may be an issue with the gc320 libs. The reason it rendered into half of the frame was that the source stride returned by gcoSURF_QueryFormat was incorrect.

    I setup my source surface with this code:

    /* create a wrapper gcoSURF surface object, because we are mapping the user
                 * allocated buffer pool should be gcvPOOL_USER */
        status = gcoSURF_Construct(
                    gcvNULL,
                    m_SrcWidth,
                    m_SrcHeight,
                    1,
                    gcvSURF_BITMAP,
                    gcvSURF_UYVY,
                    gcvPOOL_USER,
                    &m_SrcSurf);
        if (status < 0) {
            fprintf(stderr,"*ERROR* Failed to create gcoSURF object\n");
            return gcvFALSE;
        }

    And then I immediately called QueryFormat:

    /* calculate the size of the buffer needed. Use gcoSURF_QueryFormat API to
                 * format parameters descriptor - this contains information on format as
                 * needed by the Vivante driver
                 */
        status = gcoSURF_QueryFormat(m_Format, info);
        if (status < 0) {
            fprintf(stderr,"*ERROR* Failed to create query format info\n");
            return gcvFALSE;
        }

    I then immediately printed bits per pixel like this:

    qDebug() << info[0]->bitsPerPixel;

    And it prints 2560 ( 640 * 4 ). 

    This is wrong because I specified the pixel format of gcvSURF_UYVU... which should be 16 bits. 

    When I convert the format later with the code - I have to force the source stride to 1280. After that the frame completely renders fine:

    // GC320 Lib might have a bug with it's pixel stride for YUYV where it says it is 32 bits
    quint32 hijackedStride = 1280;
    
    ...
    
    gcmONERROR(gco2D_FilterBlitEx2(m_Engine2d,
                    (gctUINT32_PTR)&m_SrcPhysAddr, 1,
                    (gctUINT32_PTR)&hijackedStride, 1,
                    gcvLINEAR, m_SrcFormat, gcvSURF_0_DEGREE,
                    m_SrcWidth, m_SrcHeight, (gcsRECT_PTR)&sourceRect,
                    (gctUINT32_PTR)&m_DstPhysAddr, 1, (gctUINT32_PTR)&m_DstStride, 1,
                    gcvLINEAR, m_DstFormat, gcvSURF_0_DEGREE,
                    m_DstWidth, m_DstHeight, (gcsRECT_PTR)&targetRect,
                    gcvNULL));

    Is this a bug or am I misunderstanding something? Thanks.

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.