Search code examples
ffmpegyuv

FFMPEG: Dumping YUV data into AVFrame structure


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.


Solution

  • 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).