player_v2_example.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. #include "../player/player_core_v2.h"
  2. #include "../base/logger.h"
  3. #include <iostream>
  4. #include <thread>
  5. #include <chrono>
  6. #include <string>
  7. using namespace av::player;
  8. using namespace av::utils;
  9. // 示例事件回调类
  10. class ExamplePlayerCallback : public PlayerEventCallback {
  11. public:
  12. void onStateChanged(PlayerState newState) override {
  13. std::string stateStr;
  14. switch (newState) {
  15. case PlayerState::Idle: stateStr = "Idle"; break;
  16. case PlayerState::Opening: stateStr = "Opening"; break;
  17. case PlayerState::Stopped: stateStr = "Stopped"; break;
  18. case PlayerState::Playing: stateStr = "Playing"; break;
  19. case PlayerState::Paused: stateStr = "Paused"; break;
  20. case PlayerState::Seeking: stateStr = "Seeking"; break;
  21. case PlayerState::Error: stateStr = "Error"; break;
  22. }
  23. std::cout << "[EVENT] State changed to: " << stateStr << std::endl;
  24. }
  25. void onPositionChanged(int64_t position) override {
  26. // 每秒更新一次位置信息
  27. static auto lastUpdate = std::chrono::steady_clock::now();
  28. auto now = std::chrono::steady_clock::now();
  29. if (std::chrono::duration_cast<std::chrono::seconds>(now - lastUpdate).count() >= 1) {
  30. double seconds = position / 1000000.0;
  31. std::cout << "[EVENT] Position: " << std::fixed << std::setprecision(2) << seconds << "s" << std::endl;
  32. lastUpdate = now;
  33. }
  34. }
  35. void onMediaInfoChanged(const MediaInfo& info) override {
  36. std::cout << "[EVENT] Media info changed:" << std::endl;
  37. std::cout << " File: " << info.filename << std::endl;
  38. std::cout << " Duration: " << (info.duration / 1000000.0) << "s" << std::endl;
  39. std::cout << " Has Video: " << (info.hasVideo ? "Yes" : "No") << std::endl;
  40. std::cout << " Has Audio: " << (info.hasAudio ? "Yes" : "No") << std::endl;
  41. if (info.hasVideo) {
  42. std::cout << " Video: " << info.width << "x" << info.height << " @ " << info.fps << " fps" << std::endl;
  43. }
  44. if (info.hasAudio) {
  45. std::cout << " Audio: " << info.sampleRate << " Hz, " << info.channels << " channels" << std::endl;
  46. }
  47. }
  48. void onErrorOccurred(const std::string& error) override {
  49. std::cout << "[ERROR] " << error << std::endl;
  50. }
  51. void onFrameDropped(int64_t totalDropped) override {
  52. std::cout << "[WARNING] Frame dropped, total: " << totalDropped << std::endl;
  53. }
  54. void onSyncError(double error, const std::string& reason) override {
  55. std::cout << "[WARNING] Sync error: " << (error * 1000) << "ms, reason: " << reason << std::endl;
  56. }
  57. };
  58. // 简单的命令行界面
  59. class SimplePlayerUI {
  60. public:
  61. SimplePlayerUI(PlayerCoreV2* player) : m_player(player), m_running(true) {}
  62. void run() {
  63. std::cout << "\n=== PlayerCoreV2 Example ===" << std::endl;
  64. std::cout << "Commands:" << std::endl;
  65. std::cout << " open <filename> - Open media file" << std::endl;
  66. std::cout << " play - Start playback" << std::endl;
  67. std::cout << " pause - Pause playback" << std::endl;
  68. std::cout << " stop - Stop playback" << std::endl;
  69. std::cout << " seek <seconds> - Seek to position" << std::endl;
  70. std::cout << " speed <rate> - Set playback speed (0.5-4.0)" << std::endl;
  71. std::cout << " volume <level> - Set volume (0.0-1.0)" << std::endl;
  72. std::cout << " stats - Show playback statistics" << std::endl;
  73. std::cout << " debug - Show debug information" << std::endl;
  74. std::cout << " config - Show sync configuration" << std::endl;
  75. std::cout << " quit - Exit program" << std::endl;
  76. std::cout << "============================\n" << std::endl;
  77. std::string line;
  78. while (m_running && std::getline(std::cin, line)) {
  79. processCommand(line);
  80. }
  81. }
  82. private:
  83. void processCommand(const std::string& line) {
  84. std::istringstream iss(line);
  85. std::string command;
  86. iss >> command;
  87. if (command == "open") {
  88. std::string filename;
  89. iss >> filename;
  90. if (!filename.empty()) {
  91. auto result = m_player->openFile(filename);
  92. if (result == ErrorCode::SUCCESS) {
  93. std::cout << "File opened successfully" << std::endl;
  94. } else {
  95. std::cout << "Failed to open file: " << static_cast<int>(result) << std::endl;
  96. }
  97. } else {
  98. std::cout << "Usage: open <filename>" << std::endl;
  99. }
  100. }
  101. else if (command == "play") {
  102. auto result = m_player->play();
  103. if (result == ErrorCode::SUCCESS) {
  104. std::cout << "Playback started" << std::endl;
  105. } else {
  106. std::cout << "Failed to start playback: " << static_cast<int>(result) << std::endl;
  107. }
  108. }
  109. else if (command == "pause") {
  110. auto result = m_player->pause();
  111. if (result == ErrorCode::SUCCESS) {
  112. std::cout << "Playback paused" << std::endl;
  113. } else {
  114. std::cout << "Failed to pause playback: " << static_cast<int>(result) << std::endl;
  115. }
  116. }
  117. else if (command == "stop") {
  118. auto result = m_player->stop();
  119. if (result == ErrorCode::SUCCESS) {
  120. std::cout << "Playback stopped" << std::endl;
  121. } else {
  122. std::cout << "Failed to stop playback: " << static_cast<int>(result) << std::endl;
  123. }
  124. }
  125. else if (command == "seek") {
  126. double seconds;
  127. iss >> seconds;
  128. if (iss) {
  129. int64_t timestamp = static_cast<int64_t>(seconds * 1000000); // 转换为微秒
  130. auto result = m_player->seek(timestamp);
  131. if (result == ErrorCode::SUCCESS) {
  132. std::cout << "Seeking to " << seconds << "s" << std::endl;
  133. } else {
  134. std::cout << "Failed to seek: " << static_cast<int>(result) << std::endl;
  135. }
  136. } else {
  137. std::cout << "Usage: seek <seconds>" << std::endl;
  138. }
  139. }
  140. else if (command == "speed") {
  141. double speed;
  142. iss >> speed;
  143. if (iss) {
  144. auto result = m_player->setPlaybackSpeed(speed);
  145. if (result == ErrorCode::SUCCESS) {
  146. std::cout << "Playback speed set to " << speed << "x" << std::endl;
  147. } else {
  148. std::cout << "Failed to set playback speed: " << static_cast<int>(result) << std::endl;
  149. }
  150. } else {
  151. std::cout << "Usage: speed <rate>" << std::endl;
  152. }
  153. }
  154. else if (command == "volume") {
  155. double volume;
  156. iss >> volume;
  157. if (iss) {
  158. m_player->setVolume(volume);
  159. std::cout << "Volume set to " << volume << std::endl;
  160. } else {
  161. std::cout << "Usage: volume <level>" << std::endl;
  162. }
  163. }
  164. else if (command == "stats") {
  165. showStats();
  166. }
  167. else if (command == "debug") {
  168. std::cout << m_player->getDebugInfo() << std::endl;
  169. }
  170. else if (command == "config") {
  171. showSyncConfig();
  172. }
  173. else if (command == "quit" || command == "exit") {
  174. m_running = false;
  175. std::cout << "Exiting..." << std::endl;
  176. }
  177. else if (!command.empty()) {
  178. std::cout << "Unknown command: " << command << std::endl;
  179. }
  180. }
  181. void showStats() {
  182. auto stats = m_player->getStats();
  183. std::cout << "\n=== Playback Statistics ===" << std::endl;
  184. std::cout << "Current Time: " << std::fixed << std::setprecision(2) << (stats.currentTime / 1000000.0) << "s" << std::endl;
  185. std::cout << "Playback Speed: " << stats.playbackSpeed << "x" << std::endl;
  186. std::cout << "Total Frames: " << stats.totalFrames << std::endl;
  187. std::cout << "Dropped Frames: " << stats.droppedFrames << std::endl;
  188. std::cout << "Duplicated Frames: " << stats.duplicatedFrames << std::endl;
  189. std::cout << "Sync Error: " << std::fixed << std::setprecision(1) << (stats.syncError * 1000) << "ms" << std::endl;
  190. std::cout << "Avg Sync Error: " << std::fixed << std::setprecision(1) << (stats.avgSyncError * 1000) << "ms" << std::endl;
  191. std::cout << "Max Sync Error: " << std::fixed << std::setprecision(1) << (stats.maxSyncError * 1000) << "ms" << std::endl;
  192. std::cout << "CPU Usage: " << std::fixed << std::setprecision(1) << stats.cpuUsage << "%" << std::endl;
  193. std::cout << "Memory Usage: " << std::fixed << std::setprecision(1) << stats.memoryUsage << "MB" << std::endl;
  194. std::cout << "Queued Packets: " << stats.queuedPackets << std::endl;
  195. std::cout << "Queued Video Frames: " << stats.queuedVideoFrames << std::endl;
  196. std::cout << "Queued Audio Frames: " << stats.queuedAudioFrames << std::endl;
  197. std::cout << "Bitrate: " << std::fixed << std::setprecision(1) << stats.bitrate << " kbps" << std::endl;
  198. std::cout << "===========================\n" << std::endl;
  199. }
  200. void showSyncConfig() {
  201. auto config = m_player->getSyncConfig();
  202. std::cout << "\n=== Sync Configuration ===" << std::endl;
  203. std::cout << "Sync Strategy: " << static_cast<int>(config.syncStrategy) << std::endl;
  204. std::cout << "Audio Sync Threshold: " << (config.audioSyncThreshold * 1000) << "ms" << std::endl;
  205. std::cout << "Video Sync Threshold: " << (config.videoSyncThreshold * 1000) << "ms" << std::endl;
  206. std::cout << "Max Sync Error: " << (config.maxSyncError * 1000) << "ms" << std::endl;
  207. std::cout << "Clock Update Interval: " << config.clockUpdateInterval << "ms" << std::endl;
  208. std::cout << "Smoothing Window: " << config.smoothingWindow << std::endl;
  209. std::cout << "Adaptive Sync: " << (config.enableAdaptiveSync ? "Enabled" : "Disabled") << std::endl;
  210. std::cout << "Frame Drop: " << (config.enableFrameDrop ? "Enabled" : "Disabled") << std::endl;
  211. std::cout << "Frame Duplicate: " << (config.enableFrameDuplicate ? "Enabled" : "Disabled") << std::endl;
  212. std::cout << "Prediction: " << (config.enablePrediction ? "Enabled" : "Disabled") << std::endl;
  213. std::cout << "==========================\n" << std::endl;
  214. }
  215. PlayerCoreV2* m_player;
  216. bool m_running;
  217. };
  218. int main(int argc, char* argv[]) {
  219. // 初始化日志系统
  220. Logger::instance().setLevel(LogLevel::INFO);
  221. Logger::instance().info("PlayerCoreV2 Example Started");
  222. try {
  223. // 创建同步配置
  224. SyncConfigV2 syncConfig;
  225. syncConfig.syncStrategy = SyncStrategy::ADAPTIVE; // 使用自适应同步策略
  226. syncConfig.audioSyncThreshold = 0.040; // 40ms
  227. syncConfig.videoSyncThreshold = 0.020; // 20ms
  228. syncConfig.maxSyncError = 0.200; // 200ms
  229. syncConfig.clockUpdateInterval = 10; // 10ms
  230. syncConfig.smoothingWindow = 10; // 10个样本
  231. syncConfig.enableAdaptiveSync = true;
  232. syncConfig.enableFrameDrop = true;
  233. syncConfig.enableFrameDuplicate = true;
  234. syncConfig.enablePrediction = true;
  235. syncConfig.enableErrorRecovery = true;
  236. // 创建播放器实例
  237. auto player = std::make_unique<PlayerCoreV2>(syncConfig);
  238. // 创建事件回调
  239. auto callback = std::make_unique<ExamplePlayerCallback>();
  240. player->setEventCallback(callback.get());
  241. // 如果命令行提供了文件名,自动打开
  242. if (argc > 1) {
  243. std::string filename = argv[1];
  244. std::cout << "Opening file: " << filename << std::endl;
  245. auto result = player->openFile(filename);
  246. if (result == ErrorCode::SUCCESS) {
  247. std::cout << "File opened successfully" << std::endl;
  248. // 自动开始播放
  249. result = player->play();
  250. if (result == ErrorCode::SUCCESS) {
  251. std::cout << "Playback started" << std::endl;
  252. } else {
  253. std::cout << "Failed to start playback: " << static_cast<int>(result) << std::endl;
  254. }
  255. } else {
  256. std::cout << "Failed to open file: " << static_cast<int>(result) << std::endl;
  257. }
  258. }
  259. // 启动用户界面
  260. SimplePlayerUI ui(player.get());
  261. // 启动更新线程
  262. std::atomic<bool> shouldStop(false);
  263. std::thread updateThread([&player, &shouldStop]() {
  264. while (!shouldStop) {
  265. player->update();
  266. std::this_thread::sleep_for(std::chrono::milliseconds(16)); // ~60 FPS
  267. }
  268. });
  269. // 运行用户界面
  270. ui.run();
  271. // 停止更新线程
  272. shouldStop = true;
  273. if (updateThread.joinable()) {
  274. updateThread.join();
  275. }
  276. // 停止播放器
  277. player->stop();
  278. std::cout << "PlayerCoreV2 Example finished" << std::endl;
  279. } catch (const std::exception& e) {
  280. std::cerr << "Exception: " << e.what() << std::endl;
  281. return 1;
  282. } catch (...) {
  283. std::cerr << "Unknown exception occurred" << std::endl;
  284. return 1;
  285. }
  286. return 0;
  287. }