请给出ffmpeg混音的C++代码
以下是一个简单的FFmpeg混音C++代码示例:
```c++
include
include
include
extern "C" {
include <libavcodec/avcodec.h>
include <libavformat/avformat.h>
include <libavutil/opt.h>
include <libswresample/swresample.h>
}
using namespace std;
int main(int argc, char* argv[]) { avregisterall(); avformatnetworkinit();
string audio1_file = "audio1.mp3";
string audio2_file = "audio2.mp3";
string output_file = "output.mp3";
AVFormatContext* format_ctx1 = nullptr;
AVFormatContext* format_ctx2 = nullptr;
if (avformat_open_input(&format_ctx1, audio1_file.c_str(), nullptr, nullptr) < 0) {
cout << "Error opening input file: " << audio1_file << endl;
exit(1);
}
if (avformat_open_input(&format_ctx2, audio2_file.c_str(), nullptr, nullptr) < 0) {
cout << "Error opening input file: " << audio2_file << endl;
exit(1);
}
if (avformat_find_stream_info(format_ctx1, nullptr) < 0) {
cout << "Error finding stream information" << endl;
exit(1);
}
if (avformat_find_stream_info(format_ctx2, nullptr) < 0) {
cout << "Error finding stream information" << endl;
exit(1);
}
int audio1_stream_index = -1;
int audio2_stream_index = -1;
AVCodecParameters* codec_params1 = nullptr;
AVCodecParameters* codec_params2 = nullptr;
for (unsigned int i = 0; i < format_ctx1->nb_streams; i++) {
if (format_ctx1->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
audio1_stream_index = i;
codec_params1 = format_ctx1->streams[i]->codecpar;
break;
}
}
for (unsigned int i = 0; i < format_ctx2->nb_streams; i++) {
if (format_ctx2->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
audio2_stream_index = i;
codec_params2 = format_ctx2->streams[i]->codecpar;
break;
}
}
if (audio1_stream_index == -1 || audio2_stream_index == -1) {
cout << "Error finding audio streams" << endl;
exit(1);
}
AVCodec* codec1 = avcodec_find_decoder(codec_params1->codec_id);
AVCodec* codec2 = avcodec_find_decoder(codec_params2->codec_id);
if (!codec1 || !codec2) {
cout << "Error finding codecs" << endl;
exit(1);
}
AVCodecContext* codec_ctx1 = avcodec_alloc_context3(codec1);
AVCodecContext* codec_ctx2 = avcodec_alloc_context3(codec2);
if (!codec_ctx1 || !codec_ctx2) {
cout << "Error allocating codec context" << endl;
exit(1);
}
if (avcodec_parameters_to_context(codec_ctx1, codec_params1) < 0) {
cout << "Error initializing codec context" << endl;
exit(1);
}
if (avcodec_parameters_to_context(codec_ctx2, codec_params2) < 0) {
cout << "Error initializing codec context" << endl;
exit(1);
}
if (avcodec_open2(codec_ctx1, codec1, nullptr) < 0) {
cout << "Error opening codec" << endl;
exit(1);
}
if (avcodec_open2(codec_ctx2, codec2, nullptr) < 0) {
cout << "Error opening codec" << endl;
exit(1);
}
AVPacket* packet = av_packet_alloc();
AVFrame* frame1 = av_frame_alloc();
AVFrame* frame2 = av_frame_alloc();
vector<uint8_t*> data_ptrs1;
vector<uint8_t*> data_ptrs2;
int max_samples = 0;
int num_channels = 0;
int sample_rate = 0;
SwrContext* swr_ctx = nullptr;
while (av_read_frame(format_ctx1, packet) >= 0 || av_read_frame(format_ctx2, packet) >= 0) {
if (packet->stream_index == audio1_stream_index) {
int ret = avcodec_send_packet(codec_ctx1, packet);
if (ret < 0) {
cout << "Error sending packet to decoder" << endl;
exit(1);
}
while (ret >= 0) {
ret = avcodec_receive_frame(codec_ctx1, frame1);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
} else if (ret < 0) {
cout << "Error receiving frame from decoder" << endl;
exit(1);
}
int samples = frame1->nb_samples;
int channels = codec_ctx1->channels;
int sample_rate = codec_ctx1->sample_rate;
max_samples = max(max_samples, samples);
num_channels = channels;
int buffer_size = av_samples_get_buffer_size(nullptr, channels, samples, codec_ctx1->sample_fmt, 0);
uint8_t* data_ptr = new uint8_t[buffer_size];
av_samples_copy(data_ptr, frame1->data, 0, 0, samples, channels, codec_ctx1->sample_fmt);
data_ptrs1.push_back(data_ptr);
}
} else if (packet->stream_index == audio2_stream_index) {
int ret = avcodec_send_packet(codec_ctx2, packet);
if (ret < 0) {
cout << "Error sending packet to decoder" << endl;
exit(1);
}
while (ret >= 0) {
ret = avcodec_receive_frame(codec_ctx2, frame2);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
} else if (ret < 0) {
cout << "Error receiving frame from decoder" << endl;
exit(1);
}
int samples = frame2->nb_samples;
int channels = codec_ctx2->channels;
int sample_rate = codec_ctx2->sample_rate;
max_samples = max(max_samples, samples);
num_channels = channels;
int buffer_size = av_samples_get_buffer_size(nullptr, channels, samples, codec_ctx2->sample_fmt, 0);
uint8_t* data_ptr = new uint8_t[buffer_size];
av_samples_copy(data_ptr, frame2->data, 0, 0, samples, channels, codec_ctx2->sample_fmt);
data_ptrs2.push_back(data_ptr);
}
}
av_packet_unref(packet);
}
avcodec_send_packet(codec_ctx1, nullptr);
avcodec_send_packet(codec_ctx2, nullptr);
while (true) {
int ret1 = avcodec_receive_frame(codec_ctx1, frame1);
if (ret1 == AVERROR(EAGAIN) || ret1 == AVERROR_EOF) {
break;
} else if (ret1 < 0) {
cout << "Error receiving frame from decoder" << endl;
exit(1);
}
int samples = frame1->nb_samples;
int channels = codec_ctx1->channels;
int sample_rate = codec_ctx1->sample_rate;
max_samples = max(max_samples, samples);
num_channels = channels;
int buffer_size = av_samples_get_buffer_size(nullptr, channels, samples, codec_ctx1->sample_fmt, 0);
uint8_t* data_ptr = new uint8_t[buffer_size];
av_samples_copy(data_ptr, frame1->data, 0, 0, samples, channels, codec_ctx1->sample_fmt);
data_ptrs1.push_back(data_ptr);
}
while (true) {
int ret2 = avcodec_receive_frame(codec_ctx2, frame2);
if (ret2 == AVERROR(EAGAIN) || ret2 == AVERROR_EOF) {
break;
} else if (ret2 < 0) {
cout << "Error receiving frame from decoder" << endl;
exit(1);
}
int samples = frame2->nb_samples;
int channels = codec_ctx2->channels;
int sample_rate = codec_ctx2->sample_rate;
max_samples = max(max_samples, samples);
num_channels = channels;
int buffer_size = av_samples_get_buffer_size(nullptr, channels, samples, codec_ctx2->sample_fmt, 0);
uint8_t* data_ptr = new uint8_t[buffer_size];
av_samples_copy(data_ptr, frame2->data, 0, 0, samples, channels, codec_ctx2->sample_fmt);
data_ptrs2.push_back(data_ptr);
}
avcodec_free_context(&codec_ctx1);
avcodec_free_context(&codec_ctx2);
avformat_close_input(&format_ctx1);
avformat_close_input(&format_ctx2);
AVCodec* output_codec = avcodec_find_encoder(AV_CODEC_ID_MP3);
AVCodecContext* output_codec_ctx = avcodec_alloc_context3(output_codec);
AVFormatContext* output_format_ctx = nullptr;
AVStream* output_stream = nullptr;
if (!output_codec) {
cout << "Error finding output codec" << endl;
exit(1);
}
output_codec_ctx->bit_rate = 128000;
output_codec_ctx->channels = num_channels;
output_codec_ctx->channel_layout = av_get_default_channel_layout(num_channels);
output_codec_ctx->sample_rate = sample_rate;
output_codec_ctx->sample_fmt = output_codec->sample_fmts[0];
output_codec_ctx->time_base = { 1, sample_rate };
output_codec_ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
if (avcodec_open2(output_codec_ctx, output_codec, nullptr) < 0) {
cout << "Error opening output codec" << endl;
exit(1);
}
if (avformat_alloc_output_context2(&output_format_ctx, nullptr, nullptr, output_file.c_str()) < 0) {
cout << "Error allocating output format context" << endl;
exit(1);
}
output_stream = avformat_new_stream(output_format_ctx, output_codec);
output_stream->id = output_format_ctx->nb_streams - 1;
if (!output_stream) {
cout << "Error creating output stream" << endl;
exit(1);
}
AVCodecParameters* output_codec_params = avcodec_parameters_alloc();
avcodec_parameters_from_context(output_codec_params, output_codec_ctx);
av_stream_set_codecpar(output_stream, output_codec_params);
if (avio_open(&output_format_ctx->pb, output_file.c_str(), AVIO_FLAG_WRITE) < 0) {
cout << "Error opening output file" << endl;
exit(1);
}
if (avformat_write_header(output_format_ctx, nullptr) < 0) {
cout << "Error writing header to output file" << endl;
exit(1);
}
swr_ctx = swr_alloc_set_opts(nullptr,
av_get_default_channel_layout(num_channels),
output_codec_ctx->sample_fmt,
sample_rate,
av_get_default_channel_layout(num_channels),
AV_SAMPLE_FMT_FLT,
sample_rate,
0,
nullptr);
if (!swr_ctx || swr_init(swr_ctx) < 0) {
cout << "Error initializing resampler" << endl;
exit(1);
}
uint8_t** input_data_ptrs1 = new uint8_t*[data_ptrs1.size()];
uint8_t** input_data_ptrs2 = new uint8_t*[data_ptrs2.size()];
for (unsigned int i = 0; i < data_ptrs1.size(); i++) {
input_data_ptrs1[i] = data_ptrs1[i];
}
for (unsigned int i = 0; i < data_ptrs2.size(); i++) {
input_data_ptrs2[i] = data_ptrs2[i];
}
int num_frames = max_samples;
int dst_linesize;
uint8_t* dst_data[AV_NUM_DATA_POINTERS] = { 0 };
int dst_bufsize = av_samples_get_buffer_size(&dst_linesize, num_channels, num_frames, output_codec_ctx->sample_fmt, 0);
av_fast_malloc(&dst_data[0], &dst_bufsize, dst_linesize);
for (int i = 0; i < num_frames; i++) {
uint8_t* src_data1[AV_NUM_DATA_POINTERS] = { 0 };
uint8_t* src_data2[AV_NUM_DATA_POINTERS] = { 0 };
if (i < (int)data_ptrs1.size()) {
src_data1[0] = input_data_ptrs1[i];
}
if (i < (int)data_ptrs2.size()) {
src_data2[0] = input_data_ptrs2[i];
}
float* src_data[AV_NUM_DATA_POINTERS] = { 0 };
float silence[AV_NUM_DATA_POINTERS][num_channels];
for (int ch = 0; ch < num_channels; ch++) {
if (src_data1[ch] == nullptr && src_data2[ch] == nullptr) {
memset(silence[ch], 0, sizeof(float) * num_frames);
src_data[ch] = silence[ch];
} else if (src_data1[ch] != nullptr && src_data2[ch] == nullptr) {
src_data[ch] = (float*)src_data1[ch];
} else if (src_data1[ch] == nullptr && src_data2[ch] != nullptr) {
src_data[ch] = (float*)src_data2[ch];
} else {
float mix_data[num_frames];
for (int j = 0; j < num_frames; j++) {
mix_data[j] = ((float*)src_data1[ch])[j] + ((float*)src_data2[ch])[j];
}
src_data[ch] = mix_data;
}
}
int ret = swr_convert(swr_ctx, dst_data, num_frames, (const uint8_t**)src_data, num_frames);
if (ret < 0) {
cout << "Error resampling audio data" << endl;
exit(1);
}
AVFrame* output_frame = av_frame_alloc();
output_frame->channels = num_channels;
output_frame->channel_layout = av_get_default_channel_layout(num_channels);
output_frame->format = output_codec_ctx->sample_fmt;
output_frame->sample_rate = sample_rate;
output_frame->nb_samples = num_frames;
avcodec_fill_audio_frame(output_frame, num_channels, output_codec_ctx->sample_fmt, dst_data[0], dst_bufsize, 0);
AVRational time_base = { 1, sample_rate };
output_frame->pts = av_rescale_q(i, time_base, output_stream->time_base);
AVPacket* output_packet = av_packet_alloc();
if (!output_packet) {
cout << "Error allocating packet" << endl;
exit(1);
}
ret = avcodec_send_frame(output_codec_ctx, output_frame);
if (ret < 0) {
cout << "Error sending frame to encoder" << endl;
exit(1);
}
while (ret >= 0) {
ret = avcodec_receive_packet(output_codec_ctx, output_packet);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
} else if (ret < 0) {
cout << "Error receiving packet from encoder" << endl;
exit(1);
}
av_packet_rescale_ts(output_packet, output_codec_ctx->time_base, output_stream->time_base);
av_interleaved_write_frame(output_format_ctx, output_packet);
av_packet_unref(output_packet);
}
av_packet_free(&output_packet);
av_frame_free(&output_frame);
}
av_write_trailer(output_format_ctx);
for (unsigned int i = 0; i < data_ptrs1.size(); i++) {
delete[] data_ptrs1[i];
}
for (unsigned int i = 0; i < data_ptrs2.size(); i++) {
delete[] data_ptrs2[i];
}
avformat_close_input(&format_ctx1);
avformat_close_input(&format_ctx2);
avcodec_free_context(&output_codec_ctx);
avcodec_free_context(&codec_ctx1);
avcodec_free_context(&codec_ctx2);
avformat_free_context(output_format_ctx);
swr_free(&swr_ctx);
return 0;
} ```
相关学习资料推荐,点击下方链接免费报名,先码住不迷路~】
音视频免费学习地址:FFmpeg/WebRTC/RTMP/NDK/Android音视频流媒体高级开发
【免费分享】音视频学习资料包、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以点击788280672加群免费领取~
