#include "../player/player_core_v2.h" #include "../base/logger.h" #include #include #include #include using namespace av::player; using namespace av::utils; // 示例事件回调类 class ExamplePlayerCallback : 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; } std::cout << "[EVENT] State changed to: " << stateStr << std::endl; } 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(now - lastUpdate).count() >= 1) { double seconds = position / 1000000.0; std::cout << "[EVENT] Position: " << std::fixed << std::setprecision(2) << seconds << "s" << std::endl; lastUpdate = now; } } void onMediaInfoChanged(const MediaInfo& info) override { std::cout << "[EVENT] Media info changed:" << std::endl; std::cout << " File: " << info.filename << std::endl; std::cout << " Duration: " << (info.duration / 1000000.0) << "s" << std::endl; std::cout << " Has Video: " << (info.hasVideo ? "Yes" : "No") << std::endl; std::cout << " Has Audio: " << (info.hasAudio ? "Yes" : "No") << std::endl; if (info.hasVideo) { std::cout << " Video: " << info.width << "x" << info.height << " @ " << info.fps << " fps" << std::endl; } if (info.hasAudio) { std::cout << " Audio: " << info.sampleRate << " Hz, " << info.channels << " channels" << std::endl; } } void onErrorOccurred(const std::string& error) override { std::cout << "[ERROR] " << error << std::endl; } void onFrameDropped(int64_t totalDropped) override { std::cout << "[WARNING] Frame dropped, total: " << totalDropped << std::endl; } void onSyncError(double error, const std::string& reason) override { std::cout << "[WARNING] Sync error: " << (error * 1000) << "ms, reason: " << reason << std::endl; } }; // 简单的命令行界面 class SimplePlayerUI { public: SimplePlayerUI(PlayerCoreV2* player) : m_player(player), m_running(true) {} void run() { std::cout << "\n=== PlayerCoreV2 Example ===" << std::endl; std::cout << "Commands:" << std::endl; std::cout << " open - Open media file" << std::endl; std::cout << " play - Start playback" << std::endl; std::cout << " pause - Pause playback" << std::endl; std::cout << " stop - Stop playback" << std::endl; std::cout << " seek - Seek to position" << std::endl; std::cout << " speed - Set playback speed (0.5-4.0)" << std::endl; std::cout << " volume - Set volume (0.0-1.0)" << std::endl; std::cout << " stats - Show playback statistics" << std::endl; std::cout << " debug - Show debug information" << std::endl; std::cout << " config - Show sync configuration" << std::endl; std::cout << " quit - Exit program" << std::endl; std::cout << "============================\n" << std::endl; std::string line; while (m_running && std::getline(std::cin, line)) { processCommand(line); } } private: void processCommand(const std::string& line) { std::istringstream iss(line); std::string command; iss >> command; if (command == "open") { std::string filename; iss >> filename; if (!filename.empty()) { auto result = m_player->openFile(filename); if (result == ErrorCode::SUCCESS) { std::cout << "File opened successfully" << std::endl; } else { std::cout << "Failed to open file: " << static_cast(result) << std::endl; } } else { std::cout << "Usage: open " << std::endl; } } else if (command == "play") { auto result = m_player->play(); if (result == ErrorCode::SUCCESS) { std::cout << "Playback started" << std::endl; } else { std::cout << "Failed to start playback: " << static_cast(result) << std::endl; } } else if (command == "pause") { auto result = m_player->pause(); if (result == ErrorCode::SUCCESS) { std::cout << "Playback paused" << std::endl; } else { std::cout << "Failed to pause playback: " << static_cast(result) << std::endl; } } else if (command == "stop") { auto result = m_player->stop(); if (result == ErrorCode::SUCCESS) { std::cout << "Playback stopped" << std::endl; } else { std::cout << "Failed to stop playback: " << static_cast(result) << std::endl; } } else if (command == "seek") { double seconds; iss >> seconds; if (iss) { int64_t timestamp = static_cast(seconds * 1000000); // 转换为微秒 auto result = m_player->seek(timestamp); if (result == ErrorCode::SUCCESS) { std::cout << "Seeking to " << seconds << "s" << std::endl; } else { std::cout << "Failed to seek: " << static_cast(result) << std::endl; } } else { std::cout << "Usage: seek " << std::endl; } } else if (command == "speed") { double speed; iss >> speed; if (iss) { auto result = m_player->setPlaybackSpeed(speed); if (result == ErrorCode::SUCCESS) { std::cout << "Playback speed set to " << speed << "x" << std::endl; } else { std::cout << "Failed to set playback speed: " << static_cast(result) << std::endl; } } else { std::cout << "Usage: speed " << std::endl; } } else if (command == "volume") { double volume; iss >> volume; if (iss) { m_player->setVolume(volume); std::cout << "Volume set to " << volume << std::endl; } else { std::cout << "Usage: volume " << std::endl; } } else if (command == "stats") { showStats(); } else if (command == "debug") { std::cout << m_player->getDebugInfo() << std::endl; } else if (command == "config") { showSyncConfig(); } else if (command == "quit" || command == "exit") { m_running = false; std::cout << "Exiting..." << std::endl; } else if (!command.empty()) { std::cout << "Unknown command: " << command << std::endl; } } void showStats() { auto stats = m_player->getStats(); std::cout << "\n=== Playback Statistics ===" << std::endl; std::cout << "Current Time: " << std::fixed << std::setprecision(2) << (stats.currentTime / 1000000.0) << "s" << std::endl; std::cout << "Playback Speed: " << stats.playbackSpeed << "x" << std::endl; std::cout << "Total Frames: " << stats.totalFrames << std::endl; std::cout << "Dropped Frames: " << stats.droppedFrames << std::endl; std::cout << "Duplicated Frames: " << stats.duplicatedFrames << std::endl; std::cout << "Sync Error: " << std::fixed << std::setprecision(1) << (stats.syncError * 1000) << "ms" << std::endl; std::cout << "Avg Sync Error: " << std::fixed << std::setprecision(1) << (stats.avgSyncError * 1000) << "ms" << std::endl; std::cout << "Max Sync Error: " << std::fixed << std::setprecision(1) << (stats.maxSyncError * 1000) << "ms" << std::endl; std::cout << "CPU Usage: " << std::fixed << std::setprecision(1) << stats.cpuUsage << "%" << std::endl; std::cout << "Memory Usage: " << std::fixed << std::setprecision(1) << stats.memoryUsage << "MB" << std::endl; std::cout << "Queued Packets: " << stats.queuedPackets << std::endl; std::cout << "Queued Video Frames: " << stats.queuedVideoFrames << std::endl; std::cout << "Queued Audio Frames: " << stats.queuedAudioFrames << std::endl; std::cout << "Bitrate: " << std::fixed << std::setprecision(1) << stats.bitrate << " kbps" << std::endl; std::cout << "===========================\n" << std::endl; } void showSyncConfig() { auto config = m_player->getSyncConfig(); std::cout << "\n=== Sync Configuration ===" << std::endl; std::cout << "Sync Strategy: " << static_cast(config.syncStrategy) << std::endl; std::cout << "Audio Sync Threshold: " << (config.audioSyncThreshold * 1000) << "ms" << std::endl; std::cout << "Video Sync Threshold: " << (config.videoSyncThreshold * 1000) << "ms" << std::endl; std::cout << "Max Sync Error: " << (config.maxSyncError * 1000) << "ms" << std::endl; std::cout << "Clock Update Interval: " << config.clockUpdateInterval << "ms" << std::endl; std::cout << "Smoothing Window: " << config.smoothingWindow << std::endl; std::cout << "Adaptive Sync: " << (config.enableAdaptiveSync ? "Enabled" : "Disabled") << std::endl; std::cout << "Frame Drop: " << (config.enableFrameDrop ? "Enabled" : "Disabled") << std::endl; std::cout << "Frame Duplicate: " << (config.enableFrameDuplicate ? "Enabled" : "Disabled") << std::endl; std::cout << "Prediction: " << (config.enablePrediction ? "Enabled" : "Disabled") << std::endl; std::cout << "==========================\n" << std::endl; } PlayerCoreV2* m_player; bool m_running; }; int main(int argc, char* argv[]) { // 初始化日志系统 Logger::instance().setLevel(LogLevel::INFO); Logger::instance().info("PlayerCoreV2 Example Started"); try { // 创建同步配置 SyncConfigV2 syncConfig; syncConfig.syncStrategy = SyncStrategy::ADAPTIVE; // 使用自适应同步策略 syncConfig.audioSyncThreshold = 0.040; // 40ms syncConfig.videoSyncThreshold = 0.020; // 20ms syncConfig.maxSyncError = 0.200; // 200ms syncConfig.clockUpdateInterval = 10; // 10ms syncConfig.smoothingWindow = 10; // 10个样本 syncConfig.enableAdaptiveSync = true; syncConfig.enableFrameDrop = true; syncConfig.enableFrameDuplicate = true; syncConfig.enablePrediction = true; syncConfig.enableErrorRecovery = true; // 创建播放器实例 auto player = std::make_unique(syncConfig); // 创建事件回调 auto callback = std::make_unique(); player->setEventCallback(callback.get()); // 如果命令行提供了文件名,自动打开 if (argc > 1) { std::string filename = argv[1]; std::cout << "Opening file: " << filename << std::endl; auto result = player->openFile(filename); if (result == ErrorCode::SUCCESS) { std::cout << "File opened successfully" << std::endl; // 自动开始播放 result = player->play(); if (result == ErrorCode::SUCCESS) { std::cout << "Playback started" << std::endl; } else { std::cout << "Failed to start playback: " << static_cast(result) << std::endl; } } else { std::cout << "Failed to open file: " << static_cast(result) << std::endl; } } // 启动用户界面 SimplePlayerUI ui(player.get()); // 启动更新线程 std::atomic shouldStop(false); std::thread updateThread([&player, &shouldStop]() { while (!shouldStop) { player->update(); std::this_thread::sleep_for(std::chrono::milliseconds(16)); // ~60 FPS } }); // 运行用户界面 ui.run(); // 停止更新线程 shouldStop = true; if (updateThread.joinable()) { updateThread.join(); } // 停止播放器 player->stop(); std::cout << "PlayerCoreV2 Example finished" << std::endl; } catch (const std::exception& e) { std::cerr << "Exception: " << e.what() << std::endl; return 1; } catch (...) { std::cerr << "Unknown exception occurred" << std::endl; return 1; } return 0; }