1
votes

I'm trying to convert my YUV420p image to RGB24 in c++ and create bitmap from byte array in c#.

My image size is 1920 w * 1020 h and ffmpeg decoder give me 3 planars for data with linesizes = {1920, 960, 960}. But after sws_scale I'm getting RGB picture with only one plane with linesize = 5760. It does not looks correct: I should get (5760 * h), not just only one row of data. What I'm doing wrong?

 //c++ part
    if (avcodec_receive_frame(m_decoderContext, pFrame) == 0)
    {
        //RGB
        sws_ctx = sws_getContext(m_decoderContext->width,
            m_decoderContext->height,
            m_decoderContext->pix_fmt,
            m_decoderContext->width,
            m_decoderContext->height,
            AV_PIX_FMT_RGB24,
            SWS_BILINEAR,
            NULL,
            NULL,
            NULL
        );

        sws_scale(sws_ctx, (uint8_t const * const *)pFrame->data, pFrame->linesize,
            0, pFrame->height,
            pFrameRGB->data, pFrameRGB->linesize);


//c# part (im reading data from pipe and its equal to c++ part)------------------------------------------------------------------
        byte[] rgbch = new byte[frameLen];
        for (int i=0; i<frameLen; i++)
        {
            rgbch[i] = Convert.ToByte(pipe.ReadByte());
        }

        if (rgbch.Length > 0)
        {
            var arrayHandle = System.Runtime.InteropServices.GCHandle.Alloc(rgbch,
    System.Runtime.InteropServices.GCHandleType.Pinned);

            var bmp = new Bitmap(1920, 1080,
                3,
                System.Drawing.Imaging.PixelFormat.Format24bppRgb,
                arrayHandle.AddrOfPinnedObject()
            );

            pictureBox1.Image = bmp;
        }
1
Why do you think it is not correct? You give in planar pixel data, get out interleaved pixel data where each row has a size of 3 * 1920, and the memory region in total is 3 * 1920 * height.Rudolfs Bundulis
Well, I do not understand where is that 3*1920*height memory region. I got only one row of 3 * 1920 in pFrameRGB->data... For full image I need all other rows?..Aleksey
What is the return value of sws_scale ? It should be the number of rows in the output buffer - pFrameRGB->data. If its not 1 then your assumption is wrong. If it really is 1 then something is going wrong.Rudolfs Bundulis
I've missed return value of sws_scale.. With it I got right amount of "columns" in my buffer... so, basically, as I understand now linesize is not a size of data - it just show one row size in data?Aleksey
Yes, the name of the variable kind of tells it:)Rudolfs Bundulis

1 Answers

1
votes

Your assumption that the linesize field of AVFrame is the total amount of data is not correct. As the name of the variable states it is the length of a single row, while the return value of sws_scale gives you the number of rows. Thus the total memory range size for the output bitmap is linesize multiplied by the return value.