//FFMpeg版本:3.3.1
#include<iostream>
#include<windows.h>
using namespace std;
//用到的C的头文件
extern "C"
{
#include<libavcodec/avcodec.h>
#include<libavfilter/avfilter.h>
#include<libavfilter/buffersink.h>
#include<libavfilter/buffersrc.h>
#include<libavfilter/avfiltergraph.h>
#include<libavformat/avformat.h>
#include<libavutil/avutil.h>
#include<libavutil/fifo.h>
#include<libavutil/audio_fifo.h>
#include<libavdevice/avdevice.h>
}
//对用到的预编译
#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avfilter.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "swscale.lib")
//第一个音频文件
AVFormatContext* ctx3 = NULL;
int ctx3index = -1;
AVCodecContext* codec_ctx_three = NULL;
AVAudioFifo* ctx3buff = NULL;
//第二个音频文件
AVFormatContext* ctx4 = NULL;
int ctx4index = -1;
AVCodecContext* codec_ctx_four = NULL;
AVAudioFifo* ctx4buff = NULL;
AVFilterGraph* filter_graph = NULL;
AVFilterContext* filter_three_ctx = NULL;
AVFilterContext* filter_four_ctx = NULL;
AVFilterContext* filter_out_ctx = NULL;
//打开输出的文件流IO
//输出文件初始化
AVCodecContext* acode = NULL;
AVFormatContext* out = NULL;
bool status = false;
//打开第一个音频文件
int openMp3Codec3(char* filename)
{
int ret = 0;
ret = avformat_open_input(&ctx3, filename, NULL, NULL);
if (ret < 0)
{
cout << "avformat_open_input ctx3 faaild" << endl;
return -1;
}
ret = avformat_find_stream_info(ctx3, NULL);
if (ret < 0)
{
cout << "avformat_find_stream_info ctx3 faaild" << endl;
return -1;
}
for (int i = 0; i < ctx3->nb_streams; i++)
{
if (ctx3->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
{
ctx3index = i;
break;
}
}
if (ctx3index < 0)
{
cout << "stream not find ctx3 failed" << endl;
return -1;
}
AVCodec* codec = avcodec_find_decoder(ctx3->streams[ctx3index]->codecpar ->codec_id);
if (!codec)
{
cout << "avcodec_find_decoder ctx3 failed" << endl;
return -1;
}
//根据找到的解码器创造上下文
codec_ctx_three = avcodec_alloc_context3(codec);
avcodec_parameters_to_context(codec_ctx_three, ctx3->streams[ctx3index]->codecpar);
avcodec_open2(codec_ctx_three, codec, NULL);
if (ret < 0)
{
cout << "avcodec_open2 ctx3 failed" << endl;
return -1;
}
//第四个参数设置为0,表示输入的音频数据,如果为1的话,就是输出的音频数据
av_dump_format(ctx3, ctx3index, filename,0);
return ret;
}
//打开第二个音频文件
int openMp3Codec4(char* filename)
{
int ret = 0;
ret = avformat_open_input(&ctx4, filename, NULL, NULL);
ret = avformat_find_stream_info(ctx4, NULL);
for (int i = 0; i < ctx4->nb_streams; i++)
{
if (ctx4->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
{
ctx4index = i;
break;
}
}
AVCodec* codec = avcodec_find_decoder(ctx4->streams[ctx4index]->codecpar->codec_id);
//根据找到的解码器创造上下文
codec_ctx_four = avcodec_alloc_context3(codec);
avcodec_parameters_to_context(codec_ctx_four, ctx4->streams[ctx4index]->codecpar);
avcodec_open2(codec_ctx_four, codec, NULL);
//第四个参数设置为0,表示输入的音频数据,如果为1的话,就是输出的音频数据
av_dump_format(ctx4, ctx4index, filename, 0);
return ret;
}
int openFileIO(char* filename) {
int ret = 0;
AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_MP3);
if (!codec)
{
cout << "avcodec_find_encoder faild" << endl;
return -1;
}
acode = avcodec_alloc_context3(codec);
if (!acode)
{
cout << "avcodec_alloc_context3 out faild" << endl;
return -1;
}
acode->sample_rate = 44100;
acode->bit_rate = 320000;
acode->time_base.num = 1;
acode->time_base.den = 44100;
acode->channels = 2;
acode->channel_layout = AV_CH_LAYOUT_STEREO;
acode->sample_fmt = AV_SAMPLE_FMT_S32P;
acode->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
ret = avcodec_open2(acode, codec, NULL);
if (ret < 0)
{
cout << "avcodec_open2 out faild" << endl;
return -1;
}
ret = avformat_alloc_output_context2(&out, NULL, NULL, filename);
if (ret < 0)
{
cout << "avformat_alloc_output_context2 out faild" << endl;
return -1;
}
AVStream* audio_stream = avformat_new_stream(out, NULL);
audio_stream->codecpar->codec_tag = 0;
avcodec_parameters_from_context(audio_stream->codecpar, acode);
ret = avio_open(&out->pb, filename, AVIO_FLAG_WRITE);
if (ret < 0)
{
cout << "avio_open out faild" << endl;
return -1;
}
avformat_write_header(out, NULL);
ctx3buff = av_audio_fifo_alloc(codec_ctx_three->sample_fmt,
ctx3->streams[ctx3index]->codecpar->channels,
30 * codec_ctx_three->frame_size
);
ctx4buff = av_audio_fifo_alloc(codec_ctx_four->sample_fmt,
ctx4->streams[ctx4index]->codecpar->channels,
30 * codec_ctx_four->frame_size
);
return ret;
}
int InitFilter(const char* filter_desc)
{
int ret = 0;
const char* mp3_three = "in0";
const char* mp3_four = "in1";
//用于装载音频参数
char args_three[512];
char args_four[512];
//寻找输入输出的过滤器
AVFilter * filter_three = avfilter_get_by_name("abuffer");
AVFilter* filter_four = avfilter_get_by_name("abuffer");
AVFilter* filter_out = avfilter_get_by_name("abuffersink");
if (!filter_three || !filter_four || !filter_out)
{
cout << " avfilter_get_by_name faild" << endl;
return -1;
}
//AVFilterGraph,分配输入输出流
AVFilterInOut* filter_three_inout = avfilter_inout_alloc();
AVFilterInOut* filter_four_inout = avfilter_inout_alloc();
AVFilterInOut* filter_out_inout = avfilter_inout_alloc();
//分配一个过滤图
filter_graph = avfilter_graph_alloc();
if (!filter_graph)
{
cout << " avfilter_inout_alloc faild" << endl;
return -1;
}
sprintf_s(args_three, sizeof(args_three),
"time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%I64x",
codec_ctx_three->time_base.num,
codec_ctx_three->time_base.den,
ctx3->streams[ctx3index]->codecpar->sample_rate,
av_get_sample_fmt_name(codec_ctx_three->sample_fmt),
ctx3->streams[ctx3index]->codecpar->channel_layout
);
sprintf_s(args_four, sizeof(args_four),
"time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%I64x",
codec_ctx_four->time_base.num,
codec_ctx_four->time_base.den,
ctx4->streams[ctx4index]->codecpar->sample_rate,
av_get_sample_fmt_name(codec_ctx_four->sample_fmt),
ctx4->streams[ctx4index]->codecpar->channel_layout
);
//AVFilterContext* filter_three_ctx = NULL;
//AVFilterContext* filter_four_ctx = NULL;
//AVFilterContext* filter_out_ctx = NULL;
ret = avfilter_graph_create_filter(&filter_three_ctx,
filter_three,
mp3_three, args_three,
NULL, filter_graph);
if (ret < 0)
{
cout << "avfilter_graph_create_filter faild" << endl;
return -1;
}
ret = avfilter_graph_create_filter(&filter_four_ctx,
filter_four,
mp3_four, args_four,
NULL, filter_graph);
if (ret < 0)
{
cout << "avfilter_graph_create_filter faild" << endl;
return -1;
}
//初始化AVFilterContext,并将其添加到过滤图,输出的过滤图初始化
ret = avfilter_graph_create_filter(&filter_out_ctx,
filter_out,
"out", NULL,
NULL, filter_graph);
if (ret < 0)
{
cout << "avfilter_graph_create_filter faild" << endl;
return -1;
}
//输出的采样率,样本格式,通道样本布局
ret = av_opt_set_bin(filter_out_ctx, "sample_rates", (uint8_t *)&acode->sample_rate,
sizeof(acode->sample_rate), AV_OPT_SEARCH_CHILDREN);
if (ret < 0)
{
cout << "av_opt_set_bin faild" << endl;
return -1;
}
ret = av_opt_set_bin(filter_out_ctx, "channel_layouts", (uint8_t*)&acode->channel_layout,
sizeof(acode->channel_layout), AV_OPT_SEARCH_CHILDREN);
if (ret < 0)
{
cout << "av_opt_set_bin faild" << endl;
return -1;
}
ret = av_opt_set_bin(filter_out_ctx, "sample_fmts", (uint8_t*)&acode->sample_fmt,
sizeof(acode->sample_fmt), AV_OPT_SEARCH_CHILDREN);
if (ret < 0)
{
cout << "av_opt_set_bin faild" << endl;
return -1;
}
//AVFilterGraph分配输入输出流
filter_three_inout->name = av_strdup(mp3_three);
filter_three_inout->filter_ctx = filter_three_ctx;
filter_three_inout->pad_idx = 0;
filter_three_inout->next = filter_four_inout;
filter_four_inout->name = av_strdup(mp3_four);
filter_four_inout->filter_ctx = filter_four_ctx;
filter_four_inout->pad_idx = 0;
filter_four_inout->next = NULL;
filter_out_inout->name = av_strdup("out");
filter_out_inout->filter_ctx = filter_out_ctx;
filter_out_inout->pad_idx = 0;
filter_out_inout->next = NULL;
AVFilterInOut* filter_outputs[2];
filter_outputs[0] = filter_three_inout;
filter_outputs[1] = filter_four_inout;
//将描述的过滤图添加到对象中
ret = avfilter_graph_parse_ptr(filter_graph, filter_desc,
&filter_out_inout, filter_outputs, NULL);
if (ret < 0)
{
cout << "avfilter_graph_parse_ptr faild" << endl;
return -1;
}
//检查过滤图所有链接格式
ret = avfilter_graph_config(filter_graph, NULL);
if (ret < 0)
{
cout << " avfilter_graph_config faild" << endl;
return -1;
}
char *infos = avfilter_graph_dump(filter_graph, NULL);
printf("%s
", infos);
return ret;
}
DWORD WINAPI three_demux(LPVOID IpParam) {
int ret = 0;
AVPacket packet;
av_init_packet(&packet);
AVFrame* pFrame = av_frame_alloc();
while (status)
{
packet.data = NULL;
packet.size = 0;
//读取数据
ret = av_read_frame(ctx3, &packet);
if (ret < 0)
{
av_packet_unref(&packet);
break;
}
cout << packet.size << endl;
//将数据发送到解码线程
ret = avcodec_send_packet(codec_ctx_three, &packet);
if (ret < 0)
{
cout << "avcodec_send_packet faild" << endl;
break;
}
//接受解码后的数据
ret = avcodec_receive_frame(codec_ctx_three, pFrame);
int three_size = av_audio_fifo_space(ctx3buff);
while (three_size < pFrame->nb_samples && !status)
{
Sleep(10);
three_size = av_audio_fifo_space(ctx3buff);
cout<< "ctx3buff full wait" << endl;
}
//判断缓存队列中可供写入大小
if (three_size >= pFrame->nb_samples)
{
av_audio_fifo_write(ctx3buff, (void**)pFrame->data, pFrame->nb_samples);
}
av_packet_unref(&packet);
}
av_frame_free(&pFrame);
return ret;
}
DWORD WINAPI four_demux(LPVOID IpParam) {
int ret = 0;
AVPacket packet;
AVFrame* pFrame = av_frame_alloc();
av_init_packet(&packet);
while (status)
{
packet.data = NULL;
packet.size = 0;
ret = av_read_frame(ctx4, &packet);
if (ret < 0)
{
av_packet_unref(&packet);
break;
}
cout << packet.size << endl;
ret = avcodec_send_packet(codec_ctx_four, &packet);
if (ret < 0)
{
cout << "avcodec_send_packet faild" << endl;
break;
}
ret = avcodec_receive_frame(codec_ctx_four, pFrame);
int four_size = av_audio_fifo_space(ctx4buff);
while (four_size < pFrame->nb_samples && !status)
{
Sleep(10);
four_size = av_audio_fifo_space(ctx4buff);
cout << "ctx3buff full wait" << endl;
}
if (four_size >= pFrame->nb_samples)
{
av_audio_fifo_write(ctx4buff, (void**)pFrame->data, pFrame->nb_samples);
}
av_packet_unref(&packet);
}
av_frame_free(&pFrame);
return ret;
}
int main()
{
//注册
av_register_all();
avcodec_register_all();
avfilter_register_all();
int ret = 0;
char input3[] = "3.mp3";
char input4[] = "4.mp3";
ret = openMp3Codec3(input3);
if (ret < 0)
{
cout << "openMp3Codec3 faild" << endl;
return -1;
}
ret = openMp3Codec4(input4);
if (ret < 0)
{
cout << "openMp3Codec4 faild" << endl;
return -1;
}
char outfile[] = "out.mp3";
ret = openFileIO(outfile);
if (ret < 0)
{
cout << "openFileIO faild" << endl;
return -1;
}
//过滤器配置
const char* filter_desc = "[in0][in1]amix=inputs=2[out]";
ret = InitFilter(filter_desc);
if (ret < 0)
{
cout << "InitFilter faild" << endl;
return -1;
}
status = true;
CreateThread(NULL, 0, three_demux, 0, 0, NULL);
CreateThread(NULL, 0, four_demux, 0, 0, NULL);
while (status)
{
}
return 0;
}