在ffmpeg中添加一个src滤镜

本文介绍了src滤镜和处理滤镜的区别,src滤镜无输入,通过接口获取AVFrame并输出。详细展示了自定义src滤镜的实现,包括滤镜结构体定义、初始化过程,如注册滤镜、分配内存等,还给出了请求帧函数的实现。

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

上一篇博客介绍了如何添加一个自定义的处理滤镜。

src滤镜和处理滤镜的区别就是src滤镜没有输入,通过接口直接获取AVFrame 然后输出ff_filter_frame

具体看一个实现

AVFilter ff_avsrc_lottie = {
    .name          = "lottie",// 滤镜名
    .description   = NULL_IF_CONFIG_SMALL("Read from a lottie source."),
    .priv_size     = sizeof(LottieContext),// 滤镜上下文,保存参数
    .priv_class    = &lottie_class,
    .init          = lottie_common_init, //初始化
    .uninit        = lottie_uninit,
    .query_formats = lottie_query_formats,//支持的格式

    .inputs    = NULL,
    .outputs   = NULL,
    .flags     = AVFILTER_FLAG_DYNAMIC_OUTPUTS,
    .process_command = process_command //命令处理
};

初始化的时候,先注册这个新的src滤镜

 LottieContext *lottie = ctx->priv;
    if (!lottie->file_name) {
        av_log(ctx, AV_LOG_ERROR, "No filename provided!\n");
        return AVERROR(EINVAL);
    }

    av_register_all();
    lottie->lt = alloc_lottie_handle(lottie->file_name);
    if(lottie->lt == NULL)
    {
        av_log(ctx, AV_LOG_ERROR,
               "alloc_lottie_handle failed.\n");
        return AVERROR_PATCHWELCOME;
    }
    
    // Try to find the lottie format (container)
    lottie->frame_buf = (uint8_t*)av_malloc(MAX_FRAME_SIZE);
    if(lottie->frame_buf == NULL)
    {
        av_log(ctx, AV_LOG_ERROR, "av_malloc failed!\n");
        return AVERROR(EINVAL);
    }
    lottie->fill_buf = (uint8_t*)av_malloc(MAX_FRAME_SIZE);
    if(lottie->fill_buf == NULL)
    {
        av_log(ctx, AV_LOG_ERROR, "av_malloc failed!\n");
        return AVERROR(EINVAL);
    }
    
    lottie->total_frames = lottie_get_totalframes(lottie->lt);
    AVFilterPad pad = { 0 };
    pad.type          = AVMEDIA_TYPE_VIDEO;
    pad.name          = av_strdup("out0");
    if (!pad.name)
          return AVERROR(ENOMEM);
    pad.config_props  = lottie_config_output_props;
    pad.request_frame = lottie_request_frame;
    ff_insert_outpad(ctx, 0, &pad);// 插入滤镜相关信息,包括入口函数lottie_request_frame

static int lottie_request_frame(AVFilterLink *outlink)

{     AVFrame *frm = av_frame_alloc();

      ff_filter_frame(outlink,frm);

}

具体实现还有不懂得可以加qq交流

 


 

### 开发 FFmpeg 滤镜 开发自定义 FFmpeg 滤镜涉及多个方面,包括理解 FFmpeg 的架构、编写 C 代码以及编译集成到 FFmpeg 中。以下是创建简单滤镜的过程。 #### 创建简单的灰度转换滤镜 为了实现一个将彩色图像转为灰度图的滤镜,可以按照如下方式操作: 1. **初始化项目结构** 建立一个新的目录用于存放源码文件,并下载 FFmpeg 源码作为参考和依赖库。 2. **编写滤镜核心逻辑** 下面是一个简化版本的灰度化滤镜 `vf_grayscale.c` 文件的内容示例[^1]: ```c #include "libavutil/imgutils.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavfilter/buffersink.h" #include "libavfilter/buffer.h" typedef struct GrayscaleContext { const AVClass *class; } GrayscaleContext; #define OFFSET(x) offsetof(GrayscaleContext, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM static const AVOption grayscale_options[] = { { NULL } }; AVFILTER_DEFINE_CLASS(grayscale); // 初始化函数 static int init(AVFilterContext *ctx){ // 可以在这里设置一些默认参数或分配资源 return 0; } // 执行过滤器的核心算法 static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref){ AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; /* 获取输出缓冲区 */ AVFrame *outpicref = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!outpicref) return AVERROR(ENOMEM); uint8_t *src = inpicref->data[0]; // 输入数据指针 uint8_t *dst = outpicref->data[0]; // 输出数据指针 int linesize_in = inpicref->linesize[0]; int linesize_out = outpicref->linesize[0]; for (int y=0; y<inpicref->height; ++y){ for(int x=0; x<inpicref->width*3; x+=3){ // 假设RGB24格式 unsigned char r = src[y*linesize_in+x]; unsigned char g = src[y*linesize_in+x+1]; unsigned char b = src[y*linesize_in+x+2]; // 计算亮度值 Y = 0.299R + 0.587G + 0.114B float gray_value = 0.299*r + 0.587*g + 0.114*b; dst[y*linesize_out+(x/3)] = (unsigned char)(gray_value); } } av_frame_free(&inpicref); return ff_filter_frame(outlink, outpicref); } // 定义静态常量描述符 static const AVFilterPad inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .filter_frame = filter_frame, }, {NULL} }; static const AVFilterPad outputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, }, {NULL} }; // 注册此滤镜FFmpeg框架内 AVFilter ff_vf_grayscale = { .name = "grayscale", .description = NULL_IF_CONFIG_SMALL("Convert video to grayscale."), .init = init, .uninit = uninit, .query_formats = query_formats, .priv_size = sizeof(GrayscaleContext), .inputs = inputs, .outputs = outputs, .priv_class=&grayscale_class, }; ``` 这段代码实现了基本的功能——接收输入帧,在内存中将其颜色空间由 RGB 转换为单通道灰度表示形式后再传递给下一个环节。注意这里假设输入像素是以 RGB24 格式存储;实际应用时可能需要考虑更多种情况下的兼容性处理[^3]。 3. **配置与构建** 完成上述工作之后,还需要修改 FFmpeg 构建系统的 Makefile 和其他必要的配置文件来包含新添加的模块。具体来说就是编辑 `filters/filters.c`, 添加一行注册语句以便让整个程序知道有这样一个新的外部插件存在。 最后运行标准流程重新编译整个工程即可使新增加的效果生效。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值