avfilter_graph_parse_ptr 返回值 -22. 报  no such  filter: ‘‘ 

博客讲述了在使用ffmpeg时遇到avfilter_graph_parse_ptr返回-22错误,具体表现为"no such filter: ' '"。问题根源在于vfilters_list索引位置的内容不正确。通过检查源码发现过滤器名称为空。解决方案是在ffplay_init时清空vfilters_list并重置nb_vfilters为0,从而成功解决问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 if ((ret = avfilter_graph_parse_ptr(graph, filtergraph, &inputs, &outputs, NULL)) < 0)
     goto fail;
avfilter_graph_parse_ptr 返回值 -22问题. 报  no such  filter: '  '           
每次调用 ffplay_init时  is->vfilter_idx 是0 ,  vfilters_list 索引位置的内容不对.  avfilter_graph_parse_ptr 返回值 -22,no such  filter: '   ' 。 查找这个 vfilters_list在 GROW_ARRAY中,做数组扩容. nb_vfilters也在增长, 可能ffmpeg 考虑的是多个vf 过滤器形成list。 查看源码发现no such  filter: ''  对应的位置就是filtername为空。 顺着这条线,找到了 vfilters_list 索引位置的内容不对。
            
而我实际应用就是每次ffplay_init 带的arg参数里面就一个vf. 放在vf[0]就好. 
最后我在ffplay_init最初时avfree (vfilters_list),nb_vfilters = 0;
解决了avfilter_graph_parse_ptr 返回值 -22问题. 报  no such  filter: '' 
部分代码
static const char **vfilters_list = NULL;
static int nb_vfilters = 0;  


