| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- #include <chrono>
- #include <string>
- #include <thread>
- #include <iomanip>
- #include "code/base/logger.h"
- #include "code/player/player_core_v2.h"
- #include <QApplication>
- #include <QAudioDeviceInfo>
- #include <QAudioOutput>
- #include <QAudioFormat>
- #include <QDebug>
- using namespace av::player;
- using namespace av::utils;
- // 增强的事件回调类,包含更详细的调试信息
- class DebugPlayerCallback : public PlayerEventCallback {
- public:
- void onStateChanged(PlayerState newState) override {
- std::string stateStr;
- switch (newState) {
- case PlayerState::Idle: stateStr = "Idle"; break;
- case PlayerState::Opening: stateStr = "Opening"; break;
- case PlayerState::Stopped: stateStr = "Stopped"; break;
- case PlayerState::Playing: stateStr = "Playing"; break;
- case PlayerState::Paused: stateStr = "Paused"; break;
- case PlayerState::Seeking: stateStr = "Seeking"; break;
- case PlayerState::Error: stateStr = "Error"; break;
- }
- Logger::instance().info("[EVENT] State changed to: " + stateStr);
- }
-
- void onPositionChanged(int64_t position) override {
- static auto lastUpdate = std::chrono::steady_clock::now();
- auto now = std::chrono::steady_clock::now();
- if (std::chrono::duration_cast<std::chrono::seconds>(now - lastUpdate).count() >= 1) {
- double seconds = position / 1000000.0;
- Logger::instance().debug("[EVENT] Position: " + std::to_string(seconds) + "s");
- lastUpdate = now;
- }
- }
-
- void onMediaInfoChanged(const MediaInfo& info) override {
- Logger::instance().info("[EVENT] Media info changed:");
- Logger::instance().info(" File: " + info.filename);
- Logger::instance().info(" Duration: " + std::to_string(info.duration / 1000000.0) + "s");
- Logger::instance().info(" Has Video: " + std::string(info.hasVideo ? "Yes" : "No"));
- Logger::instance().info(" Has Audio: " + std::string(info.hasAudio ? "Yes" : "No"));
-
- if (info.hasAudio) {
- Logger::instance().info(" Audio: " + std::to_string(info.sampleRate) + " Hz, " + std::to_string(info.channels) + " channels");
- }
- }
-
- void onErrorOccurred(const std::string& error) override {
- Logger::instance().error("[ERROR] " + error);
- }
-
- void onFrameDropped(int64_t totalDropped) override {
- Logger::instance().warningf("[WARNING] Frame dropped, total: "
- + std::to_string(totalDropped));
- }
-
- void onSyncError(double error, const std::string& reason) override {
- Logger::instance().warningf("[WARNING] Sync error: " + std::to_string(error * 1000)
- + "ms, reason: " + reason);
- }
- void onEndOfFile() override {
- Logger::instance().info("[EVENT] End of file reached");
- }
- };
- // 检查系统音频设备
- void checkAudioDevices() {
- Logger::instance().info("\n=== 音频设备检查 ===");
-
- // 获取默认输出设备
- QAudioDeviceInfo defaultDevice = QAudioDeviceInfo::defaultOutputDevice();
- Logger::instance().info("默认音频输出设备: " + defaultDevice.deviceName().toStdString());
-
- // 列出所有可用的音频输出设备
- QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
- Logger::instance().info("可用音频输出设备数量: " + std::to_string(devices.size()));
-
- for (int i = 0; i < devices.size(); ++i) {
- const QAudioDeviceInfo& device = devices[i];
- Logger::instance().info(" 设备 " + std::to_string(i + 1) + ": " + device.deviceName().toStdString());
-
- // 检查支持的采样率
- QList<int> sampleRates = device.supportedSampleRates();
- std::string ratesStr = " 支持的采样率: ";
- for (int rate : sampleRates) {
- ratesStr += std::to_string(rate) + " ";
- }
- Logger::instance().info(ratesStr);
-
- // 检查支持的通道数
- QList<int> channels = device.supportedChannelCounts();
- std::string channelsStr = " 支持的通道数: ";
- for (int ch : channels) {
- channelsStr += std::to_string(ch) + " ";
- }
- Logger::instance().info(channelsStr);
- }
- }
- // 测试Qt音频输出
- void testQtAudioOutput() {
- Logger::instance().info("\n=== Qt音频输出测试 ===");
-
- // 设置音频格式
- QAudioFormat format;
- format.setSampleRate(44100);
- format.setChannelCount(2);
- format.setSampleSize(16);
- format.setCodec("audio/pcm");
- format.setByteOrder(QAudioFormat::LittleEndian);
- format.setSampleType(QAudioFormat::SignedInt);
-
- // 检查默认设备是否支持该格式
- QAudioDeviceInfo deviceInfo = QAudioDeviceInfo::defaultOutputDevice();
- if (!deviceInfo.isFormatSupported(format)) {
- Logger::instance().warningf("警告: 默认设备不支持指定的音频格式");
- format = deviceInfo.nearestFormat(format);
- Logger::instance().info("使用最接近的格式: " + std::to_string(format.sampleRate()) + "Hz, "
- + std::to_string(format.channelCount()) + "ch, " + std::to_string(format.sampleSize()) + "bit");
- } else {
- Logger::instance().info("默认设备支持指定的音频格式");
- }
-
- // 创建音频输出
- QAudioOutput* audioOutput = new QAudioOutput(format);
- if (!audioOutput) {
- Logger::instance().error("错误: 无法创建QAudioOutput");
- return;
- }
-
- Logger::instance().info("QAudioOutput创建成功");
- Logger::instance().info("缓冲区大小: " + std::to_string(audioOutput->bufferSize()) + " bytes");
- Logger::instance().info("音量: " + std::to_string(audioOutput->volume()));
-
- // 尝试启动音频设备
- QIODevice* device = audioOutput->start();
- if (!device) {
- Logger::instance().error("错误: 无法启动音频设备");
- delete audioOutput;
- return;
- }
-
- Logger::instance().info("音频设备启动成功");
-
- // 生成并播放测试音调(440Hz正弦波)
- const int sampleRate = format.sampleRate();
- const int channels = format.channelCount();
- const double frequency = 440.0; // A4音符
- const double duration = 2.0; // 2秒
- const int totalSamples = static_cast<int>(sampleRate * duration);
-
- QByteArray testData;
- testData.resize(totalSamples * channels * sizeof(int16_t));
- int16_t* samples = reinterpret_cast<int16_t*>(testData.data());
-
- for (int i = 0; i < totalSamples; ++i) {
- double time = static_cast<double>(i) / sampleRate;
- int16_t sample = static_cast<int16_t>(16383 * std::sin(2.0 * M_PI * frequency * time));
-
- for (int ch = 0; ch < channels; ++ch) {
- samples[i * channels + ch] = sample;
- }
- }
-
- Logger::instance().info("播放测试音调 (440Hz, 2秒)...");
-
- // 分块写入音频数据
- const int chunkSize = 4096;
- int bytesWritten = 0;
-
- while (bytesWritten < testData.size()) {
- int remainingBytes = testData.size() - bytesWritten;
- int writeSize = std::min(chunkSize, remainingBytes);
-
- qint64 written = device->write(testData.data() + bytesWritten, writeSize);
- if (written > 0) {
- bytesWritten += written;
- }
-
- // 等待一小段时间
- std::this_thread::sleep_for(std::chrono::milliseconds(50));
- }
-
- Logger::instance().info("测试音调播放完成");
-
- // 等待播放完成
- std::this_thread::sleep_for(std::chrono::milliseconds(500));
-
- audioOutput->stop();
- delete audioOutput;
- }
- int main(int argc, char* argv[]) {
- // 创建QApplication实例(Qt音频需要)
- QApplication app(argc, argv);
- Logger::instance().initialize("test.log", LogLevel::DEBUG, false, true);
- // 初始化日志系统
- Logger::instance().setLevel(LogLevel::DEBUG);
- Logger::instance().info("Enhanced Audio Debug Test Started");
- try {
- // 检查音频设备
- checkAudioDevices();
-
- // 测试Qt音频输出
- // testQtAudioOutput();
- Logger::instance().info("\n=== PlayerCoreV2音频测试 ===");
- // 创建同步配置
- SyncConfigV2 syncConfig;
- syncConfig.syncStrategy = SyncStrategy::ADAPTIVE;
- syncConfig.audioSyncThreshold = 0.040;
- syncConfig.videoSyncThreshold = 0.020;
- syncConfig.maxSyncError = 0.200;
- syncConfig.clockUpdateInterval = 10;
- syncConfig.smoothingWindow = 10;
- syncConfig.enableAdaptiveSync = true;
- syncConfig.enableFrameDrop = true;
- syncConfig.enableFrameDuplicate = true;
- syncConfig.enablePrediction = true;
- syncConfig.enableErrorRecovery = true;
-
- // 创建播放器实例
- auto player = std::make_unique<PlayerCoreV2>(syncConfig);
-
- // 创建事件回调
- auto callback = std::make_unique<DebugPlayerCallback>();
- player->setEventCallback(callback.get());
-
- // 测试音频文件路径
- std::string audioFile = "C:\\Windows\\Media\\notify.wav";
- Logger::instance().info("测试音频文件: " + audioFile);
- // 打开音频文件
- auto result = player->openFile(audioFile);
- if (result != ErrorCode::SUCCESS) {
- Logger::instance().error("无法打开音频文件: " + std::to_string(static_cast<int>(result)));
-
- // 尝试其他文件
- audioFile = "C:\\Windows\\Media\\chimes.wav";
- Logger::instance().info("尝试备用文件: " + audioFile);
- result = player->openFile(audioFile);
-
- if (result != ErrorCode::SUCCESS) {
- Logger::instance().error("无法打开备用音频文件: " + std::to_string(static_cast<int>(result)));
- return 1;
- }
- }
-
- Logger::instance().info("音频文件打开成功!");
-
- // 获取媒体信息
- auto mediaInfo = player->getMediaInfo();
- Logger::instance().info("媒体时长: " + std::to_string(mediaInfo.duration / 1000000.0) + " 秒");
- Logger::instance().info("包含音频: " + std::string(mediaInfo.hasAudio ? "是" : "否"));
-
- if (!mediaInfo.hasAudio) {
- Logger::instance().error("文件中未找到音频流!");
- return 1;
- }
-
- // 设置音量为最大
- player->setVolume(1.0);
- Logger::instance().info("音量设置为: " + std::to_string(player->getVolume()));
-
- // 开始播放
- result = player->play();
- if (result != ErrorCode::SUCCESS) {
- Logger::instance().error("播放启动失败: " + std::to_string(static_cast<int>(result)));
- return 1;
- }
-
- Logger::instance().info("播放已开始! 现在应该能听到声音了.");
- Logger::instance().info("当前音量: " + std::to_string(player->getVolume()));
-
- // 等待播放完成
- double totalDuration = mediaInfo.duration / 1000000.0;
- Logger::instance().info("等待播放完成 (" + std::to_string(totalDuration) + " 秒)...");
-
- // 监控播放状态 - 让播放器自然结束
- auto startTime = std::chrono::steady_clock::now();
- while (true) {
- auto currentTime = std::chrono::steady_clock::now();
- auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(currentTime - startTime).count();
-
- auto state = player->getState();
- auto currentPos = player->getCurrentTime() / 1000000.0;
-
- Logger::instance().debug("状态: " + std::to_string(static_cast<int>(state)) + ", 位置: " + std::to_string(currentPos) + "s");
-
- // 如果播放完成或出错,退出
- if (state == PlayerState::Stopped || state == PlayerState::Error) {
- Logger::instance().info("播放器自然停止,状态: " + std::to_string(static_cast<int>(state)));
- break;
- }
-
- // 超时保护 - 增加更长的超时时间
- if (elapsed > totalDuration + 10) {
- Logger::instance().warningf("超时保护触发,停止播放...");
- player->stop();
- break;
- }
-
- std::this_thread::sleep_for(std::chrono::milliseconds(500));
- }
-
- Logger::instance().info("音频测试完成.");
- } catch (const std::exception& e) {
- Logger::instance().error("异常: " + std::string(e.what()));
- return 1;
- } catch (...) {
- Logger::instance().error("发生未知异常");
- return 1;
- }
- return 0;
- }
|