#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;
}
ffmpeg解码opus,生成pcm,再由pcm转成aac格式
于 2021-11-01 15:33:05 首次发布