ffmpeg 代码实现图像加时间动态水印(三)

实现对取到的摄像头帧加时间水印数据,随系统时间变化。ffmpeg编译时必须加上./configure --enable-libfreetype,否则会提示找不到filter.

//frame_in:需要加水印的输入帧
//frame_out:完成加水印后取到的帧,执行完函数并完成相关逻辑后需要av_frame_unref(frame_out);
int waterMark(AVFrame *frame_in,AVFrame *frame_out){
    AVFilterContext *buffersink_ctx = NULL;
    AVFilterContext *buffersrc_ctx = NULL;
    AVFilterGraph *filter_graph = NULL; //最关键的过滤器结构体
    AVFilterContext* filter_ctx;//上下文
    AVFilterInOut *outputs ;
    AVFilterInOut *inputs;
    AVBufferSinkParams *buffersink_params;

    /*********************************************初始化结构体****************************************/
    int ret;
    const AVFilter *buffersrc = avfilter_get_by_name("buffer");                 //输入,原始数据输入处
    const AVFilter *buffersink = avfilter_get_by_name("buffersink");        //输出,处理后的数据输出
    outputs = avfilter_inout_alloc();
    inputs = avfilter_inout_alloc();
    filter_graph = avfilter_graph_alloc();
    enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_NONE };  //摄像头的像素格式

    char args[256];
    snprintf(args, sizeof(args),"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
             1280, 720, AV_PIX_FMT_YUVJ420P,1, 30, 1, 1);   //输入过滤器参数配置:1280*720 j420p 帧率30
    ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", args, NULL, filter_graph);  //初始化并创建输入过滤器参数,通过参数指向具体的过滤器
    if (ret < 0)
    {
        return -1;
    }

    buffersink_params = av_buffersink_params_alloc();
    buffersink_params->pixel_fmts = pix_fmts;   //设置输出的像素格式
    ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",NULL, buffersink_params, filter_graph); //创建输出过滤器
    av_free(buffersink_params);
    if (ret < 0)
    {
        return -2;
    }

    //参考和总结其他人的参数配置,实现水印格式添加
    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;

    //将一串通过字符串描述的Graph添加到FilterGraph中
    char filter_descr[128];
    memset(filter_descr,0,sizeof(filter_descr));
    sprintf(filter_descr,"drawtext=fontfile =verdanaz.ttf:x =w-tw:fontcolor=white:fontsize=20:text="":x=5:y=5");
    if ((ret = avfilter_graph_parse_ptr(filter_graph, filter_descr,&inputs, &outputs, NULL)) < 0)
        return ret;
    if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0)
        return ret;

    int parsed_drawtext_0_index = -1;
    for (int i = 0; i < filter_graph->nb_filters; i++)
    {
        AVFilterContext* filter_ctxn = filter_graph->filters[i];
        fprintf(stdout, "[%s](%d) filter_ctxn->name=%s\n",__func__,__LINE__,filter_ctxn->name);
        if(!strcmp(filter_ctxn->name,"Parsed_drawtext_0"))
            parsed_drawtext_0_index = i;
    }
    if(parsed_drawtext_0_index == -1)
        fprintf(stderr, "[%s](%d) no Parsed_drawtext_0\n",__func__,__LINE__);
    filter_ctx = filter_graph->filters[parsed_drawtext_0_index];
    /*****************************************************初始化完成*********************************************/

     /**************************************************给图像添加水印*********************************************/
    char sys_time[64];
    time_t ltime;
    time(&ltime);
    struct tm* today = localtime(&ltime);
    strftime(sys_time, sizeof(sys_time), "%Y-%m-%d %a %H:%M:%S", today);       //24小时制
    av_opt_set(filter_ctx->priv, "text", sys_time, 0 );  //设置text到过滤器

    // 往源滤波器buffer中输入待处理的数据
    if (av_buffersrc_add_frame(buffersrc_ctx, frame_in) < 0)
    {
        return  -3;
    }
    // 从目的滤波器buffersink中输出处理完的数据
    ret = av_buffersink_get_frame(buffersink_ctx, frame_out);
    if (ret < 0)
        return  ret;
    avfilter_inout_free(&outputs);
    avfilter_inout_free(&inputs);
    avfilter_graph_free(&filter_graph);
    return 0;
}

效果如图:
摄像头加水印
接下来会对处理后的水印图片做格式转换,AV_PIX_FMT_YUVJ420P转AV_PIX_FMT_NV12。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值