codec_audio_decoder.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. #include "codec_audio_decoder.h"
  2. #include "../base/logger.h"
  3. #include "../base/media_common.h"
  4. #include <algorithm>
  5. #include <sstream>
  6. #include <thread>
  7. extern "C" {
  8. #include <libavcodec/avcodec.h>
  9. #include <libavutil/channel_layout.h>
  10. #include <libavutil/opt.h>
  11. #include <libswresample/swresample.h>
  12. }
  13. namespace av {
  14. namespace codec {
  15. // 静态成员初始化
  16. std::vector<std::string> AudioDecoder::supportedDecoders_;
  17. std::once_flag AudioDecoder::decodersInitFlag_;
  18. AudioDecoder::AudioDecoder() : AbstractDecoder(MediaType::AUDIO) {
  19. AV_LOGGER_DEBUG("创建音频解码器");
  20. }
  21. AudioDecoder::~AudioDecoder() {
  22. close();
  23. AV_LOGGER_DEBUG("音频解码器已销毁");
  24. }
  25. ErrorCode AudioDecoder::initialize(const CodecParams& params) {
  26. if (params.type != MediaType::AUDIO) {
  27. AV_LOGGER_ERROR("参数类型不是音频");
  28. return ErrorCode::INVALID_PARAMS;
  29. }
  30. audioParams_ = static_cast<const AudioDecoderParams&>(params);
  31. if (!validateParams(params)) {
  32. return ErrorCode::INVALID_PARAMS;
  33. }
  34. setState(CodecState::IDLE);
  35. AV_LOGGER_INFOF("音频解码器初始化成功: {}", audioParams_.codecName);
  36. return ErrorCode::SUCCESS;
  37. }
  38. ErrorCode AudioDecoder::open(const CodecParams& params) {
  39. std::lock_guard<std::mutex> lock(decodeMutex_);
  40. // 如果提供了参数,先初始化
  41. if (params.type != MediaType::UNKNOWN) {
  42. ErrorCode initResult = initialize(params);
  43. if (initResult != ErrorCode::SUCCESS) {
  44. return initResult;
  45. }
  46. }
  47. if (state_ != CodecState::IDLE) {
  48. AV_LOGGER_ERROR("解码器状态无效,无法打开");
  49. return ErrorCode::INVALID_STATE;
  50. }
  51. ErrorCode result = initDecoder();
  52. if (result != ErrorCode::SUCCESS) {
  53. return result;
  54. }
  55. setState(CodecState::OPENED);
  56. AV_LOGGER_INFOF("音频解码器已打开: {} ({}Hz, {}ch, {})",
  57. audioParams_.codecName,
  58. codecCtx_->sample_rate,
  59. codecCtx_->ch_layout.nb_channels,
  60. av_get_sample_fmt_name(codecCtx_->sample_fmt));
  61. return ErrorCode::SUCCESS;
  62. }
  63. void AudioDecoder::close() {
  64. std::lock_guard<std::mutex> lock(decodeMutex_);
  65. if (state_ == CodecState::IDLE) {
  66. return;
  67. }
  68. // 清理重采样器
  69. cleanupResampler();
  70. codecCtx_.reset();
  71. codec_ = nullptr;
  72. needResampling_ = false;
  73. setState(CodecState::IDLE);
  74. AV_LOGGER_DEBUG("音频解码器已关闭");
  75. }
  76. ErrorCode AudioDecoder::flush() {
  77. std::lock_guard<std::mutex> lock(decodeMutex_);
  78. if (state_ != CodecState::OPENED && state_ != CodecState::RUNNING) {
  79. return ErrorCode::INVALID_STATE;
  80. }
  81. if (codecCtx_) {
  82. avcodec_flush_buffers(codecCtx_.get());
  83. }
  84. // 重置重采样器
  85. if (swrCtx_) {
  86. swr_close(swrCtx_);
  87. needResampling_ = false;
  88. }
  89. setState(CodecState::OPENED);
  90. AV_LOGGER_DEBUG("音频解码器已重置");
  91. return ErrorCode::SUCCESS;
  92. }
  93. ErrorCode AudioDecoder::reset() {
  94. return flush();
  95. }
  96. ErrorCode AudioDecoder::decode(const AVPacketPtr& packet, std::vector<AVFramePtr>& frames) {
  97. // 状态检查(使用基类的线程安全方法)
  98. if (!isOpened()) {
  99. return ErrorCode::INVALID_STATE;
  100. }
  101. // 只在处理过程中锁定,缩小锁的粒度
  102. std::lock_guard<std::mutex> processLock(decodeMutex_);
  103. // 使用StateGuard确保异常安全的状态管理
  104. StateGuard stateGuard(this, CodecState::RUNNING);
  105. auto startTime = std::chrono::high_resolution_clock::now();
  106. ErrorCode result = decodeFrame(packet, frames);
  107. // 只有在成功时才提交状态变更
  108. if (result == ErrorCode::SUCCESS) {
  109. stateGuard.commit();
  110. }
  111. auto endTime = std::chrono::high_resolution_clock::now();
  112. double processTime = std::chrono::duration<double, std::milli>(endTime - startTime).count();
  113. int totalSamples = 0;
  114. for (const auto& frame : frames) {
  115. if (frame) {
  116. totalSamples += frame->nb_samples;
  117. }
  118. }
  119. updateStats(result == ErrorCode::SUCCESS, processTime,
  120. packet ? packet->size : 0, totalSamples);
  121. if (frameCallback_) {
  122. for (const auto& frame : frames) {
  123. frameCallback_(frame);
  124. }
  125. }
  126. return result;
  127. }
  128. ErrorCode AudioDecoder::finishDecode(std::vector<AVFramePtr>& frames) {
  129. return decode(nullptr, frames); // 发送空包来刷新解码器
  130. }
  131. bool AudioDecoder::validateParams(const CodecParams& params) {
  132. if (params.type != MediaType::AUDIO) {
  133. AV_LOGGER_ERROR("参数媒体类型不是音频");
  134. return false;
  135. }
  136. const auto& audioParams = static_cast<const AudioDecoderParams&>(params);
  137. if (audioParams.codecName.empty()) {
  138. AV_LOGGER_ERROR("解码器名称为空");
  139. return false;
  140. }
  141. if (audioParams.sampleRate <= 0) {
  142. AV_LOGGER_ERROR("采样率无效");
  143. return false;
  144. }
  145. if (audioParams.channels <= 0) {
  146. AV_LOGGER_ERROR("声道数无效");
  147. return false;
  148. }
  149. return true;
  150. }
  151. ErrorCode AudioDecoder::initDecoder() {
  152. // 查找解码器
  153. codec_ = avcodec_find_decoder_by_name(audioParams_.codecName.c_str());
  154. if (!codec_) {
  155. AV_LOGGER_ERRORF("未找到解码器: {}", audioParams_.codecName);
  156. return ErrorCode::CODEC_NOT_FOUND;
  157. }
  158. if (codec_->type != AVMEDIA_TYPE_AUDIO) {
  159. AV_LOGGER_ERROR("解码器类型不是音频");
  160. return ErrorCode::INVALID_PARAMS;
  161. }
  162. // 创建解码上下文
  163. codecCtx_ = makeAVCodecContext(codec_);
  164. if (!codecCtx_) {
  165. AV_LOGGER_ERROR("分配解码上下文失败");
  166. return ErrorCode::MEMORY_ALLOC_FAILED;
  167. }
  168. // 设置解码器参数
  169. ErrorCode result = setupDecoderParams();
  170. if (result != ErrorCode::SUCCESS) {
  171. return result;
  172. }
  173. // 打开解码器前的详细日志
  174. AV_LOGGER_INFOF("准备打开音频解码器: {}", audioParams_.codecName);
  175. AV_LOGGER_INFOF("解码器参数: 采样率: {}, 声道: {}, 格式: {}, 线程数: {}",
  176. codecCtx_->sample_rate,
  177. codecCtx_->ch_layout.nb_channels,
  178. av_get_sample_fmt_name(codecCtx_->sample_fmt),
  179. codecCtx_->thread_count);
  180. // 打开解码器
  181. int ret = avcodec_open2(codecCtx_.get(), codec_, nullptr);
  182. if (ret < 0) {
  183. AV_LOGGER_ERRORF("打开音频解码器失败: {} (错误码: {})",
  184. ffmpeg_utils::errorToString(ret), ret);
  185. // 详细错误分析
  186. if (ret == AVERROR(EINVAL)) {
  187. AV_LOGGER_ERROR("解码器参数无效 - 可能的原因:");
  188. AV_LOGGER_ERROR(" 1. 不支持的采样格式或参数组合");
  189. AV_LOGGER_ERROR(" 2. 采样率或声道数不支持");
  190. } else if (ret == AVERROR(ENOMEM)) {
  191. AV_LOGGER_ERROR("内存不足 - 无法分配解码器资源");
  192. }
  193. return static_cast<ErrorCode>(ret);
  194. }
  195. AV_LOGGER_INFOF("音频解码器打开成功: {}", audioParams_.codecName);
  196. return ErrorCode::SUCCESS;
  197. }
  198. ErrorCode AudioDecoder::setupDecoderParams() {
  199. // 设置线程数
  200. if (audioParams_.threadCount > 0) {
  201. codecCtx_->thread_count = audioParams_.threadCount;
  202. } else {
  203. codecCtx_->thread_count = std::thread::hardware_concurrency();
  204. }
  205. // 设置采样率(如果指定)
  206. if (audioParams_.sampleRate > 0) {
  207. codecCtx_->sample_rate = audioParams_.sampleRate;
  208. }
  209. // 设置声道数(如果指定)
  210. if (audioParams_.channels > 0) {
  211. av_channel_layout_default(&codecCtx_->ch_layout, audioParams_.channels);
  212. }
  213. // 设置采样格式(如果指定)
  214. if (audioParams_.sampleFormat != AV_SAMPLE_FMT_NONE) {
  215. codecCtx_->sample_fmt = audioParams_.sampleFormat;
  216. }
  217. // 低延迟设置
  218. if (audioParams_.lowLatency) {
  219. codecCtx_->flags |= AV_CODEC_FLAG_LOW_DELAY;
  220. codecCtx_->flags2 |= AV_CODEC_FLAG2_FAST;
  221. }
  222. // 针对特定解码器的优化设置
  223. if (audioParams_.codecName == "aac") {
  224. // AAC 特定设置
  225. av_opt_set(codecCtx_->priv_data, "dual_mono_mode", "stereo", 0);
  226. } else if (audioParams_.codecName == "mp3" || audioParams_.codecName == "mp3float") {
  227. // MP3 特定设置
  228. if (audioParams_.lowLatency) {
  229. av_opt_set_int(codecCtx_->priv_data, "skip_frame", 0, 0);
  230. }
  231. } else if (audioParams_.codecName == "opus") {
  232. // Opus 特定设置
  233. if (audioParams_.lowLatency) {
  234. av_opt_set_int(codecCtx_->priv_data, "apply_phase_inv", 0, 0);
  235. }
  236. }
  237. return ErrorCode::SUCCESS;
  238. }
  239. ErrorCode AudioDecoder::decodeFrame(const AVPacketPtr& packet, std::vector<AVFramePtr>& frames) {
  240. // 发送包到解码器
  241. int ret = avcodec_send_packet(codecCtx_.get(), packet ? packet.get() : nullptr);
  242. if (ret < 0 && ret != AVERROR_EOF && ret != AVERROR(EAGAIN)) {
  243. AV_LOGGER_ERRORF("发送包到音频解码器失败: {}", ffmpeg_utils::errorToString(ret));
  244. return static_cast<ErrorCode>(ret);
  245. }
  246. // AVERROR(EAGAIN) 表示解码器暂时无法接受更多输入,这是正常情况
  247. if (ret == AVERROR(EAGAIN)) {
  248. AV_LOGGER_DEBUGF("解码器暂时无法接受更多输入 (EAGAIN),继续接收帧");
  249. }
  250. // 接收解码后的帧
  251. return receiveFrames(frames);
  252. }
  253. ErrorCode AudioDecoder::receiveFrames(std::vector<AVFramePtr>& frames) {
  254. while (true) {
  255. AVFramePtr frame = makeAVFrame();
  256. if (!frame) {
  257. return ErrorCode::MEMORY_ALLOC_FAILED;
  258. }
  259. int ret = avcodec_receive_frame(codecCtx_.get(), frame.get());
  260. if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
  261. break; // 需要更多输入或已结束
  262. }
  263. if (ret < 0) {
  264. ErrorCode error = AbstractCodec::convertFFmpegError(ret);
  265. AV_LOGGER_ERRORF("接收音频解码帧失败: {} ({})",
  266. AbstractCodec::getErrorDescription(error),
  267. ffmpeg_utils::errorToString(ret));
  268. return error;
  269. }
  270. // 格式转换(如果需要)
  271. auto convertedFrame = convertFrame(std::move(frame));
  272. if (convertedFrame) {
  273. frames.push_back(std::move(convertedFrame));
  274. }
  275. }
  276. return ErrorCode::SUCCESS;
  277. }
  278. AVFramePtr AudioDecoder::convertFrame(AVFramePtr frame) {
  279. if (!frame) {
  280. return nullptr;
  281. }
  282. // 检查是否需要重采样
  283. bool needConvert = (frame->format != audioParams_.sampleFormat) ||
  284. (frame->sample_rate != audioParams_.sampleRate) ||
  285. (frame->ch_layout.nb_channels != audioParams_.channels);
  286. if (!needConvert) {
  287. return std::move(frame); // 格式已经匹配,直接返回
  288. }
  289. // 设置重采样器
  290. ErrorCode result = setupResampler(frame.get());
  291. if (result != ErrorCode::SUCCESS) {
  292. AV_LOGGER_ERROR("设置重采样器失败");
  293. return nullptr;
  294. }
  295. // 创建输出帧
  296. AVFramePtr outFrame = makeAVFrame();
  297. if (!outFrame) {
  298. return nullptr;
  299. }
  300. outFrame->format = audioParams_.sampleFormat;
  301. outFrame->sample_rate = audioParams_.sampleRate;
  302. av_channel_layout_default(&outFrame->ch_layout, audioParams_.channels);
  303. // 计算输出采样数
  304. int outSamples = swr_get_out_samples(swrCtx_, frame->nb_samples);
  305. outFrame->nb_samples = outSamples;
  306. // 分配输出缓冲区
  307. if (av_frame_get_buffer(outFrame.get(), 0) < 0) {
  308. AV_LOGGER_ERROR("分配音频输出缓冲区失败");
  309. return nullptr;
  310. }
  311. // 执行重采样
  312. int convertedSamples = swr_convert(swrCtx_,
  313. outFrame->data, outSamples,
  314. (const uint8_t**)frame->data, frame->nb_samples);
  315. if (convertedSamples < 0) {
  316. AV_LOGGER_ERRORF("音频重采样失败: {}", ffmpeg_utils::errorToString(convertedSamples));
  317. return nullptr;
  318. }
  319. outFrame->nb_samples = convertedSamples;
  320. // 复制时间戳等信息
  321. av_frame_copy_props(outFrame.get(), frame.get());
  322. return outFrame;
  323. }
  324. ErrorCode AudioDecoder::setupResampler(const AVFrame* inputFrame) {
  325. if (!inputFrame) {
  326. return ErrorCode::INVALID_PARAMS;
  327. }
  328. // 检查是否需要重新配置重采样器
  329. bool needReconfigure = !swrCtx_ ||
  330. !needResampling_ ||
  331. (inputFrame->format != codecCtx_->sample_fmt) ||
  332. (inputFrame->sample_rate != codecCtx_->sample_rate) ||
  333. (inputFrame->ch_layout.nb_channels != codecCtx_->ch_layout.nb_channels);
  334. if (!needReconfigure) {
  335. return ErrorCode::SUCCESS;
  336. }
  337. // 清理旧的重采样器
  338. cleanupResampler();
  339. // 创建新的重采样器
  340. swrCtx_ = swr_alloc();
  341. if (!swrCtx_) {
  342. AV_LOGGER_ERROR("分配重采样器失败");
  343. return ErrorCode::MEMORY_ALLOC_FAILED;
  344. }
  345. // 设置输入参数
  346. av_opt_set_chlayout(swrCtx_, "in_chlayout", &inputFrame->ch_layout, 0);
  347. av_opt_set_int(swrCtx_, "in_sample_rate", inputFrame->sample_rate, 0);
  348. av_opt_set_sample_fmt(swrCtx_, "in_sample_fmt", static_cast<AVSampleFormat>(inputFrame->format), 0);
  349. // 设置输出参数
  350. AVChannelLayout out_ch_layout;
  351. av_channel_layout_default(&out_ch_layout, audioParams_.channels);
  352. av_opt_set_chlayout(swrCtx_, "out_chlayout", &out_ch_layout, 0);
  353. av_opt_set_int(swrCtx_, "out_sample_rate", audioParams_.sampleRate, 0);
  354. av_opt_set_sample_fmt(swrCtx_, "out_sample_fmt", audioParams_.sampleFormat, 0);
  355. // 初始化重采样器
  356. int ret = swr_init(swrCtx_);
  357. if (ret < 0) {
  358. AV_LOGGER_ERRORF("初始化重采样器失败: {}", ffmpeg_utils::errorToString(ret));
  359. cleanupResampler();
  360. return static_cast<ErrorCode>(ret);
  361. }
  362. needResampling_ = true;
  363. AV_LOGGER_INFOF("重采样器配置成功: {}Hz,{}ch,{} -> {}Hz,{}ch,{}",
  364. inputFrame->sample_rate, inputFrame->ch_layout.nb_channels,
  365. av_get_sample_fmt_name(static_cast<AVSampleFormat>(inputFrame->format)),
  366. audioParams_.sampleRate, audioParams_.channels,
  367. av_get_sample_fmt_name(audioParams_.sampleFormat));
  368. return ErrorCode::SUCCESS;
  369. }
  370. void AudioDecoder::cleanupResampler() {
  371. if (swrCtx_) {
  372. swr_free(&swrCtx_);
  373. swrCtx_ = nullptr;
  374. }
  375. needResampling_ = false;
  376. }
  377. void AudioDecoder::updateStats(bool success, double decodeTime, size_t dataSize, int samples) {
  378. std::lock_guard<std::mutex> lock(statsMutex_);
  379. if (success) {
  380. stats_.decodedFrames++;
  381. stats_.totalSamples += samples;
  382. stats_.totalBytes += dataSize;
  383. stats_.totalDecodeTime += decodeTime;
  384. // 如果启用了重采样,更新重采样帧数
  385. if (isResamplingEnabled()) {
  386. stats_.resampledFrames++;
  387. }
  388. // 更新平均解码时间
  389. if (stats_.decodedFrames == 1) {
  390. stats_.avgDecodeTime = decodeTime;
  391. } else {
  392. stats_.avgDecodeTime = stats_.totalDecodeTime / stats_.decodedFrames;
  393. }
  394. } else {
  395. stats_.errorCount++;
  396. }
  397. }
  398. AudioDecoder::DecoderStats AudioDecoder::getStats() const {
  399. std::lock_guard<std::mutex> lock(statsMutex_);
  400. return stats_;
  401. }
  402. void AudioDecoder::resetStats() {
  403. std::lock_guard<std::mutex> lock(statsMutex_);
  404. stats_ = DecoderStats{};
  405. }
  406. std::string AudioDecoder::getDecoderName() const {
  407. return audioParams_.codecName;
  408. }
  409. bool AudioDecoder::isResamplingEnabled() const {
  410. return audioParams_.enableResampling && needResampling_;
  411. }
  412. std::vector<std::string> AudioDecoder::getSupportedDecoders() {
  413. std::call_once(decodersInitFlag_, findUsableDecoders);
  414. return supportedDecoders_;
  415. }
  416. bool AudioDecoder::isDecoderSupported(const std::string& codecName) {
  417. auto decoders = getSupportedDecoders();
  418. return std::find(decoders.begin(), decoders.end(), codecName) != decoders.end();
  419. }
  420. std::string AudioDecoder::getRecommendedDecoder(const std::string& codecName) {
  421. auto decoders = getSupportedDecoders();
  422. if (!codecName.empty()) {
  423. // 查找指定编解码格式的解码器
  424. if (std::find(decoders.begin(), decoders.end(), codecName) != decoders.end()) {
  425. return codecName;
  426. }
  427. // 查找相关的解码器
  428. for (const auto& decoder : decoders) {
  429. if (decoder.find(codecName) != std::string::npos) {
  430. return decoder;
  431. }
  432. }
  433. }
  434. // 返回默认推荐的解码器
  435. const char* preferredDecoders[] = {"aac", "mp3", "opus", "vorbis", "flac"};
  436. for (const char* preferred : preferredDecoders) {
  437. if (std::find(decoders.begin(), decoders.end(), preferred) != decoders.end()) {
  438. return preferred;
  439. }
  440. }
  441. return decoders.empty() ? "" : decoders[0];
  442. }
  443. void AudioDecoder::findUsableDecoders() {
  444. AV_LOGGER_INFO("查找可用的音频解码器...");
  445. // 测试所有音频解码器
  446. for (const char* decoder : AUDIO_DECODERS) {
  447. if (decoder && CodecFactory::isCodecSupported(decoder, CodecType::DECODER, MediaType::AUDIO)) {
  448. supportedDecoders_.emplace_back(decoder);
  449. AV_LOGGER_INFOF("找到音频解码器: {}", decoder);
  450. }
  451. }
  452. AV_LOGGER_INFOF("总共找到 {} 个可用的音频解码器", supportedDecoders_.size());
  453. }
  454. // AudioDecoderFactory 实现
  455. std::unique_ptr<AudioDecoder> AudioDecoder::AudioDecoderFactory::create(const std::string& codecName) {
  456. auto decoder = std::make_unique<AudioDecoder>();
  457. if (!codecName.empty()) {
  458. if (!CodecFactory::isCodecSupported(codecName, CodecType::DECODER, MediaType::AUDIO)) {
  459. AV_LOGGER_ERRORF("不支持的音频解码器: {}", codecName);
  460. return nullptr;
  461. }
  462. }
  463. return decoder;
  464. }
  465. std::unique_ptr<AudioDecoder> AudioDecoder::AudioDecoderFactory::createBest() {
  466. std::string codecName = AudioDecoder::getRecommendedDecoder();
  467. if (codecName.empty()) {
  468. AV_LOGGER_ERROR("未找到可用的音频解码器");
  469. return nullptr;
  470. }
  471. return create(codecName);
  472. }
  473. } // namespace codec
  474. } // namespace av