test_audio_debug.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. #include <chrono>
  2. #include <string>
  3. #include <thread>
  4. #include <iomanip>
  5. #include "code/base/logger.h"
  6. #include "code/player/player_core_v2.h"
  7. #include <QApplication>
  8. #include <QAudioDeviceInfo>
  9. #include <QAudioOutput>
  10. #include <QAudioFormat>
  11. #include <QDebug>
  12. using namespace av::player;
  13. using namespace av::utils;
  14. // 增强的事件回调类,包含更详细的调试信息
  15. class DebugPlayerCallback : public PlayerEventCallback {
  16. public:
  17. void onStateChanged(PlayerState newState) override {
  18. std::string stateStr;
  19. switch (newState) {
  20. case PlayerState::Idle: stateStr = "Idle"; break;
  21. case PlayerState::Opening: stateStr = "Opening"; break;
  22. case PlayerState::Stopped: stateStr = "Stopped"; break;
  23. case PlayerState::Playing: stateStr = "Playing"; break;
  24. case PlayerState::Paused: stateStr = "Paused"; break;
  25. case PlayerState::Seeking: stateStr = "Seeking"; break;
  26. case PlayerState::Error: stateStr = "Error"; break;
  27. }
  28. Logger::instance().info("[EVENT] State changed to: " + stateStr);
  29. }
  30. void onPositionChanged(int64_t position) override {
  31. static auto lastUpdate = std::chrono::steady_clock::now();
  32. auto now = std::chrono::steady_clock::now();
  33. if (std::chrono::duration_cast<std::chrono::seconds>(now - lastUpdate).count() >= 1) {
  34. double seconds = position / 1000000.0;
  35. Logger::instance().debug("[EVENT] Position: " + std::to_string(seconds) + "s");
  36. lastUpdate = now;
  37. }
  38. }
  39. void onMediaInfoChanged(const MediaInfo& info) override {
  40. Logger::instance().info("[EVENT] Media info changed:");
  41. Logger::instance().info(" File: " + info.filename);
  42. Logger::instance().info(" Duration: " + std::to_string(info.duration / 1000000.0) + "s");
  43. Logger::instance().info(" Has Video: " + std::string(info.hasVideo ? "Yes" : "No"));
  44. Logger::instance().info(" Has Audio: " + std::string(info.hasAudio ? "Yes" : "No"));
  45. if (info.hasAudio) {
  46. Logger::instance().info(" Audio: " + std::to_string(info.sampleRate) + " Hz, " + std::to_string(info.channels) + " channels");
  47. }
  48. }
  49. void onErrorOccurred(const std::string& error) override {
  50. Logger::instance().error("[ERROR] " + error);
  51. }
  52. void onFrameDropped(int64_t totalDropped) override {
  53. Logger::instance().warningf("[WARNING] Frame dropped, total: "
  54. + std::to_string(totalDropped));
  55. }
  56. void onSyncError(double error, const std::string& reason) override {
  57. Logger::instance().warningf("[WARNING] Sync error: " + std::to_string(error * 1000)
  58. + "ms, reason: " + reason);
  59. }
  60. void onEndOfFile() override {
  61. Logger::instance().info("[EVENT] End of file reached");
  62. }
  63. };
  64. // 检查系统音频设备
  65. void checkAudioDevices() {
  66. Logger::instance().info("\n=== 音频设备检查 ===");
  67. // 获取默认输出设备
  68. QAudioDeviceInfo defaultDevice = QAudioDeviceInfo::defaultOutputDevice();
  69. Logger::instance().info("默认音频输出设备: " + defaultDevice.deviceName().toStdString());
  70. // 列出所有可用的音频输出设备
  71. QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
  72. Logger::instance().info("可用音频输出设备数量: " + std::to_string(devices.size()));
  73. for (int i = 0; i < devices.size(); ++i) {
  74. const QAudioDeviceInfo& device = devices[i];
  75. Logger::instance().info(" 设备 " + std::to_string(i + 1) + ": " + device.deviceName().toStdString());
  76. // 检查支持的采样率
  77. QList<int> sampleRates = device.supportedSampleRates();
  78. std::string ratesStr = " 支持的采样率: ";
  79. for (int rate : sampleRates) {
  80. ratesStr += std::to_string(rate) + " ";
  81. }
  82. Logger::instance().info(ratesStr);
  83. // 检查支持的通道数
  84. QList<int> channels = device.supportedChannelCounts();
  85. std::string channelsStr = " 支持的通道数: ";
  86. for (int ch : channels) {
  87. channelsStr += std::to_string(ch) + " ";
  88. }
  89. Logger::instance().info(channelsStr);
  90. }
  91. }
  92. // 测试Qt音频输出
  93. void testQtAudioOutput() {
  94. Logger::instance().info("\n=== Qt音频输出测试 ===");
  95. // 设置音频格式
  96. QAudioFormat format;
  97. format.setSampleRate(44100);
  98. format.setChannelCount(2);
  99. format.setSampleSize(16);
  100. format.setCodec("audio/pcm");
  101. format.setByteOrder(QAudioFormat::LittleEndian);
  102. format.setSampleType(QAudioFormat::SignedInt);
  103. // 检查默认设备是否支持该格式
  104. QAudioDeviceInfo deviceInfo = QAudioDeviceInfo::defaultOutputDevice();
  105. if (!deviceInfo.isFormatSupported(format)) {
  106. Logger::instance().warningf("警告: 默认设备不支持指定的音频格式");
  107. format = deviceInfo.nearestFormat(format);
  108. Logger::instance().info("使用最接近的格式: " + std::to_string(format.sampleRate()) + "Hz, "
  109. + std::to_string(format.channelCount()) + "ch, " + std::to_string(format.sampleSize()) + "bit");
  110. } else {
  111. Logger::instance().info("默认设备支持指定的音频格式");
  112. }
  113. // 创建音频输出
  114. QAudioOutput* audioOutput = new QAudioOutput(format);
  115. if (!audioOutput) {
  116. Logger::instance().error("错误: 无法创建QAudioOutput");
  117. return;
  118. }
  119. Logger::instance().info("QAudioOutput创建成功");
  120. Logger::instance().info("缓冲区大小: " + std::to_string(audioOutput->bufferSize()) + " bytes");
  121. Logger::instance().info("音量: " + std::to_string(audioOutput->volume()));
  122. // 尝试启动音频设备
  123. QIODevice* device = audioOutput->start();
  124. if (!device) {
  125. Logger::instance().error("错误: 无法启动音频设备");
  126. delete audioOutput;
  127. return;
  128. }
  129. Logger::instance().info("音频设备启动成功");
  130. // 生成并播放测试音调(440Hz正弦波)
  131. const int sampleRate = format.sampleRate();
  132. const int channels = format.channelCount();
  133. const double frequency = 440.0; // A4音符
  134. const double duration = 2.0; // 2秒
  135. const int totalSamples = static_cast<int>(sampleRate * duration);
  136. QByteArray testData;
  137. testData.resize(totalSamples * channels * sizeof(int16_t));
  138. int16_t* samples = reinterpret_cast<int16_t*>(testData.data());
  139. for (int i = 0; i < totalSamples; ++i) {
  140. double time = static_cast<double>(i) / sampleRate;
  141. int16_t sample = static_cast<int16_t>(16383 * std::sin(2.0 * M_PI * frequency * time));
  142. for (int ch = 0; ch < channels; ++ch) {
  143. samples[i * channels + ch] = sample;
  144. }
  145. }
  146. Logger::instance().info("播放测试音调 (440Hz, 2秒)...");
  147. // 分块写入音频数据
  148. const int chunkSize = 4096;
  149. int bytesWritten = 0;
  150. while (bytesWritten < testData.size()) {
  151. int remainingBytes = testData.size() - bytesWritten;
  152. int writeSize = std::min(chunkSize, remainingBytes);
  153. qint64 written = device->write(testData.data() + bytesWritten, writeSize);
  154. if (written > 0) {
  155. bytesWritten += written;
  156. }
  157. // 等待一小段时间
  158. std::this_thread::sleep_for(std::chrono::milliseconds(50));
  159. }
  160. Logger::instance().info("测试音调播放完成");
  161. // 等待播放完成
  162. std::this_thread::sleep_for(std::chrono::milliseconds(500));
  163. audioOutput->stop();
  164. delete audioOutput;
  165. }
  166. int main(int argc, char* argv[]) {
  167. // 创建QApplication实例(Qt音频需要)
  168. QApplication app(argc, argv);
  169. Logger::instance().initialize("test.log", LogLevel::DEBUG, false, true);
  170. // 初始化日志系统
  171. Logger::instance().setLevel(LogLevel::DEBUG);
  172. Logger::instance().info("Enhanced Audio Debug Test Started");
  173. try {
  174. // 检查音频设备
  175. checkAudioDevices();
  176. // 测试Qt音频输出
  177. // testQtAudioOutput();
  178. Logger::instance().info("\n=== PlayerCoreV2音频测试 ===");
  179. // 创建同步配置
  180. SyncConfigV2 syncConfig;
  181. syncConfig.syncStrategy = SyncStrategy::ADAPTIVE;
  182. syncConfig.audioSyncThreshold = 0.040;
  183. syncConfig.videoSyncThreshold = 0.020;
  184. syncConfig.maxSyncError = 0.200;
  185. syncConfig.clockUpdateInterval = 10;
  186. syncConfig.smoothingWindow = 10;
  187. syncConfig.enableAdaptiveSync = true;
  188. syncConfig.enableFrameDrop = true;
  189. syncConfig.enableFrameDuplicate = true;
  190. syncConfig.enablePrediction = true;
  191. syncConfig.enableErrorRecovery = true;
  192. // 创建播放器实例
  193. auto player = std::make_unique<PlayerCoreV2>(syncConfig);
  194. // 创建事件回调
  195. auto callback = std::make_unique<DebugPlayerCallback>();
  196. player->setEventCallback(callback.get());
  197. // 测试音频文件路径
  198. std::string audioFile = "C:\\Windows\\Media\\notify.wav";
  199. Logger::instance().info("测试音频文件: " + audioFile);
  200. // 打开音频文件
  201. auto result = player->openFile(audioFile);
  202. if (result != ErrorCode::SUCCESS) {
  203. Logger::instance().error("无法打开音频文件: " + std::to_string(static_cast<int>(result)));
  204. // 尝试其他文件
  205. audioFile = "C:\\Windows\\Media\\chimes.wav";
  206. Logger::instance().info("尝试备用文件: " + audioFile);
  207. result = player->openFile(audioFile);
  208. if (result != ErrorCode::SUCCESS) {
  209. Logger::instance().error("无法打开备用音频文件: " + std::to_string(static_cast<int>(result)));
  210. return 1;
  211. }
  212. }
  213. Logger::instance().info("音频文件打开成功!");
  214. // 获取媒体信息
  215. auto mediaInfo = player->getMediaInfo();
  216. Logger::instance().info("媒体时长: " + std::to_string(mediaInfo.duration / 1000000.0) + " 秒");
  217. Logger::instance().info("包含音频: " + std::string(mediaInfo.hasAudio ? "是" : "否"));
  218. if (!mediaInfo.hasAudio) {
  219. Logger::instance().error("文件中未找到音频流!");
  220. return 1;
  221. }
  222. // 设置音量为最大
  223. player->setVolume(1.0);
  224. Logger::instance().info("音量设置为: " + std::to_string(player->getVolume()));
  225. // 开始播放
  226. result = player->play();
  227. if (result != ErrorCode::SUCCESS) {
  228. Logger::instance().error("播放启动失败: " + std::to_string(static_cast<int>(result)));
  229. return 1;
  230. }
  231. Logger::instance().info("播放已开始! 现在应该能听到声音了.");
  232. Logger::instance().info("当前音量: " + std::to_string(player->getVolume()));
  233. // 等待播放完成
  234. double totalDuration = mediaInfo.duration / 1000000.0;
  235. Logger::instance().info("等待播放完成 (" + std::to_string(totalDuration) + " 秒)...");
  236. // 监控播放状态 - 让播放器自然结束
  237. auto startTime = std::chrono::steady_clock::now();
  238. while (true) {
  239. auto currentTime = std::chrono::steady_clock::now();
  240. auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(currentTime - startTime).count();
  241. auto state = player->getState();
  242. auto currentPos = player->getCurrentTime() / 1000000.0;
  243. Logger::instance().debug("状态: " + std::to_string(static_cast<int>(state)) + ", 位置: " + std::to_string(currentPos) + "s");
  244. // 如果播放完成或出错,退出
  245. if (state == PlayerState::Stopped || state == PlayerState::Error) {
  246. Logger::instance().info("播放器自然停止,状态: " + std::to_string(static_cast<int>(state)));
  247. break;
  248. }
  249. // 超时保护 - 增加更长的超时时间
  250. if (elapsed > totalDuration + 10) {
  251. Logger::instance().warningf("超时保护触发,停止播放...");
  252. player->stop();
  253. break;
  254. }
  255. std::this_thread::sleep_for(std::chrono::milliseconds(500));
  256. }
  257. Logger::instance().info("音频测试完成.");
  258. } catch (const std::exception& e) {
  259. Logger::instance().error("异常: " + std::string(e.what()));
  260. return 1;
  261. } catch (...) {
  262. Logger::instance().error("发生未知异常");
  263. return 1;
  264. }
  265. return 0;
  266. }