|
|
@@ -1,133 +1,385 @@
|
|
|
-// #include "AVPlayer2/mainwindowa.h"
|
|
|
-// #include "mainwindow.h"
|
|
|
-// #include "thememanager.h"
|
|
|
-// #include "themesettingswidget.h"
|
|
|
-
|
|
|
-// #include <QApplication>
|
|
|
-// #include <QAudioDeviceInfo>
|
|
|
-// #include <QAudioOutput>
|
|
|
-// #include <QDebug>
|
|
|
-// #include <QVBoxLayout>
|
|
|
-// #include <qendian.h>
|
|
|
-// #include <qmath.h>
|
|
|
-// #include <QFile>
|
|
|
-// #include <QTextStream>
|
|
|
-// #include <QDateTime>
|
|
|
-// #include <QMutex>
|
|
|
-// #include <QLoggingCategory>
|
|
|
-
|
|
|
-// QFile g_logFile;
|
|
|
-// QTextStream* g_logStream = nullptr;
|
|
|
-// QMutex g_logMutex;
|
|
|
-
|
|
|
-// void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
|
|
|
+// #include "AV/code/base/logger.h"
|
|
|
+// #include "AV/code/player/player_core_v2.h"
|
|
|
+// #include <chrono>
|
|
|
+// #include <iostream>
|
|
|
+// #include <string>
|
|
|
+// #include <thread>
|
|
|
+
|
|
|
+// using namespace av::player;
|
|
|
+// using namespace av::utils;
|
|
|
+
|
|
|
+// // 示例事件回调类
|
|
|
+// class ExamplePlayerCallback : public PlayerEventCallback
|
|
|
// {
|
|
|
-// QMutexLocker locker(&g_logMutex);
|
|
|
-// if (!g_logStream) return;
|
|
|
-
|
|
|
-// QString typeStr;
|
|
|
-// switch (type) {
|
|
|
-// case QtDebugMsg: typeStr = "DEBUG"; break;
|
|
|
-// case QtWarningMsg: typeStr = "WARN "; break;
|
|
|
-// case QtCriticalMsg: typeStr = "ERROR"; break;
|
|
|
-// case QtFatalMsg: typeStr = "FATAL"; break;
|
|
|
-// case QtInfoMsg:
|
|
|
-// break;
|
|
|
+// 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;
|
|
|
// }
|
|
|
|
|
|
-// QString logMsg = QString("%1 [%2] %3 (%4:%5)\n")
|
|
|
-// .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"))
|
|
|
-// .arg(typeStr)
|
|
|
-// .arg(msg)
|
|
|
-// .arg(QString(context.file ? context.file : ""))
|
|
|
-// .arg(context.line);
|
|
|
+// 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;
|
|
|
+// }
|
|
|
+// }
|
|
|
|
|
|
-// (*g_logStream) << logMsg;
|
|
|
-// g_logStream->flush();
|
|
|
+// 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 (type == QtFatalMsg)
|
|
|
-// abort();
|
|
|
-// }
|
|
|
-// namespace avrecorder::video { void InitWinRTCapture(); }
|
|
|
-// int main(int argc, char* argv[])
|
|
|
+// 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;
|
|
|
+// }
|
|
|
+
|
|
|
+// void onEndOfFile() override { std::cout << "[EVENT] End of file reached" << std::endl; }
|
|
|
+// };
|
|
|
+
|
|
|
+// // 简单的命令行界面
|
|
|
+// class SimplePlayerUI
|
|
|
// {
|
|
|
-// QLoggingCategory::setFilterRules(QStringLiteral("player.controller.ReadThread=false\n"
|
|
|
-// "player.controller.AudioPlayThread=false\n"));
|
|
|
-// // QLoggingCategory::setFilterRules("*.debug=false\n"
|
|
|
-// // "*.info=false\n"
|
|
|
-// // "*.warning=false\n"
|
|
|
-// // "*.critical=false\n"
|
|
|
-// // "player.controller.*.debug=true\n"
|
|
|
-// // "player.controller.*.info=true\n");
|
|
|
+// public:
|
|
|
+// SimplePlayerUI(PlayerCoreV2* player)
|
|
|
+// : m_player(player)
|
|
|
+// , m_running(true)
|
|
|
+// {}
|
|
|
|
|
|
-// // 打开日志文件(覆盖模式)
|
|
|
-// g_logFile.setFileName("log.txt");
|
|
|
-// g_logFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate);
|
|
|
-// g_logStream = new QTextStream(&g_logFile);
|
|
|
+// 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;
|
|
|
|
|
|
-// // 安装日志处理器
|
|
|
-// //qInstallMessageHandler(myMessageHandler);
|
|
|
+// std::string line;
|
|
|
+// while (m_running && std::getline(std::cin, line)) {
|
|
|
+// processCommand(line);
|
|
|
+// }
|
|
|
+// }
|
|
|
|
|
|
-// // std::freopen(nullptr, "w", stdout);
|
|
|
-// setvbuf(stdout, nullptr, _IONBF, 0);
|
|
|
+// private:
|
|
|
+// void processCommand(const std::string& line)
|
|
|
+// {
|
|
|
+// std::istringstream iss(line);
|
|
|
+// std::string command;
|
|
|
+// iss >> command;
|
|
|
|
|
|
-// #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
|
|
-// QGuiApplication::setHighDpiScaleFactorRoundingPolicy(
|
|
|
-// Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
|
|
-// #endif
|
|
|
-// #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
|
|
-// QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
|
|
-// QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
|
|
-// #endif
|
|
|
+// 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;
|
|
|
+// }
|
|
|
|
|
|
-// QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
|
|
|
+// void showSyncConfig()
|
|
|
+// {
|
|
|
+// auto config = m_player->getSyncConfig();
|
|
|
|
|
|
-// QApplication a(argc, argv);
|
|
|
+// 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;
|
|
|
+// };
|
|
|
|
|
|
-// ThemeManager::instance().setThemeMode(ThemeManager::Light);
|
|
|
+// int main(int argc, char* argv[])
|
|
|
+// {
|
|
|
+// // 初始化日志系统
|
|
|
+// Logger::instance().initialize("test.log", LogLevel::DEBUG, false, true);
|
|
|
+// Logger::instance().setLevel(LogLevel::DEBUG);
|
|
|
+// Logger::instance().info("PlayerCoreV2 Example Started");
|
|
|
|
|
|
-// // 注册Room 相关的类型 方便 序列化
|
|
|
-// void initRoomType();
|
|
|
-// initRoomType();
|
|
|
+// 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;
|
|
|
|
|
|
-// // 初始化wgc
|
|
|
+// // 创建播放器实例
|
|
|
+// auto player = std::make_unique<PlayerCoreV2>(syncConfig);
|
|
|
|
|
|
-// avrecorder::video::InitWinRTCapture();
|
|
|
+// // 创建事件回调
|
|
|
+// auto callback = std::make_unique<ExamplePlayerCallback>();
|
|
|
+// player->setEventCallback(callback.get());
|
|
|
|
|
|
-// /*
|
|
|
-// docker run -itd --name zlmediakit --restart=always
|
|
|
-// -p 1935:1935 -p 8080:80 -p 8443:443
|
|
|
-// -p 8554:554 -p 10000:10000
|
|
|
-// -p 10000:10000/udp -p 8000:8000/udp
|
|
|
-// -p 9000:9000/udp
|
|
|
-// -v /data/zlmediakit/media/bin:/opt/media/bin
|
|
|
-// -v /data/zlmediakit/media/conf:/opt/media/conf
|
|
|
-// zlmediakit/zlmediakit:master
|
|
|
-// */
|
|
|
-// // MainWindow w;
|
|
|
-// // w.show();
|
|
|
+// // 如果命令行提供了文件名,自动打开
|
|
|
+// if (argc > 1) {
|
|
|
+// std::string filename = argv[1];
|
|
|
+// std::cout << "Opening file: " << filename << std::endl;
|
|
|
|
|
|
-// // 视频播放测试
|
|
|
-// MainWindowA aa;
|
|
|
-// aa.show();
|
|
|
+// auto result = player->openFile(filename);
|
|
|
+// if (result == ErrorCode::SUCCESS) {
|
|
|
+// std::cout << "File opened successfully" << std::endl;
|
|
|
|
|
|
-// // ThemeSettingsWidget ThemeSettingsWidget;
|
|
|
-// // ThemeSettingsWidget.show();
|
|
|
+// // 自动开始播放
|
|
|
+// 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;
|
|
|
+// }
|
|
|
+// }
|
|
|
|
|
|
-// // PlayerWindow w;
|
|
|
-// // w.resize(960, 540);
|
|
|
-// // w.show();
|
|
|
+// // 启动用户界面
|
|
|
+// SimplePlayerUI ui(player.get());
|
|
|
|
|
|
-// // // 这里填你的流地址
|
|
|
-// // // w.startPlay("http://vd3.bdstatic.com/mda-jennyc5ci1ugrxzi/mda-jennyc5ci1ugrxzi.mp4");
|
|
|
+// // 启动更新线程
|
|
|
+// 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
|
|
|
+// }
|
|
|
+// });
|
|
|
|
|
|
-// // w.open("C:/Users/zhuizhu/Videos/1.mp4");
|
|
|
-// // // w.startPlay("rtmp://192.168.3.76:1935/stream/V1/stream");
|
|
|
+// // 运行用户界面
|
|
|
+// ui.run();
|
|
|
|
|
|
-// int ret = a.exec();
|
|
|
+// // 停止更新线程
|
|
|
+// shouldStop = true;
|
|
|
+// if (updateThread.joinable()) {
|
|
|
+// updateThread.join();
|
|
|
+// }
|
|
|
|
|
|
-// delete g_logStream;
|
|
|
-// g_logFile.close();
|
|
|
+// // 等待播放完成后再停止播放器
|
|
|
+// if (player->getState() == PlayerState::Playing) {
|
|
|
+// auto mediaInfo = player->getMediaInfo();
|
|
|
+// if (mediaInfo.duration > 0) {
|
|
|
+// std::cout << "Waiting for playback to complete..." << std::endl;
|
|
|
+
|
|
|
+// // 等待播放完成
|
|
|
+// while (player->getState() == PlayerState::Playing) {
|
|
|
+// auto currentTime = player->getCurrentTime();
|
|
|
+// auto duration = mediaInfo.duration;
|
|
|
+
|
|
|
+// // 如果播放时间接近总时长(留100ms缓冲),认为播放完成
|
|
|
+// if (currentTime >= duration - 100000) { // 100ms = 100000微秒
|
|
|
+// std::cout << "Playback completed naturally" << std::endl;
|
|
|
+// break;
|
|
|
+// }
|
|
|
+
|
|
|
+// // 每100ms检查一次
|
|
|
+// std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+// // 停止播放器
|
|
|
+// 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 ret;
|
|
|
+// return 0;
|
|
|
// }
|