static int opt_add_vfilter(void *optctx, const char *opt, const char *a

### 回答1: 为视频加水印可以使用FFmpeg中的`overlay`过滤器。以下是使用纯C代码实现的示例: ``` AVFilterContext *buffersrc_ctx; AVFilterContext *buffersink_ctx; AVFilterGraph *filter_graph; AVFilter *buffersrc = avfilter_get_by_name("buffer"); AVFilter *buffersink = avfilter_get_by_name("buffersink"); AVFilterInOut *outputs = avfilter_inout_alloc(); AVFilterInOut *inputs = avfilter_inout_alloc(); const char *filter_descr = "overlay=10:10"; int ret; filter_graph = avfilter_graph_alloc(); if (!outputs || !inputs || !filter_graph) { ret = AVERROR(ENOMEM); goto end; } // 添加 buffer 过滤器到过滤器图中 ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", "video_size=1920x1080:pix_fmt=0:time_base=1/25", NULL, filter_graph); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n"); goto end; } // 添加 buffersink 过滤器到过滤器图中 ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out", NULL, NULL, filter_graph); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n"); goto end; } // 设置 filter_graph 的输入输出链 outputs->name = av_strdup("in"); outputs->filter_ctx = buffersrc_ctx; outputs->pad_idx = 0; outputs->next = NULL; inputs->name = av_strdup("out"); inputs->filter_ctx = buffersink_ctx; inputs->pad_idx = 0; inputs->next = NULL; // 添加 filterfilter_graph 中 ret = avfilter_graph_parse_ptr(filter_graph, filter_descr, &inputs, &outputs, NULL); if (ret < 0) { goto end; } // 链接 filter ret = avfilter_graph_config(filter_graph, NULL); if (ret < 0) { goto end; } end: avfilter_inout_free(&inputs); avfilter_inout_free(&outputs); avfilter_graph_free(&filter_graph); ``` 以上代码将在视频的左上角添加一个10像素的水印。可以通过修改`filter_descr`来调整水印的位置和大小。 ### 回答2: 在使用 Ffmpeg 为视频加水印时,可以通过 Filter 部分的代码来实现。 首先,需要引入 Ffmpeg 头文件和相关的库文件: ```c extern "C" { #include <libavfilter/avfilter.h> #include <libavfilter/buffersink.h> #include <libavfilter/buffersrc.h> } #pragma comment(lib, "libavfilter.lib") #pragma comment(lib, "libavdevice.lib") #pragma comment(lib, "libavformat.lib") #pragma comment(lib, "libavcodec.lib") #pragma comment(lib, "libswscale.lib") ``` 然后,可以定义一个函数来实现添加水印的功能,如下所示: ```c void addWatermark(const char* inputFileName, const char* watermarkFileName, const char* outputFileName) { AVFilterContext* buffersink_ctx; AVFilterContext* buffersrc_ctx; AVFilterGraph* filter_graph; AVFormatContext* format_ctx; AVPacket packet; int ret; // 打开输入文件 ret = avformat_open_input(&format_ctx, inputFileName, 0, 0); if (ret < 0) { // 处理打开输入文件失败的情况 return; } // 查找流信息 ret = avformat_find_stream_info(format_ctx, 0); if (ret < 0) { // 处理查找流信息失败的情况 avformat_close_input(&format_ctx); return; } // 创建图像过滤器核心 filter_graph = avfilter_graph_alloc(); if (!filter_graph) { // 处理创建图像过滤器核心失败的情况 avformat_close_input(&format_ctx); return; } // 打开输入过滤器源(Source) const AVFilter* buffersrc = avfilter_get_by_name("buffer"); buffersrc_ctx = avfilter_graph_alloc_filter(filter_graph, buffersrc, "src"); if (!buffersrc_ctx) { // 处理打开输入过滤器源失败的情况 avfilter_graph_free(&filter_graph); avformat_close_input(&format_ctx); return; } // 设置输入过滤器源的参数 av_opt_set_int_list(buffersrc_ctx, "pix_fmts", fmts, -1, AV_OPT_SEARCH_CHILDREN); av_opt_set_int(buffersrc_ctx, "width", format_ctx->streams[0]->codecpar->width, AV_OPT_SEARCH_CHILDREN); av_opt_set_int(buffersrc_ctx, "height", format_ctx->streams[0]->codecpar->height, AV_OPT_SEARCH_CHILDREN); // 打开输出过滤器接收器(Sink) const AVFilter* buffersink = avfilter_get_by_name("buffersink"); buffersink_ctx = avfilter_graph_alloc_filter(filter_graph, buffersink, "sink"); if (!buffersink_ctx) { // 处理打开输出过滤器接收器失败的情况 avfilter_graph_free(&filter_graph); avformat_close_input(&format_ctx); return; } // 初始化图像过滤器核心 ret = avfilter_graph_parse_ptr(filter_graph, filter_desc, &buffersrc_ctx, &buffersink_ctx, NULL); if (ret < 0) { // 处理初始化图像过滤器核心失败的情况 avfilter_graph_free(&filter_graph); avformat_close_input(&format_ctx); return; } // 链接图像过滤器核心 ret = avfilter_graph_config(filter_graph, NULL); if (ret < 0) { // 处理链接图像过滤器核心失败的情况 avfilter_graph_free(&filter_graph); avformat_close_input(&format_ctx); return; } // 读取水印文件 AVFormatContext* watermark_format_ctx; ret = avformat_open_input(&watermark_format_ctx, watermarkFileName, 0, 0); if (ret < 0) { // 处理读取水印文件失败的情况 avfilter_graph_free(&filter_graph); avformat_close_input(&format_ctx); return; } // 从水印文件中读取数据包 while (av_read_frame(watermark_format_ctx, &packet) >= 0) { // 对水印的数据包进行过滤 if (packet.stream_index == 0) { av_buffersrc_add_frame_flags(buffersrc_ctx, packet.data, AV_BUFFERSRC_FLAG_PUSH); } av_packet_unref(&packet); } // 处理输出过滤器接收器(Sink)的输出帧 while (1) { AVFrame* frame = av_frame_alloc(); ret = av_buffersink_get_frame(buffersink_ctx, frame); if (ret < 0) { // 处理处理输出过滤器接收器的输出帧失败的情况 av_frame_unref(frame); break; } // 对输出帧进行处理,例如进行水印贴图 // ... av_frame_unref(frame); } // 释放资源 avfilter_graph_free(&filter_graph); avformat_close_input(&format_ctx); avformat_close_input(&watermark_format_ctx); } ``` 以上是一个参考的基本代码示例,其中需要替换部分代码来符合实际需求。此外,添加水印的具体处理方法,例如进行水印贴图,需要根据实际情况实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值