オーディオおよびビデオ処理FFmpegの戦闘開発(6) - (動画に追加したテキスト)に使用されるフィルタ

FILTERは、一般的なプロセスを作成します。

図1に示すように、フィルタオブジェクトを初期化します。

(1)コールavfilter_graph_alloc()関数は、フィルタオブジェクト作成
記述情報をオブジェクトに追加(2)コールavfilter_graph_parse_ptr()フィルター。
(3)コールavfilter_graph_config()関数は、コンフィギュレーション、フィルタ構成及び接続形式の妥当性をチェックします。

図2に示すように、フィルタオブジェクトを使用しました:

(1)使用して復号されたフレームデータはローパスフィルタ)(av_buffersrc_add_frame_flags。
(2)処理されたデータを削除するためにフィルタからav_buffersink_get_frame()を使用。

図3に示すように、サンプルコード:

int InitFilter(AVCodecContext * codecContext)
{
	char args[512];
	int ret = 0;

	AVFilter *buffersrc = avfilter_get_by_name("buffer");
	AVFilter *buffersink = avfilter_get_by_name("buffersink");
	g_outputs = avfilter_inout_alloc();
	g_inputs = avfilter_inout_alloc();
	string  filters_descr;// = "scale=iw*2:ih*2";

	// 注意字体文件存放位置
	// fontcolor=red : 红色
	// x,y:输出的位置
	// text:输出的内容
	// fontsize:字符大小
	filters_descr = "drawtext=fontfile=msyh.ttf:fontsize=100:fontcolor=red:text='filter sample':x=100:y=100";
	enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P };

	// 创建滤镜对象
	g_filter_graph = avfilter_graph_alloc();
	if (!g_outputs || !g_inputs || !g_filter_graph) {
		ret = AVERROR(ENOMEM);
		goto InitFilter_error;
	}

	sprintf_s(args, sizeof(args),
		"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
		codecContext->width, codecContext->height,  // 视频宽高
		codecContext->pix_fmt, // 视频格式
		codecContext->time_base.num, codecContext->time_base.den,// 视频频率
		codecContext->sample_aspect_ratio.num, codecContext->sample_aspect_ratio.den// 视频宽高比
	);
	 
	// 创建滤镜的输入端
	ret = avfilter_graph_create_filter(&g_buffersrcContext, buffersrc, "in",
		args, NULL, g_filter_graph);
	if (ret < 0) {
		goto InitFilter_error;
	}

	// 创建滤镜的输出端
	ret = avfilter_graph_create_filter(&g_buffersinkContext, buffersink, "out",
		NULL, NULL, g_filter_graph);
	if (ret < 0) {
		goto InitFilter_error;
	}

	ret = av_opt_set_int_list(g_buffersinkContext, "pix_fmts", pix_fmts,
		AV_PIX_FMT_YUV420P, AV_OPT_SEARCH_CHILDREN);
	if (ret < 0) {
		goto InitFilter_error;
	}

	g_outputs->name = av_strdup("in");
	g_outputs->filter_ctx = g_buffersrcContext;// 把输出端与输入连接
	g_outputs->pad_idx = 0;
	g_outputs->next = NULL;

	g_inputs->name = av_strdup("out");
	g_inputs->filter_ctx = g_buffersinkContext;// 把输入端与输出连接
	g_inputs->pad_idx = 0;
	g_inputs->next = NULL;

	if ((ret = avfilter_graph_parse_ptr(g_filter_graph, 
		filters_descr.c_str(),
		&g_inputs,
		&g_outputs,
		NULL)) 
		< 0
		)
		goto InitFilter_error;

	// 检查有效性,配置滤镜的连接和格式
	if ((ret = avfilter_graph_config(g_filter_graph, NULL)) < 0)
		goto InitFilter_error;

	return ret;

InitFilter_error:
	avfilter_inout_free(&g_inputs);
	avfilter_inout_free(&g_outputs);
	g_inputs = nullptr;
	g_outputs = nullptr;
	return ret;
}

	// 加一帧数据到buffer源,
				if (av_buffersrc_add_frame_flags(g_buffersrcContext, pSrcFrame, AV_BUFFERSRC_FLAG_KEEP_REF) >= 0)
				{
					// 从sink中取出带滤镜数据的帧。
					if (av_buffersink_get_frame(g_buffersinkContext, filterFrame) >= 0)
					{
						....
					}
				}

4、プロジェクトのソースコードのダウンロード:

X86 -デバッグでは、
環境工学の発展を含んでいます。

ソースコードをダウンロードしてください

公開された43元の記事 ウォンの賞賛9 ビュー2646

おすすめ

転載: blog.csdn.net/x879014419/article/details/105357660