Allocate and Populate an AVFrame in FFmpeg
This article explains how to programmatically allocate, configure,
and populate an AVFrame structure using the FFmpeg
libraries (libavutil and libavcodec). You will
learn how to initialize the frame, allocate the underlying data buffers
based on specific dimensions and pixel formats, write custom raw pixel
data to the buffers, and properly free the memory when finished.
1. Frame Allocation
To begin, allocate the core AVFrame structure. This
function sets up the structure wrapper but does not allocate any buffer
memory for the actual video or audio data.
#include <libavutil/frame.h>
#include <libavutil/imgutils.h>
AVFrame *frame = av_frame_alloc();
if (!frame) {
fprintf(stderr, "Could not allocate video frame\n");
exit(1);
}2. Configure Frame Properties
Before allocating data buffers, specify the properties of the frame. For a video frame, you must define the pixel format, width, and height.
frame->format = AV_PIX_FMT_YUV420P;
frame->width = 640;
frame->height = 480;3. Allocate Data Buffers
Once the properties are defined, call
av_frame_get_buffer() to allocate the physical buffers for
the image data. The second argument specifies the buffer alignment
(using 0 lets FFmpeg select the optimal alignment for the
CPU architecture).
int ret = av_frame_get_buffer(frame, 0);
if (ret < 0) {
fprintf(stderr, "Could not allocate the video frame data buffers\n");
av_frame_free(&frame);
exit(1);
}4. Populate the Frame with Data
Before writing data to the allocated buffers, call
av_frame_make_writable() to ensure the frame is not shared
and can be safely modified.
You can then access the pixel planes using the
frame->data pointers. The
frame->linesize array defines the byte-stride for each
horizontal line of data, which may include padding bytes for
alignment.
Below is an example of populating a planar YUV420P frame with a custom color pattern:
ret = av_frame_make_writable(frame);
if (ret < 0) {
av_frame_free(&frame);
exit(1);
}
// Populate the Y (Luminance) plane
for (int y = 0; y < frame->height; y++) {
for (int x = 0; x < frame->width; x++) {
frame->data[0][y * frame->linesize[0] + x] = x + y;
}
}
// Populate the U and V (Chrominance) planes (subsampled by 2 in YUV420P)
for (int y = 0; y < frame->height / 2; y++) {
for (int x = 0; x < frame->width / 2; x++) {
frame->data[1][y * frame->linesize[1] + x] = 128 + y;
frame->data[2][y * frame->linesize[2] + x] = 64 + x;
}
}5. Memory Cleanup
To avoid memory leaks, free the underlying data buffers and the frame
structure itself using av_frame_free() when you are
finished using the frame.
av_frame_free(&frame);