請給出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;
} ```
相關(guān)學(xué)習(xí)資料推薦,點(diǎn)擊下方鏈接免費(fèi)報名,先碼住不迷路~】
音視頻免費(fèi)學(xué)習(xí)地址:FFmpeg/WebRTC/RTMP/NDK/Android音視頻流媒體高級開發(fā)
【免費(fèi)分享】音視頻學(xué)習(xí)資料包、大廠面試題、技術(shù)視頻和學(xué)習(xí)路線圖,資料包括(C/C++,Linux,F(xiàn)Fmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以點(diǎn)擊788280672加群免費(fèi)領(lǐng)取~
