| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581 |
- #include "codec_audio_decoder.h"
- #include "../base/logger.h"
- #include "../base/media_common.h"
- #include <algorithm>
- #include <sstream>
- #include <thread>
- extern "C" {
- #include <libavcodec/avcodec.h>
- #include <libavutil/channel_layout.h>
- #include <libavutil/opt.h>
- #include <libswresample/swresample.h>
- }
- namespace av {
- namespace codec {
- // 静态成员初始化
- std::vector<std::string> AudioDecoder::supportedDecoders_;
- std::once_flag AudioDecoder::decodersInitFlag_;
- AudioDecoder::AudioDecoder() : AbstractDecoder(MediaType::AUDIO) {
- AV_LOGGER_DEBUG("创建音频解码器");
- }
- AudioDecoder::~AudioDecoder() {
- close();
- AV_LOGGER_DEBUG("音频解码器已销毁");
- }
- ErrorCode AudioDecoder::initialize(const CodecParams& params) {
- if (params.type != MediaType::AUDIO) {
- AV_LOGGER_ERROR("参数类型不是音频");
- return ErrorCode::INVALID_ARGUMENT;
- }
-
- audioParams_ = static_cast<const AudioDecoderParams&>(params);
-
- if (!validateParams(params)) {
- return ErrorCode::INVALID_PARAMS;
- }
-
- setState(CodecState::IDLE);
- AV_LOGGER_INFOF("音频解码器初始化成功: {}", audioParams_.codecName);
-
- return ErrorCode::OK;
- }
- ErrorCode AudioDecoder::open(const CodecParams& params) {
- std::lock_guard<std::mutex> lock(decodeMutex_);
-
- // 如果提供了参数,先初始化
- if (params.type != MediaType::UNKNOWN) {
- ErrorCode initResult = initialize(params);
- if (initResult != ErrorCode::OK) {
- return initResult;
- }
- }
-
- if (state_ != CodecState::IDLE) {
- AV_LOGGER_ERROR("解码器状态无效,无法打开");
- return ErrorCode::INVALID_STATE;
- }
-
- ErrorCode result = initDecoder();
- if (result != ErrorCode::OK) {
- return result;
- }
-
- setState(CodecState::OPENED);
- AV_LOGGER_INFOF("音频解码器已打开: {} ({}Hz, {}ch, {})",
- audioParams_.codecName,
- codecCtx_->sample_rate,
- codecCtx_->ch_layout.nb_channels,
- av_get_sample_fmt_name(codecCtx_->sample_fmt));
-
- return ErrorCode::OK;
- }
- void AudioDecoder::close() {
- std::lock_guard<std::mutex> lock(decodeMutex_);
-
- if (state_ == CodecState::IDLE) {
- return;
- }
-
- // 清理重采样器
- cleanupResampler();
-
- codecCtx_.reset();
- codec_ = nullptr;
- needResampling_ = false;
-
- setState(CodecState::IDLE);
- AV_LOGGER_DEBUG("音频解码器已关闭");
- }
- ErrorCode AudioDecoder::flush() {
- std::lock_guard<std::mutex> lock(decodeMutex_);
-
- if (state_ != CodecState::OPENED && state_ != CodecState::RUNNING) {
- return ErrorCode::INVALID_STATE;
- }
-
- if (codecCtx_) {
- avcodec_flush_buffers(codecCtx_.get());
- }
-
- // 重置重采样器
- if (swrCtx_) {
- swr_close(swrCtx_);
- needResampling_ = false;
- }
-
- setState(CodecState::OPENED);
- AV_LOGGER_DEBUG("音频解码器已重置");
-
- return ErrorCode::OK;
- }
- ErrorCode AudioDecoder::reset() {
- return flush();
- }
- ErrorCode AudioDecoder::decode(const AVPacketPtr& packet, std::vector<AVFramePtr>& frames) {
- std::lock_guard<std::mutex> lock(decodeMutex_);
-
- if (state_ != CodecState::OPENED && state_ != CodecState::RUNNING) {
- return ErrorCode::INVALID_STATE;
- }
-
- setState(CodecState::RUNNING);
-
- auto startTime = std::chrono::high_resolution_clock::now();
-
- ErrorCode result = decodeFrame(packet, frames);
-
- auto endTime = std::chrono::high_resolution_clock::now();
- double processTime = std::chrono::duration<double, std::milli>(endTime - startTime).count();
-
- int totalSamples = 0;
- for (const auto& frame : frames) {
- if (frame) {
- totalSamples += frame->nb_samples;
- }
- }
-
- updateStats(result == ErrorCode::OK, processTime,
- packet ? packet->size : 0, totalSamples);
-
- if (frameCallback_) {
- for (const auto& frame : frames) {
- frameCallback_(frame);
- }
- }
-
- return result;
- }
- ErrorCode AudioDecoder::finishDecode(std::vector<AVFramePtr>& frames) {
- return decode(nullptr, frames); // 发送空包来刷新解码器
- }
- bool AudioDecoder::validateParams(const CodecParams& params) {
- if (params.type != MediaType::AUDIO) {
- AV_LOGGER_ERROR("参数媒体类型不是音频");
- return false;
- }
-
- const auto& audioParams = static_cast<const AudioDecoderParams&>(params);
-
- if (audioParams.codecName.empty()) {
- AV_LOGGER_ERROR("解码器名称为空");
- return false;
- }
-
- if (audioParams.sampleRate <= 0) {
- AV_LOGGER_ERROR("采样率无效");
- return false;
- }
-
- if (audioParams.channels <= 0) {
- AV_LOGGER_ERROR("声道数无效");
- return false;
- }
-
- return true;
- }
- ErrorCode AudioDecoder::initDecoder() {
- // 查找解码器
- codec_ = avcodec_find_decoder_by_name(audioParams_.codecName.c_str());
- if (!codec_) {
- AV_LOGGER_ERRORF("未找到解码器: {}", audioParams_.codecName);
- return ErrorCode::CODEC_NOT_FOUND;
- }
-
- if (codec_->type != AVMEDIA_TYPE_AUDIO) {
- AV_LOGGER_ERROR("解码器类型不是音频");
- return ErrorCode::INVALID_ARGUMENT;
- }
-
- // 创建解码上下文
- codecCtx_ = makeAVCodecContext(codec_);
- if (!codecCtx_) {
- AV_LOGGER_ERROR("分配解码上下文失败");
- return ErrorCode::OUT_OF_MEMORY;
- }
-
- // 设置解码器参数
- ErrorCode result = setupDecoderParams();
- if (result != ErrorCode::OK) {
- return result;
- }
-
- // 打开解码器前的详细日志
- AV_LOGGER_INFOF("准备打开音频解码器: {}", audioParams_.codecName);
- AV_LOGGER_INFOF("解码器参数: 采样率: {}, 声道: {}, 格式: {}, 线程数: {}",
- codecCtx_->sample_rate,
- codecCtx_->ch_layout.nb_channels,
- av_get_sample_fmt_name(codecCtx_->sample_fmt),
- codecCtx_->thread_count);
-
- // 打开解码器
- int ret = avcodec_open2(codecCtx_.get(), codec_, nullptr);
- if (ret < 0) {
- AV_LOGGER_ERRORF("打开音频解码器失败: {} (错误码: {})",
- ffmpeg_utils::errorToString(ret), ret);
-
- // 详细错误分析
- if (ret == AVERROR(EINVAL)) {
- AV_LOGGER_ERROR("解码器参数无效 - 可能的原因:");
- AV_LOGGER_ERROR(" 1. 不支持的采样格式或参数组合");
- AV_LOGGER_ERROR(" 2. 采样率或声道数不支持");
- } else if (ret == AVERROR(ENOMEM)) {
- AV_LOGGER_ERROR("内存不足 - 无法分配解码器资源");
- }
-
- return static_cast<ErrorCode>(ret);
- }
-
- AV_LOGGER_INFOF("音频解码器打开成功: {}", audioParams_.codecName);
-
- return ErrorCode::OK;
- }
- ErrorCode AudioDecoder::setupDecoderParams() {
- // 设置线程数
- if (audioParams_.threadCount > 0) {
- codecCtx_->thread_count = audioParams_.threadCount;
- } else {
- codecCtx_->thread_count = std::thread::hardware_concurrency();
- }
-
- // 设置采样率(如果指定)
- if (audioParams_.sampleRate > 0) {
- codecCtx_->sample_rate = audioParams_.sampleRate;
- }
-
- // 设置声道数(如果指定)
- if (audioParams_.channels > 0) {
- av_channel_layout_default(&codecCtx_->ch_layout, audioParams_.channels);
- }
-
- // 设置采样格式(如果指定)
- if (audioParams_.sampleFormat != AV_SAMPLE_FMT_NONE) {
- codecCtx_->sample_fmt = audioParams_.sampleFormat;
- }
-
- // 低延迟设置
- if (audioParams_.lowLatency) {
- codecCtx_->flags |= AV_CODEC_FLAG_LOW_DELAY;
- codecCtx_->flags2 |= AV_CODEC_FLAG2_FAST;
- }
-
- // 针对特定解码器的优化设置
- if (audioParams_.codecName == "aac") {
- // AAC 特定设置
- av_opt_set(codecCtx_->priv_data, "dual_mono_mode", "stereo", 0);
- } else if (audioParams_.codecName == "mp3" || audioParams_.codecName == "mp3float") {
- // MP3 特定设置
- if (audioParams_.lowLatency) {
- av_opt_set_int(codecCtx_->priv_data, "skip_frame", 0, 0);
- }
- } else if (audioParams_.codecName == "opus") {
- // Opus 特定设置
- if (audioParams_.lowLatency) {
- av_opt_set_int(codecCtx_->priv_data, "apply_phase_inv", 0, 0);
- }
- }
-
- return ErrorCode::OK;
- }
- ErrorCode AudioDecoder::decodeFrame(const AVPacketPtr& packet, std::vector<AVFramePtr>& frames) {
- // 发送包到解码器
- int ret = avcodec_send_packet(codecCtx_.get(), packet ? packet.get() : nullptr);
- if (ret < 0 && ret != AVERROR_EOF) {
- AV_LOGGER_ERRORF("发送包到音频解码器失败: {}", ffmpeg_utils::errorToString(ret));
- return static_cast<ErrorCode>(ret);
- }
-
- // 接收解码后的帧
- return receiveFrames(frames);
- }
- ErrorCode AudioDecoder::receiveFrames(std::vector<AVFramePtr>& frames) {
- while (true) {
- AVFramePtr frame = makeAVFrame();
- if (!frame) {
- return ErrorCode::OUT_OF_MEMORY;
- }
-
- int ret = avcodec_receive_frame(codecCtx_.get(), frame.get());
- if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
- break; // 需要更多输入或已结束
- }
-
- if (ret < 0) {
- AV_LOGGER_ERRORF("接收音频解码帧失败: {}", ffmpeg_utils::errorToString(ret));
- return static_cast<ErrorCode>(ret);
- }
-
- // 格式转换(如果需要)
- auto convertedFrame = convertFrame(std::move(frame));
- if (convertedFrame) {
- frames.push_back(std::move(convertedFrame));
- }
- }
-
- return ErrorCode::OK;
- }
- AVFramePtr AudioDecoder::convertFrame(AVFramePtr frame) {
- if (!frame) {
- return nullptr;
- }
-
- // 检查是否需要重采样
- bool needConvert = (frame->format != audioParams_.sampleFormat) ||
- (frame->sample_rate != audioParams_.sampleRate) ||
- (frame->ch_layout.nb_channels != audioParams_.channels);
-
- if (!needConvert) {
- return std::move(frame); // 格式已经匹配,直接返回
- }
-
- // 设置重采样器
- ErrorCode result = setupResampler(frame.get());
- if (result != ErrorCode::OK) {
- AV_LOGGER_ERROR("设置重采样器失败");
- return nullptr;
- }
-
- // 创建输出帧
- AVFramePtr outFrame = makeAVFrame();
- if (!outFrame) {
- return nullptr;
- }
-
- outFrame->format = audioParams_.sampleFormat;
- outFrame->sample_rate = audioParams_.sampleRate;
- av_channel_layout_default(&outFrame->ch_layout, audioParams_.channels);
-
- // 计算输出采样数
- int outSamples = swr_get_out_samples(swrCtx_, frame->nb_samples);
- outFrame->nb_samples = outSamples;
-
- // 分配输出缓冲区
- if (av_frame_get_buffer(outFrame.get(), 0) < 0) {
- AV_LOGGER_ERROR("分配音频输出缓冲区失败");
- return nullptr;
- }
-
- // 执行重采样
- int convertedSamples = swr_convert(swrCtx_,
- outFrame->data, outSamples,
- (const uint8_t**)frame->data, frame->nb_samples);
-
- if (convertedSamples < 0) {
- AV_LOGGER_ERRORF("音频重采样失败: {}", ffmpeg_utils::errorToString(convertedSamples));
- return nullptr;
- }
-
- outFrame->nb_samples = convertedSamples;
-
- // 复制时间戳等信息
- av_frame_copy_props(outFrame.get(), frame.get());
-
- return outFrame;
- }
- ErrorCode AudioDecoder::setupResampler(const AVFrame* inputFrame) {
- if (!inputFrame) {
- return ErrorCode::INVALID_ARGUMENT;
- }
-
- // 检查是否需要重新配置重采样器
- bool needReconfigure = !swrCtx_ ||
- !needResampling_ ||
- (inputFrame->format != codecCtx_->sample_fmt) ||
- (inputFrame->sample_rate != codecCtx_->sample_rate) ||
- (inputFrame->ch_layout.nb_channels != codecCtx_->ch_layout.nb_channels);
-
- if (!needReconfigure) {
- return ErrorCode::OK;
- }
-
- // 清理旧的重采样器
- cleanupResampler();
-
- // 创建新的重采样器
- swrCtx_ = swr_alloc();
- if (!swrCtx_) {
- AV_LOGGER_ERROR("分配重采样器失败");
- return ErrorCode::OUT_OF_MEMORY;
- }
-
- // 设置输入参数
- av_opt_set_chlayout(swrCtx_, "in_chlayout", &inputFrame->ch_layout, 0);
- av_opt_set_int(swrCtx_, "in_sample_rate", inputFrame->sample_rate, 0);
- av_opt_set_sample_fmt(swrCtx_, "in_sample_fmt", static_cast<AVSampleFormat>(inputFrame->format), 0);
-
- // 设置输出参数
- AVChannelLayout out_ch_layout;
- av_channel_layout_default(&out_ch_layout, audioParams_.channels);
- av_opt_set_chlayout(swrCtx_, "out_chlayout", &out_ch_layout, 0);
- av_opt_set_int(swrCtx_, "out_sample_rate", audioParams_.sampleRate, 0);
- av_opt_set_sample_fmt(swrCtx_, "out_sample_fmt", audioParams_.sampleFormat, 0);
-
- // 初始化重采样器
- int ret = swr_init(swrCtx_);
- if (ret < 0) {
- AV_LOGGER_ERRORF("初始化重采样器失败: {}", ffmpeg_utils::errorToString(ret));
- cleanupResampler();
- return static_cast<ErrorCode>(ret);
- }
-
- needResampling_ = true;
-
- AV_LOGGER_INFOF("重采样器配置成功: {}Hz,{}ch,{} -> {}Hz,{}ch,{}",
- inputFrame->sample_rate, inputFrame->ch_layout.nb_channels,
- av_get_sample_fmt_name(static_cast<AVSampleFormat>(inputFrame->format)),
- audioParams_.sampleRate, audioParams_.channels,
- av_get_sample_fmt_name(audioParams_.sampleFormat));
-
- return ErrorCode::OK;
- }
- void AudioDecoder::cleanupResampler() {
- if (swrCtx_) {
- swr_free(&swrCtx_);
- swrCtx_ = nullptr;
- }
- needResampling_ = false;
- }
- void AudioDecoder::updateStats(bool success, double decodeTime, size_t dataSize, int samples) {
- std::lock_guard<std::mutex> lock(statsMutex_);
-
- if (success) {
- stats_.decodedFrames++;
- stats_.totalSamples += samples;
- stats_.totalBytes += dataSize;
- stats_.totalDecodeTime += decodeTime;
-
- // 如果启用了重采样,更新重采样帧数
- if (isResamplingEnabled()) {
- stats_.resampledFrames++;
- }
-
- // 更新平均解码时间
- if (stats_.decodedFrames == 1) {
- stats_.avgDecodeTime = decodeTime;
- } else {
- stats_.avgDecodeTime = stats_.totalDecodeTime / stats_.decodedFrames;
- }
- } else {
- stats_.errorCount++;
- }
- }
- AudioDecoder::DecoderStats AudioDecoder::getStats() const {
- std::lock_guard<std::mutex> lock(statsMutex_);
- return stats_;
- }
- void AudioDecoder::resetStats() {
- std::lock_guard<std::mutex> lock(statsMutex_);
- stats_ = DecoderStats{};
- }
- std::string AudioDecoder::getDecoderName() const {
- return audioParams_.codecName;
- }
- bool AudioDecoder::isResamplingEnabled() const {
- return audioParams_.enableResampling && needResampling_;
- }
- std::vector<std::string> AudioDecoder::getSupportedDecoders() {
- std::call_once(decodersInitFlag_, findUsableDecoders);
- return supportedDecoders_;
- }
- bool AudioDecoder::isDecoderSupported(const std::string& codecName) {
- auto decoders = getSupportedDecoders();
- return std::find(decoders.begin(), decoders.end(), codecName) != decoders.end();
- }
- std::string AudioDecoder::getRecommendedDecoder(const std::string& codecName) {
- auto decoders = getSupportedDecoders();
-
- if (!codecName.empty()) {
- // 查找指定编解码格式的解码器
- if (std::find(decoders.begin(), decoders.end(), codecName) != decoders.end()) {
- return codecName;
- }
-
- // 查找相关的解码器
- for (const auto& decoder : decoders) {
- if (decoder.find(codecName) != std::string::npos) {
- return decoder;
- }
- }
- }
-
- // 返回默认推荐的解码器
- const char* preferredDecoders[] = {"aac", "mp3", "opus", "vorbis", "flac"};
- for (const char* preferred : preferredDecoders) {
- if (std::find(decoders.begin(), decoders.end(), preferred) != decoders.end()) {
- return preferred;
- }
- }
-
- return decoders.empty() ? "" : decoders[0];
- }
- void AudioDecoder::findUsableDecoders() {
- AV_LOGGER_INFO("查找可用的音频解码器...");
-
- // 测试所有音频解码器
- for (const char* decoder : AUDIO_DECODERS) {
- if (decoder && CodecFactory::isCodecSupported(decoder, CodecType::DECODER, MediaType::AUDIO)) {
- supportedDecoders_.emplace_back(decoder);
- AV_LOGGER_INFOF("找到音频解码器: {}", decoder);
- }
- }
-
- AV_LOGGER_INFOF("总共找到 {} 个可用的音频解码器", supportedDecoders_.size());
- }
- // AudioDecoderFactory 实现
- std::unique_ptr<AudioDecoder> AudioDecoder::AudioDecoderFactory::create(const std::string& codecName) {
- auto decoder = std::make_unique<AudioDecoder>();
-
- if (!codecName.empty()) {
- if (!CodecFactory::isCodecSupported(codecName, CodecType::DECODER, MediaType::AUDIO)) {
- AV_LOGGER_ERRORF("不支持的音频解码器: {}", codecName);
- return nullptr;
- }
- }
-
- return decoder;
- }
- std::unique_ptr<AudioDecoder> AudioDecoder::AudioDecoderFactory::createBest() {
- std::string codecName = AudioDecoder::getRecommendedDecoder();
-
- if (codecName.empty()) {
- AV_LOGGER_ERROR("未找到可用的音频解码器");
- return nullptr;
- }
-
- return create(codecName);
- }
- } // namespace codec
- } // namespace av
|