Convert Pixel Formats with libswscale in FFmpeg
This article provides a step-by-step technical guide on how to
convert the pixel format and rescale a decoded video frame using the
libswscale library in FFmpeg. You will learn how to
initialize the scaling context, allocate target buffers, perform the
conversion efficiently in C/C++, and properly free the allocated
resources.
To convert the pixel format of a decoded AVFrame (for
example, from AV_PIX_FMT_YUV420P to
AV_PIX_FMT_RGB24), you must use FFmpeg’s
libswscale library. The process involves four main steps:
creating a scaling context, preparing the destination frame, performing
the conversion, and freeing the resources.
1. Initialize the Scaling Context
First, allocate and configure a SwsContext using
sws_getContext. This context stores the configuration for
the source and destination dimensions, pixel formats, and the
interpolation algorithm.
#include <libswscale/swscale.h>
struct SwsContext* sws_ctx = sws_getContext(
src_width, // Source frame width
src_height, // Source frame height
src_pix_fmt, // Source pixel format (e.g., AV_PIX_FMT_YUV420P)
dst_width, // Target frame width
dst_height, // Target frame height
dst_pix_fmt, // Target pixel format (e.g., AV_PIX_FMT_RGB24)
SWS_BILINEAR, // Rescaling algorithm (e.g., SWS_BICUBIC, SWS_BILINEAR)
NULL, NULL, NULL // Optional filters and parameters
);
if (!sws_ctx) {
// Handle error: context creation failed
}2. Allocate the Destination Frame
Create a destination AVFrame to hold the converted pixel
data and allocate its internal buffers.
#include <libavutil/frame.h>
AVFrame* dst_frame = av_frame_alloc();
if (!dst_frame) {
// Handle allocation error
}
dst_frame->format = dst_pix_fmt;
dst_frame->width = dst_width;
dst_frame->height = dst_height;
// Allocate buffer memory for the target frame format
int ret = av_frame_get_buffer(dst_frame, 0);
if (ret < 0) {
// Handle buffer allocation error
}3. Perform the Conversion
Use the sws_scale function to perform the actual pixel
format conversion. You must pass the pointers to the data planes and the
linesizes for both the source and destination frames.
int output_height = sws_scale(
sws_ctx,
(const uint8_t *const *)src_frame->data, // Source data pointers
src_frame->linesize, // Source line sizes
0, // Start slice Y coordinate
src_frame->height, // Source slice height
dst_frame->data, // Destination data pointers
dst_frame->linesize // Destination line sizes
);
if (output_height < 0) {
// Handle scaling error
}4. Clean Up Resources
Once you are done with the conversion process, free the
SwsContext and the destination frame to prevent memory
leaks.
sws_freeContext(sws_ctx);
av_frame_free(&dst_frame);