Obtaining FFmpeg
Visit the official download page at https://ffmpeg.org/download.html. For Windows users, we recommend selecting the ffmpeg-release-full-shared.7z package which contains the shared/dynamic libraries.
Environment Configuration
Add the bin and lib directories from the extracted FFmpeg package to the system's PATH enviroment variable. This ensures that applications can locate the necessary dynamic libraries at runtime.
Sample Application: H.264 Encoder
This example demonstrates how to use FFmpeg to encode a sequence of grayscale frames into H.264 format.
#include <iostream>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavutil/frame.h>
#include <libavutil/imgutils.h>
}
int main() {
const AVCodec* encoder = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!encoder) {
std::cerr << "H.264 encoder not found" << std::endl;
return -1;
}
AVCodecContext* context = avcodec_alloc_context3(encoder);
if (!context) {
std::cerr << "Failed to allocate encoder context" << std::endl;
return -1;
}
// Encoder configuration
context->width = 640;
context->height = 480;
context->time_base = (AVRational){1, 25};
context->framerate = (AVRational){25, 1};
context->pix_fmt = AV_PIX_FMT_YUV420P;
context->bit_rate = 400000;
// Encoder options
AVDictionary* options = nullptr;
av_dict_set(&options, "preset", "ultrafast", 0);
av_dict_set(&options, "tune", "zerolatency", 0);
// Open encoder
if (avcodec_open2(context, encoder, &options) < 0) {
std::cerr << "Failed to open encoder" << std::endl;
av_dict_free(&options);
avcodec_free_context(&context);
return -1;
}
av_dict_free(&options);
// Frame allocation
AVFrame* frame = av_frame_alloc();
frame->format = context->pix_fmt;
frame->width = context->width;
frame->height = context->height;
if (av_frame_get_buffer(frame, 0) < 0) {
std::cerr << "Failed to allocate frame buffer" << std::endl;
av_frame_free(&frame);
avcodec_free_context(&context);
return -1;
}
AVPacket* packet = av_packet_alloc();
const int TOTAL_FRAMES = 10;
int frames_encoded = 0;
for (int i = 0; i < TOTAL_FRAMES; i++) {
if (av_frame_make_writable(frame) < 0) {
std::cerr << "Frame not writable" << std::endl;
break;
}
frame->pts = i;
// Generate grayscale pattern
int brightness = 128 + (i * 10) % 64;
memset(frame->data[0], brightness, frame->linesize[0] * frame->height);
memset(frame->data[1], 128, frame->linesize[1] * frame->height / 2);
memset(frame->data[2], 128, frame->linesize[2] * frame->height / 2);
// Encode frame
if (avcodec_send_frame(context, frame) < 0) {
std::cerr << "Frame send error" << std::endl;
continue;
}
while (true) {
int ret = avcodec_receive_packet(context, packet);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) break;
if (ret < 0) {
std::cerr << "Packet receive error" << std::endl;
break;
}
std::cout << "Encoded frame " << i << ", size: " << packet->size << " bytes" << std::endl;
frames_encoded++;
av_packet_unref(packet);
}
}
// Flush encoder
avcodec_send_frame(context, nullptr);
while (true) {
int ret = avcodec_receive_packet(context, packet);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) break;
if (ret < 0) {
std::cerr << "Flush error" << std::endl;
break;
}
std::cout << "Flushed packet, size: " << packet->size << " bytes" << std::endl;
frames_encoded++;
av_packet_unref(packet);
}
// Cleanup
av_packet_free(&packet);
av_frame_free(&frame);
avcodec_free_context(&context);
std::cout << "Encoding completed! Total frames encoded: " << frames_encoded << std::endl;
return 0;
}
CMake Configuration
Project configuration for CMake-based builds:
cmake_minimum_required(VERSION 3.10)
project(h264_encoder LANGUAGES C CXX)
set(SOURCES main.cpp)
add_executable(h264_encoder ${SOURCES})
# FFmpeg integration
set(FFMPEG_ROOT "D:/Software/ffmpeg-7.1.1-full_build-shared")
target_include_directories(h264_encoder PRIVATE ${FFMPEG_ROOT}/include)
target_link_directories(h264_encoder PRIVATE ${FFMPEG_ROOT}/lib)
target_link_libraries(h264_encoder PRIVATE
avcodec
avutil
swscale
)