C++调用FFMpeg接口

本文介绍了如何在C++项目中调用FFmpeg接口,包括从FFmpeg官网下载所需文件,处理运行时缺少dll的问题,以及解决C++编译时的链接错误。关键步骤包括将FFmpeg的头文件和lib文件添加到项目,使用extern "C"来包裹C头文件,以及在预处理器中定义_cplusplus。
1.首先下载FFMpeg
FFMpeg编译有些复杂,我就没有自己编译,在FFMpeg官网下载FFMpeg的dev和share两个版本。dev目录如下:

里面有创建项目需要的头文件和lib文件,但是没有dll,创建一个新的项目,添加include和lib依赖引用,编译可以通过,但是运行的时候会出现缺少dll的错误提示。



下载share版本,目录如下:

<think>我们遇到了一个FFmpeg滤镜图中的错误:`avfilter_graph_config`返回错误,提示"impossible to convert between the formats supported by the filter in and the filter auto_scaler_0"。这通常表示两个相连的滤镜之间无法自动完成像素格式转换,即输入滤镜的输出格式与输出滤镜的输入格式不兼容,且FFmpeg没有找到自动转换的方法。 ### 错误原因分析 1. **滤镜间格式不匹配**:相邻滤镜的输入输出格式(如像素格式、分辨率、帧率等)不一致。 2. **缺少自动转换支持**:FFmpeg无法自动插入`scale`或`format`滤镜进行转换(通常由于格式转换路径不存在或显式禁止自动插入)。 3. **滤镜图配置错误**:连接滤镜时指定了不兼容的格式约束。 ### 解决方案 #### 1. 显式添加格式转换滤镜 在格式不匹配的滤镜之间手动插入转换滤镜: ```c // 原始滤镜链(错误示例): // [in] -> filterA -> [out] // 假设filterA输出格式为YUV420P // [in] -> filterB -> [out] // 假设filterB要求输入为NV12 // 修改方案:在filterA和filterB之间插入scale和format滤镜 const char* filter_spec = "filterA, format=pix_fmts=nv12, scale=w=1280:h=720:flags=bicubic, filterB"; // 或者仅转换像素格式(若分辨率相同): // "filterA, format=nv12, filterB"; ``` #### 2. 使用`auto_conversion`功能(FFmpeg 4.0+) 启用滤镜图的自动转换模式: ```c AVFilterGraph* graph = avfilter_graph_alloc(); graph->auto_convert = AVFILTER_AUTO_CONVERT_ALL; // 允许自动插入转换滤镜 // 再执行avfilter_graph_config ``` #### 3. 检查并统一滤镜格式要求 通过代码验证相邻滤镜的格式: ```c // 获取滤镜A的输出格式 AVFilterContext* filterA_ctx = ...; AVFilterLink* outlink = filterA_ctx->outputs[0]; enum AVPixelFormat fmtA = outlink->format; // 获取滤镜B的输入格式 AVFilterContext* filterB_ctx = ...; AVFilterLink* inlink = filterB_ctx->inputs[0]; enum AVPixelFormat fmtB = inlink->in_formats->formats[0]; // 取第一个支持格式 if (fmtA != fmtB) { // 手动插入format滤镜 AVFilter* format_filter = avfilter_get_by_name("format"); avfilter_graph_create_filter(&format_ctx, format_filter, "fmt", "pix_fmts=nv12", NULL, graph); avfilter_link(filterA_ctx, 0, format_ctx, 0); avfilter_link(format_ctx, 0, filterB_ctx, 0); } ``` #### 4. 调试输出滤镜图结构 通过`avfilter_graph_dump`获取错误详情: ```c char* graph_dump = avfilter_graph_dump(graph, NULL); fprintf(stderr, "滤镜图结构:\n%s\n", graph_dump); av_free(graph_dump); ``` ### 错误处理流程图 ```mermaid graph TD A[avfilter_graph_config报错] --> B{检查错误信息} B -->|格式不匹配| C[手动插入转换滤镜] B -->|其他错误| D[查看graph_dump] C --> E[重新配置] D -->|连接错误| F[修正连接顺序] D -->|格式约束冲突| G[放宽格式限制] E --> H[再次调用avfilter_graph_config] ``` ### 常见案例:缩放滤镜与编码器格式冲突 若`auto_scaler_0`是自动插入的缩放滤镜,错误可能源于: - 缩放滤镜不支持输入格式(如输入为HDR格式但缩放器仅支持SDR) - 目标编码器要求特定格式(如NV12)但前级滤镜输出RGBA **解决方案**:在输入源后立即统一格式 ```c // 在解码器后立即转换格式 avfilter_graph_create_filter(&src_ctx, ...); avfilter_graph_create_filter(&format_ctx, "format", "fmt", "pix_fmts=yuv420p|nv12", NULL, graph); avfilter_link(src_ctx, 0, format_ctx, 0); // 再将format_ctx连接到后续滤镜 ``` §§相关问题§§ 1. 如何通过编程方式获取FFmpeg滤镜支持的所有输入输出格式? 2. 使用avfilter_link连接滤镜时如何指定格式约束? 3. FFmpeg滤镜图中自动插入转换滤镜的条件是什么? 4. 如何解决HDR视频处理中的格式转换问题? 5. 在哪些情况下需要手动设置AVFilterGraph的auto_convert属性?</think>当调用 `avfilter_graph_config` 时出现 **"impossible to convert between the formats supported by the filter in and the filter auto_scaler_0"** 错误,这表示滤镜图中的格式转换失败。以下是详细解决方案: ### 核心问题分析 该错误通常由以下原因引起: 1. **像素格式不兼容**:输入源与滤镜要求的像素格式不匹配(如 YUV420P 与 RGB24) 2. **分辨率/帧率冲突**:滤镜链中的分辨率或帧率设置不一致 3. **自动插入的缩放滤镜失败**:`auto_scaler_0` 是 FFmpeg 自动添加的格式转换滤镜,但无法完成转换 4. **色彩空间不匹配**:输入和输出滤镜的色彩特性(如 BT.709 vs BT.2020)不兼容 --- ### 解决方案与调试步骤 #### 1. 显式指定格式转换(推荐) 在滤镜描述中手动添加格式转换滤镜: ```c // 原始错误滤镜链 const char* filter_spec = "scale=1280:720,drawtext=text='Watermark'"; // 修正方案:添加format滤镜统一像素格式 const char* fixed_spec = "format=pix_fmts=yuv420p,scale=1280:720:flags=bicubic,drawtext=text='Watermark'"; ``` #### 2. 验证输入源格式 ```c // 获取输入流的格式信息 AVStream* in_stream = fmt_ctx->streams[video_stream_idx]; AVCodecParameters* codecpar = in_stream->codecpar; printf("输入格式: %s %dx%d %.2ffps\n", av_get_pix_fmt_name(codecpar->format), codecpar->width, codecpar->height, av_q2d(in_stream->avg_frame_rate)); ``` #### 3. 统一滤镜链格式要求 ```c // 创建格式约束 AVFilterLink* outlink = buffersrc_ctx->outputs[0]; enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }; // 设置输出格式约束 av_opt_set_int_list(outlink, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN); ``` #### 4. 调试自动插入的滤镜 ```c // 获取并分析自动插入的scaler滤镜 AVFilterContext* auto_scaler = avfilter_graph_get_filter(filter_graph, "auto_scaler_0"); if (auto_scaler) { // 打印scaler支持的格式 av_opt_show2(auto_scaler, NULL, AV_OPT_FLAG_FILTERING_PARAM, 0); // 检查输入/输出链接 printf("输入格式: %s\n", av_get_pix_fmt_name(auto_scaler->inputs[0]->format)); printf("输出格式: %s\n", av_get_pix_fmt_name(auto_scaler->outputs[0]->format)); } ``` #### 5. 完整解决方案示例 ```c // 创建buffersrc时指定格式约束 AVBufferSrcParameters* params = av_buffersrc_parameters_alloc(); params->format = AV_PIX_FMT_YUV420P; // 强制统一格式 params->width = 1920; params->height = 1080; params->time_base = (AVRational){1, 25}; av_buffersrc_parameters_set(buffersrc_ctx, params); av_free(params); // 构建带格式转换的滤镜链 const char* filter_spec = "format=pix_fmts=yuv420p," // 确保像素格式一致 "scale=1280:720:force_original_aspect_ratio=decrease," // 智能缩放 "drawtext=fontfile=/fonts/Arial.ttf:text='Watermark':x=10:y=10"; avfilter_graph_parse_ptr(filter_graph, filter_spec, &inputs, &outputs, NULL); ``` ### 格式转换流程图 ```mermaid graph LR A[输入源] -->|原始格式| B[format滤镜] B -->|统一格式| C[scale滤镜] C -->|目标分辨率| D[水印滤镜] D -->|输出格式| E[编码器] classDef error fill:#f9f,stroke:#333; class auto_scaler_0 error; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值