| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321 |
- #include "../player/player_core_v2.h"
- #include "../base/logger.h"
- #include <iostream>
- #include <thread>
- #include <chrono>
- #include <string>
- 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<std::chrono::seconds>(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 <filename> - 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 <seconds> - Seek to position" << std::endl;
- std::cout << " speed <rate> - Set playback speed (0.5-4.0)" << std::endl;
- std::cout << " volume <level> - 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<int>(result) << std::endl;
- }
- } else {
- std::cout << "Usage: open <filename>" << 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<int>(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<int>(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<int>(result) << std::endl;
- }
- }
- else if (command == "seek") {
- double seconds;
- iss >> seconds;
- if (iss) {
- int64_t timestamp = static_cast<int64_t>(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<int>(result) << std::endl;
- }
- } else {
- std::cout << "Usage: seek <seconds>" << 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<int>(result) << std::endl;
- }
- } else {
- std::cout << "Usage: speed <rate>" << 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 <level>" << 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<int>(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<PlayerCoreV2>(syncConfig);
-
- // 创建事件回调
- auto callback = std::make_unique<ExamplePlayerCallback>();
- 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<int>(result) << std::endl;
- }
- } else {
- std::cout << "Failed to open file: " << static_cast<int>(result) << std::endl;
- }
- }
-
- // 启动用户界面
- SimplePlayerUI ui(player.get());
-
- // 启动更新线程
- std::atomic<bool> 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;
- }
|