欢迎光临散文网 会员登陆 & 注册

请给出ffmpeg混音的C++代码

2023-04-24 17:46 作者:音视频开发进阶  | 我要投稿

以下是一个简单的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加群免费领取~


请给出ffmpeg混音的C++代码的评论 (共 条)

分享到微博请遵守国家法律