音视频处理FFMPeg开发实战(8) -- Filter的使用(录制麦克的声音,变换格式处理)

从主机麦克中取出音频,经过Filter变换处理,编码为TS文件。

1、首先要取得主机麦克设备的名称:

用ffmpeg 命令取ymt
ffmpeg -list_devices true -f dshow -i dummy
如下图所示:
在这里插入图片描述

2、麦克设备的名称转化为UTF-8

由于函数需要,要把设备名称转为UTF-8格式:

WideCharToMultiByte(CP_UTF8, 0, wchar_devicename, -1, utf_8_devicename, buffer_len, 0, 0);

3、Filter主要源码:

(1)创建filter:

int InitAudioFilter(AVCodecContext * codecContext)
{
	char args[512];
	int ret;
	AVFilter *abuffersrc = avfilter_get_by_name("abuffer");
	AVFilter *abuffersink = avfilter_get_by_name("abuffersink");
	g_outputs = avfilter_inout_alloc();
	g_inputs = avfilter_inout_alloc();

	auto audioDecoderContext = g_inputAudioFormatContext->streams[0]->codec;
	if (!audioDecoderContext->channel_layout)
		audioDecoderContext->channel_layout = av_get_default_channel_layout(audioDecoderContext->channels);

	static const enum AVSampleFormat out_sample_fmts[] = { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE };
	static const int64_t out_channel_layouts[] = { audioDecoderContext->channel_layout, -1 };
	static const int out_sample_rates[] = { audioDecoderContext->sample_rate , -1 };

	AVRational time_base = g_inputAudioFormatContext->streams[0]->time_base;
	g_filter_graph = avfilter_graph_alloc();
	g_filter_graph->nb_threads = 1;

	sprintf_s(args, sizeof(args),
		"time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%I64x",
		time_base.num, time_base.den, audioDecoderContext->sample_rate,
		av_get_sample_fmt_name(audioDecoderContext->sample_fmt), audioDecoderContext->channel_layout);

	ret = avfilter_graph_create_filter(&g_buffersrcAudioContext, abuffersrc, "in",
		args, NULL, g_filter_graph);
	if (ret < 0) {
		av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer source\n");
		return ret;
	}

	/* buffer audio sink: to terminate the filter chain. */
	ret = avfilter_graph_create_filter(&g_buffersinkContext, abuffersink, "out",
		NULL, NULL, g_filter_graph);
	if (ret < 0) {
		return ret;
	}

	ret = av_opt_set_int_list(g_buffersinkContext, "sample_fmts", out_sample_fmts, -1,
		AV_OPT_SEARCH_CHILDREN);
	if (ret < 0) {
		return ret;
	}

	ret = av_opt_set_int_list(g_buffersinkContext, "channel_layouts", out_channel_layouts, -1,
		AV_OPT_SEARCH_CHILDREN);
	if (ret < 0) {
		return ret;
	}

	ret = av_opt_set_int_list(g_buffersinkContext, "sample_rates", out_sample_rates, -1,
		AV_OPT_SEARCH_CHILDREN);
	if (ret < 0) {
		av_log(NULL, AV_LOG_ERROR, "Cannot set output sample rate\n");
		return ret;
	}

	/* Endpoints for the filter graph. */
	g_outputs->name = av_strdup("in");
	g_outputs->filter_ctx = g_buffersrcAudioContext;;
	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, "anull",
		&g_inputs, &g_outputs, nullptr)) < 0)
		return ret;

	if ((ret = avfilter_graph_config(g_filter_graph, NULL)) < 0)
		return ret;

	av_buffersink_set_frame_size(g_buffersinkContext, 1024);

	return 0;
}

(2)使用filter:

if (av_buffersrc_add_frame_flags(g_buffersrcAudioContext, pSrcAudioFrame, AV_BUFFERSRC_FLAG_PUSH) >= 0)
{
		ret = av_buffersink_get_frame_flags(g_buffersinkContext, filterFrame, AV_BUFFERSINK_FLAG_NO_REQUEST);
		if (ret >= 0)
		{
					....
		}
}

4、工程项目源代码下载:

在本工程在Debug – x86编译通过。

记得调用命令ffmpeg 取得设备名称

项目源代码下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值