ffmpeg添加水印

ffmpeg需要重新编译才能支持添加水印

/*全局变量*/
AVFilterGraph *filter_graph = nullptr; //最关键的过滤器结构体
AVFilterContext* filter_ctx = nullptr;//上下文
AVFilterInOut *outputs  = nullptr;
AVFilterInOut *inputs = nullptr;
AVFilterContext *buffersink_ctx = nullptr;
AVFilterContext *buffersrc_ctx = nullptr;
/*初始化滤镜*/
int initAVFilter()
{
    /*********************************************初始化结构体****************************************/
    int ret = 0;
    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_YUV420P };  //摄像头的像素格式
    snprintf(m_args, sizeof(m_args),"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
             720, 576, AV_PIX_FMT_YUV420P,1, 25, 1, 1);   //
    ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", m_args, nullptr, filter_graph);  //初始化并创建输入过滤器参数,通过参数指向具体的过滤器
    if (ret < 0)
    {
        return -1;
    }
    AVBufferSinkParams* buffersink_params = av_buffersink_params_alloc();
    buffersink_params->pixel_fmts = pix_fmts;   //设置输出的像素格式
    ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",nullptr, 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中
    memset(m_filter_descr,0,sizeof(m_filter_descr));//FreeSans verdanaz
    sprintf(m_filter_descr,"[in]drawtext=fontfile=FreeSans.ttf:x=4:y=0:fontsize=15:text='',scale=720:576[a];"
                         "[a]drawtext=fontfile=FreeSans.ttf:x=4:y=15:fontsize=15:text='pix=;GOP=',scale=720:576[b];"
                         "[b]drawtext=fontfile=FreeSans.ttf:x=4:y=30:fontsize=15:text='PID=;FPS=;',scale=720:576[c];"
                        "[c]drawtext=fontfile=FreeSans.ttf:x=4:y=45:fontsize=15:text='transformat=;muxer=',scale=720:576[d];"
                        "[d]drawtext=fontfile=FreeSans.ttf:x=4:y=60:fontsize=15:text='encode=;ratebit=',scale=720:576[out]");

    char*temp = new  char[56];
    memset(temp,0,sizeof(temp));
    sprintf(temp,"%d%s%d%s%d",m_videoInfo.width,"*",m_videoInfo.height,";  GOP=",m_videoInfo.gopSize);
    std::string aa = subreplace(m_filter_descr,"pix=;GOP=",temp);

    memset(temp,0,sizeof(temp));
    sprintf(temp,"%s%d%s%d"," PID=",m_videoInfo.PID,";     FPS=",m_videoInfo.FPS);
    aa = subreplace(aa.c_str(),"PID=;FPS=;",temp);

    memset(temp,0,sizeof(temp));
    sprintf(temp,"%s%s%s%s"," transformat=",m_videoInfo.transformProtocol.c_str(),"; muxer=",m_videoInfo.muxeFormat.c_str());
    aa = subreplace(aa.c_str(),"transformat=;muxer=",temp);

    memset(temp,0,sizeof(temp));
    sprintf(temp,"%s%s%s%d"," encode=",m_videoInfo.encodeProtocol.c_str(),"; ratebit=",m_videoInfo.ratebit);
    aa = subreplace(aa.c_str(),"encode=;ratebit=",temp);
    if ((ret = avfilter_graph_parse_ptr(filter_graph, aa.c_str(),&inputs, &outputs, nullptr)) < 0)
        return ret;
    if ((ret = avfilter_graph_config(filter_graph, nullptr)) < 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];
    delete [] temp;
    temp = nullptr;
    return  0;
}
//frame_in:需要加水印的输入帧
//frame_out:完成加水印后取到的帧,执行完函数并完成相关逻辑后需要av_frame_unref(frame_out);
int waterMark(AVFrame *frame_in,AVFrame *frame_out)
{
    int ret = 0;
    char sys_time[64];
    memset(sys_time,0,sizeof (sys_time));
    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;
    }
    return 0;
}

使用:

 int nRet = 0;
 int got_picture = 0;
 AVFrame frame_watermark = av_frame_alloc();
 AVFrame frame= av_frame_alloc();
 nRet = avcodec_send_packet(m_pDecodeCtx,pkt);
 if( 0 == nRet)
 {
     got_picture =avcodec_receive_frame(m_pDecodeCtx, frame);
     if(got_picture == 0)
     {
         waterMark(frame,frame_watermark);//添加水印
     }
     av_packet_unref(pkt);
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值