windows环境下载ffmpeg库 与 示例

官网:https://ffmpeg.org/download.html

image

image

我们这里选择 ffmpeg-release-full-shared.7z`动态库下载

image

添加系统变量

将lib bin添加到系统环境变量path,供程序执行时查询动态库

动态库本体一般输出到bin,静态库和动态库的符号链接在lib

image

测试程序

#include <iostream>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavutil/frame.h>
#include <libavutil/imgutils.h>
}

int main() {


    // FFmpeg 7.1 及以上版本已经移除了 avcodec_register_all() 等注册函数,因为编解码器会在首次使用时自动注册,无需手动调用。
    // avcodec_register_all();

    // 查找H.264编码器
    const AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_H264);
    if (!codec) {
        std::cerr << "H.264 encoder not found" << std::endl;
        return -1;
    }

    // 创建编码器上下文
    AVCodecContext* enc_ctx = avcodec_alloc_context3(codec);
    if (!enc_ctx) {
        std::cerr << "Failed to allocate encoder context" << std::endl;
        return -1;
    }

    // 设置编码器参数
    enc_ctx->width = 640;
    enc_ctx->height = 480;
    enc_ctx->time_base = {1, 25}; // 25 fps
    enc_ctx->framerate = {25, 1};
    enc_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
    enc_ctx->bit_rate = 400000; // 400 kbps

    // 使用AVDictionary设置编码器选项(正确初始化和使用)
    AVDictionary* opts = nullptr;
    av_dict_set(&opts, "preset", "ultrafast", 0); // 快速编码预设
    av_dict_set(&opts, "tune", "zerolatency", 0); // 零延迟模式

    // 打开编码器
    if (avcodec_open2(enc_ctx, codec, &opts) < 0) {
        std::cerr << "Failed to open encoder" << std::endl;
        av_dict_free(&opts);
        avcodec_free_context(&enc_ctx);
        return -1;
    }

    // 释放已使用的字典
    av_dict_free(&opts);

    // 创建AVFrame并分配内存
    AVFrame* frame = av_frame_alloc();
    if (!frame) {
        std::cerr << "Failed to allocate frame" << std::endl;
        avcodec_free_context(&enc_ctx);
        return -1;
    }

    frame->format = enc_ctx->pix_fmt;
    frame->width = enc_ctx->width;
    frame->height = enc_ctx->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(&enc_ctx);
        return -1;
    }

    // 创建AVPacket
    AVPacket* pkt = av_packet_alloc();
    if (!pkt) {
        std::cerr << "Failed to allocate packet" << std::endl;
        av_frame_free(&frame);
        avcodec_free_context(&enc_ctx);
        return -1;
    }

    // 编码10帧不同亮度的灰色图像
    const int FRAME_COUNT = 10;
    int encoded_frames = 0;

    for (int i = 0; i < FRAME_COUNT; i++) {
        // 确保帧可写
        if (av_frame_make_writable(frame) < 0) {
            std::cerr << "Failed to make frame writable" << std::endl;
            break;
        }

        // 设置时间戳
        frame->pts = i;

        // 填充YUV数据(每帧亮度递增)
        int y_value = 128 + (i * 10) % 64; // 亮度值在128-192之间变化
        memset(frame->data[0], y_value, frame->linesize[0] * frame->height); // Y平面
        memset(frame->data[1], 128, frame->linesize[1] * frame->height / 2); // U平面
        memset(frame->data[2], 128, frame->linesize[2] * frame->height / 2); // V平面

        // 发送帧到编码器
        if (avcodec_send_frame(enc_ctx, frame) < 0) {
            std::cerr << "Error sending frame " << i << " to encoder" << std::endl;
            continue;
        }

        // 接收编码后的数据包(可能需要多次调用,直到AVERROR(EAGAIN)或错误)
        while (true) {
            int ret = avcodec_receive_packet(enc_ctx, pkt);
            if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                break; // 需要更多帧或编码完成
            } else if (ret < 0) {
                std::cerr << "Error receiving packet for frame " << i << std::endl;
                break;
            }

            // 成功接收数据包
            std::cout << "Encoded frame " << i << ", size: " << pkt->size << " bytes" << std::endl;
            encoded_frames++;

            // 处理完数据包后释放
            av_packet_unref(pkt);
        }
    }

    // 刷新编码器(处理延迟的数据包)
    avcodec_send_frame(enc_ctx, nullptr); // 发送空帧表示结束
    while (true) {
        int ret = avcodec_receive_packet(enc_ctx, pkt);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
            break;
        } else if (ret < 0) {
            std::cerr << "Error during encoder flush" << std::endl;
            break;
        }

        std::cout << "Flushed delayed packet, size: " << pkt->size << " bytes" << std::endl;
        encoded_frames++;
        av_packet_unref(pkt);
    }

    // 释放资源
    av_packet_free(&pkt);
    av_frame_free(&frame);
    avcodec_free_context(&enc_ctx);

    std::cout << "Encoding completed! Total frames encoded: " << encoded_frames << std::endl;
    return 0;
}
cmake_minimum_required(VERSION 3.10.0)
project(ffmpeg_firstdemo VERSION 0.1.0 LANGUAGES C CXX)

aux_source_directory(. SRC_LIST)
add_executable(ffmpeg_firstdemo ${SRC_LIST})

# link ffmpeg
set(FFMPEG_DIR  "D:/Software/ffmpeg-7.1.1-full_build-shared")
# 包含头文件目录
target_include_directories(ffmpeg_firstdemo PRIVATE 
    ${FFMPEG_DIR}/include
)
# 链接库文件
target_link_directories(ffmpeg_firstdemo PRIVATE ${FFMPEG_DIR}/lib)
target_link_libraries(ffmpeg_firstdemo PRIVATE 
    avcodec 
    avformat 
    avutil 
    swscale
)
posted @ 2025-07-22 14:14  丘狸尾  阅读(697)  评论(0)    收藏  举报