#include "codec_audio_decoder.h" #include "../base/logger.h" #include "../base/media_common.h" #include #include #include extern "C" { #include #include #include #include } namespace av { namespace codec { // 静态成员初始化 std::vector 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_PARAMS; } audioParams_ = static_cast(params); if (!validateParams(params)) { return ErrorCode::INVALID_PARAMS; } setState(CodecState::IDLE); AV_LOGGER_INFOF("音频解码器初始化成功: {}", audioParams_.codecName); return ErrorCode::SUCCESS; } ErrorCode AudioDecoder::open(const CodecParams& params) { std::lock_guard lock(decodeMutex_); // 如果提供了参数,先初始化 if (params.type != MediaType::UNKNOWN) { ErrorCode initResult = initialize(params); if (initResult != ErrorCode::SUCCESS) { return initResult; } } if (state_ != CodecState::IDLE) { AV_LOGGER_ERROR("解码器状态无效,无法打开"); return ErrorCode::INVALID_STATE; } ErrorCode result = initDecoder(); if (result != ErrorCode::SUCCESS) { 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::SUCCESS; } void AudioDecoder::close() { std::lock_guard 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 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::SUCCESS; } ErrorCode AudioDecoder::reset() { return flush(); } ErrorCode AudioDecoder::decode(const AVPacketPtr& packet, std::vector& frames) { std::lock_guard 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(endTime - startTime).count(); int totalSamples = 0; for (const auto& frame : frames) { if (frame) { totalSamples += frame->nb_samples; } } updateStats(result == ErrorCode::SUCCESS, processTime, packet ? packet->size : 0, totalSamples); if (frameCallback_) { for (const auto& frame : frames) { frameCallback_(frame); } } return result; } ErrorCode AudioDecoder::finishDecode(std::vector& 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(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_PARAMS; } // 创建解码上下文 codecCtx_ = makeAVCodecContext(codec_); if (!codecCtx_) { AV_LOGGER_ERROR("分配解码上下文失败"); return ErrorCode::MEMORY_ALLOC_FAILED; } // 设置解码器参数 ErrorCode result = setupDecoderParams(); if (result != ErrorCode::SUCCESS) { 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(ret); } AV_LOGGER_INFOF("音频解码器打开成功: {}", audioParams_.codecName); return ErrorCode::SUCCESS; } 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::SUCCESS; } ErrorCode AudioDecoder::decodeFrame(const AVPacketPtr& packet, std::vector& 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(ret); } // 接收解码后的帧 return receiveFrames(frames); } ErrorCode AudioDecoder::receiveFrames(std::vector& frames) { while (true) { AVFramePtr frame = makeAVFrame(); if (!frame) { return ErrorCode::MEMORY_ALLOC_FAILED; } 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(ret); } // 格式转换(如果需要) auto convertedFrame = convertFrame(std::move(frame)); if (convertedFrame) { frames.push_back(std::move(convertedFrame)); } } return ErrorCode::SUCCESS; } 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::SUCCESS) { 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_PARAMS; } // 检查是否需要重新配置重采样器 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::SUCCESS; } // 清理旧的重采样器 cleanupResampler(); // 创建新的重采样器 swrCtx_ = swr_alloc(); if (!swrCtx_) { AV_LOGGER_ERROR("分配重采样器失败"); return ErrorCode::MEMORY_ALLOC_FAILED; } // 设置输入参数 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(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(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(inputFrame->format)), audioParams_.sampleRate, audioParams_.channels, av_get_sample_fmt_name(audioParams_.sampleFormat)); return ErrorCode::SUCCESS; } 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 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 lock(statsMutex_); return stats_; } void AudioDecoder::resetStats() { std::lock_guard lock(statsMutex_); stats_ = DecoderStats{}; } std::string AudioDecoder::getDecoderName() const { return audioParams_.codecName; } bool AudioDecoder::isResamplingEnabled() const { return audioParams_.enableResampling && needResampling_; } std::vector 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::AudioDecoderFactory::create(const std::string& codecName) { auto decoder = std::make_unique(); if (!codecName.empty()) { if (!CodecFactory::isCodecSupported(codecName, CodecType::DECODER, MediaType::AUDIO)) { AV_LOGGER_ERRORF("不支持的音频解码器: {}", codecName); return nullptr; } } return decoder; } std::unique_ptr AudioDecoder::AudioDecoderFactory::createBest() { std::string codecName = AudioDecoder::getRecommendedDecoder(); if (codecName.empty()) { AV_LOGGER_ERROR("未找到可用的音频解码器"); return nullptr; } return create(codecName); } } // namespace codec } // namespace av