FFMPEG: Dumping YUV data into AVFrame structure

17,322

Solution 1

AVFrame can be interpreted as an AVPicture to fill the data and linesize fields. The easiest way to fill these field is to the use the avpicture_fill function.

To fill in the AVFrame's Y U and V buffers, it depends on your input data and what you want to do with the frame (do you want to write into the AVFrame and erase the initial data? or keep a copy).

If the buffer is large enough (at least linesize[0] * height for Y data, linesize[1 or 2] * height/2 for U/V data), you can directly use input buffers:

// Initialize the AVFrame
AVFrame* frame = avcodec_alloc_frame();
frame->width = width;
frame->height = height;
frame->format = AV_PIX_FMT_YUV420P;

// Initialize frame->linesize
avpicture_fill((AVPicture*)frame, NULL, frame->format, frame->width, frame->height);

// Set frame->data pointers manually
frame->data[0] = inputBufferY;
frame->data[1] = inputBufferU;
frame->data[2] = inputBufferV;

// Or if your Y, U, V buffers are contiguous and have the correct size, simply use:
// avpicture_fill((AVPicture*)frame, inputBufferYUV, frame->format, frame->width, frame->height);

If you want/need to manipulate a copy of input data, you need to compute the needed buffer size, and copy input data in it.

// Initialize the AVFrame
AVFrame* frame = avcodec_alloc_frame();
frame->width = width;
frame->height = height;
frame->format = AV_PIX_FMT_YUV420P;

// Allocate a buffer large enough for all data
int size = avpicture_get_size(frame->format, frame->width, frame->height);
uint8_t* buffer = (uint8_t*)av_malloc(size);

// Initialize frame->linesize and frame->data pointers
avpicture_fill((AVPicture*)frame, buffer, frame->format, frame->width, frame->height);

// Copy data from the 3 input buffers
memcpy(frame->data[0], inputBufferY, frame->linesize[0] * frame->height);
memcpy(frame->data[1], inputBufferU, frame->linesize[1] * frame->height / 2);
memcpy(frame->data[2], inputBufferV, frame->linesize[2] * frame->height / 2);

Once you are done with the AVFrame, do not forget to free it with av_frame_free (and any buffer allocated by av_malloc).

Solution 2

FF_API int ff_get_format_plane_size(int fmt, int plane, int scanLine, int height)
{
    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
    if (desc)
    {
            int h = height;
            if (plane == 1 || plane == 2)
            {
                h = FF_CEIL_RSHIFT(height, desc->log2_chroma_h);
            }
            return h*scanLine;
    }
    else
        return AVERROR(EINVAL);
}
Share:
17,322
Zax
Author by

Zax

Work Experience: ->Android (SDK and NDK). ->Video Codec Integration (in FFMPEG). ->ASP.Net MVC-4 (Web Application Development).

Updated on June 15, 2022

Comments

  • Zax
    Zax about 2 years

    I'm trying to dump a YUV420 data into the AVFrame structure of FFMPEG. From the below link:

    http://ffmpeg.org/doxygen/trunk/structAVFrame.html, i can derive that i need to put my data into

    data[AV_NUM_DATA_POINTERS] 
    

    using

    linesize [AV_NUM_DATA_POINTERS].
    

    The YUV data i'm trying to dump is YUV420 and the picture size is 416x240. So how do i dump/map this yuv data to AVFrame structures variable? Iknow that linesize represents the stride i.e. i suppose the width of my picture, I have tried with some combinations but do not get the output.I kindly request you to help me map the buffer. Thanks in advance.

  • Zax
    Zax over 10 years
    Just awesome explanation. Thanks
  • Ciro Santilli OurBigBook.com
    Ciro Santilli OurBigBook.com over 8 years
    More on typecasting between struct *: stackoverflow.com/questions/3766229/…
  • Kumar
    Kumar about 6 years
    Is there anyway to create black frame ? or can anyone pls provide sample inputBuffer[YUV] values for black
  • Kumar
    Kumar about 6 years
    Just now got the answer, whoever need, can make use of this. For black - UYV values are : U - 0x00, Y - 0x80, V - 0x80.
  • Dennis Guse
    Dennis Guse about 5 years
    avpicture_fill is deprecated and should be replaced by av_image_fill_arrays.
  • Paul Gregoire
    Paul Gregoire over 2 years
    I'm no guru in C++ or YUV, but I think the use of height for stride may be incorrect from everything I've read. Normally stride is the width of the frame; so in the case above only a square frame would work as expected. Feel free to correct me if I'm wrong.