/*全局变量*/
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(<ime);
struct tm* today = localtime(<ime);
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);
}