ffmpeg解码opus,生成pcm,再由pcm转成aac格式

#include <iostream>
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
}

int main() {
    const char* opusFile = "input.opus";  // 输入Opus文件路径
    const char* pcmFile = "output.pcm";  // 输出PCM文件路径
    const char* aacFile = "output.aac";  // 输出AAC文件路径

    // 初始化FFmpeg库
    av_register_all();

    // 打开输入文件
    AVFormatContext* inputContext = nullptr;
    if (avformat_open_input(&inputContext, opusFile, nullptr, nullptr) < 0) {
        std::cerr << "Failed to open input file" << std::endl;
        return -1;
    }

    // 获取音频流信息
    AVCodecParameters* audioCodecParameters = nullptr;
    int audioStreamIndex = av_find_best_stream(inputContext, AVMEDIA_TYPE_AUDIO, -1, -1, nullptr, 0);
    if (audioStreamIndex < 0) {
        std::cerr << "Failed to find audio stream" << std::endl;
        return -1;
    }
    audioCodecParameters = inputContext->streams[audioStreamIndex]->codecpar;

    // 查找解码器
    AVCodec* decoder = avcodec_find_decoder(AV_CODEC_ID_OPUS);
    if (!decoder) {
        std::cerr << "Failed to find decoder" << std::endl;
        return -1;
    }

    // 创建解码器上下文
    AVCodecContext* decoderContext = avcodec_alloc_context3(decoder);
    if (!decoderContext) {
        std::cerr << "Failed to allocate decoder context" << std::endl;
        return -1;
    }

    // 设置解码器参数
    if (avcodec_parameters_to_context(decoderContext, audioCodecParameters) < 0) {
        std::cerr << "Failed to copy codec parameters to decoder context" << std::endl;
        return -1;
    }

    // 打开解码器
    if (avcodec_open2(decoderContext, decoder, nullptr) < 0) {
        std::cerr << "Failed to open decoder" << std::endl;
        return -1;
    }

    // 创建输出文件
    FILE* pcmOutputFile = fopen(pcmFile, "wb");
    if (!pcmOutputFile) {
        std::cerr << "Failed to open PCM output file" << std::endl;
        return -1;
    }

    // 解码Opus并生成PCM文件
    AVPacket packet;
    av_init_packet(&packet);
    AVFrame* frame = av_frame_alloc();

    while (av_read_frame(inputContext, &packet) >= 0) {
        if (packet.stream_index == audioStreamIndex) {
            int ret = avcodec_send_packet(decoderContext, &packet);
            if (ret < 0) {
                std::cerr << "Error sending a packet to the decoder" << std::endl;
                break;
            }

            while (ret >= 0) {
                ret = avcodec_receive_frame(decoderContext, frame);
                if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
                    break;
                else if (ret < 0) {
                    std::cerr << "Error receiving a frame from the decoder" << std::endl;
                    break;
                }

                // 将解码后的音频写入PCM文件,这里可以直接将数据塞给编码器
                fwrite(frame->data[0], 1, frame->linesize[0], pcmOutputFile);
            }
        }

        av_packet_unref(&packet);
    }

    // 关闭文件和释放资源
    fclose(pcmOutputFile);
    av_frame_free(&frame);
    avcodec_free_context(&decoderContext);
    avformat_close_input(&inputContext);
    avformat_free_context(inputContext);

    // 调用FFmpeg命令行将PCM转为AAC
    std::string command = "ffmpeg -f s16le -ar 44100 -ac 2 -i " + std::string(pcmFile) + " -c:a aac -b:a 128k " + std::string(aacFile);

    int result = system(command.c_str());
    if (result != 0) {
        std::cerr << "Failed to convert PCM to AAC" << std::endl;
        return -1;
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值