zhuizhu il y a 8 mois
Parent
commit
e88251f3f0

+ 301 - 137
AV/code/player/player_core_v2.cpp

@@ -10,21 +10,13 @@
 #include <algorithm>
 #include <cmath>
 
-#ifdef _WIN32
-#include <windows.h>
-#include <psapi.h>
-#else
-#include <sys/times.h>
-#include <unistd.h>
-#endif
-
 namespace av {
 namespace player {
 PlayerCoreV2::PlayerCoreV2(const SyncConfigV2& syncConfig)
     : m_state(PlayerState::Idle)
     , m_eventCallback(nullptr)
     , m_formatContext(nullptr)
-    , m_openGLVideoRenderer(nullptr)
+    // , m_openGLVideoRenderer(nullptr)  // 已移除
     , m_volume(1.0)
     , m_playbackSpeed(1.0)
     , m_seekTarget(-1)
@@ -33,6 +25,7 @@ PlayerCoreV2::PlayerCoreV2(const SyncConfigV2& syncConfig)
     , m_lastUpdateTime(0)
     , m_threadsShouldStop(false)
     , m_threadsRunning(false)
+    , m_paused(false)
     , m_initialized(false)
     , m_frameCount(0)
     , m_lastFrameCount(0)
@@ -134,13 +127,7 @@ PlayerCoreV2::PlayerCoreV2(const SyncConfigV2& syncConfig)
         // 初始化性能监控
         m_lastStatsUpdate = std::chrono::steady_clock::now();
         m_lastCpuMeasure = m_lastStatsUpdate;
-#ifdef _WIN32
-        m_lastCpuTime = GetTickCount64();
-#else
-        struct tms tm;
-        m_lastCpuTime = times(&tm);
-#endif
-        
+
         m_initialized = true;
         Logger::instance().info("PlayerCoreV2 initialized successfully");
 
@@ -210,20 +197,16 @@ ErrorCode PlayerCoreV2::openFile(const std::string& filename) {
     
     setState(PlayerState::Stopped);
     
-    // 如果已设置视频渲染器且有视频流,重新初始化渲染器
-    if (m_mediaInfo.hasVideo && m_openGLVideoRenderer) {
+    // 如果有视频流,通知需要初始化渲染器
+    if (m_mediaInfo.hasVideo && m_eventCallback) {
         AVStream* videoStream = m_formatContext->streams[m_mediaInfo.videoStreamIndex];
         
-        bool rendererInitResult = m_openGLVideoRenderer->Open(
+        m_eventCallback->onVideoRendererInitRequired(
             videoStream->codecpar->width,
             videoStream->codecpar->height
         );
         
-        if (!rendererInitResult) {
-            Logger::instance().warning("Failed to initialize OpenGL video renderer");
-        } else {
-            Logger::instance().info("OpenGL video renderer initialized successfully");
-        }
+        Logger::instance().info("Video renderer initialization requested");
     }
     
     // 通知媒体信息变化
@@ -248,77 +231,114 @@ ErrorCode PlayerCoreV2::play() {
         return ErrorCode::INVALID_STATE;
     }
     
-    // 启动同步器
-    if (m_synchronizer && m_synchronizer->start() != ErrorCode::SUCCESS) {
-        Logger::instance().error("Failed to start synchronizer");
-        return ErrorCode::SYNC_ERROR;
+    // 启动或恢复同步器
+    if (m_synchronizer) {
+        ErrorCode syncResult = ErrorCode::SUCCESS;
+        if (m_state == PlayerState::Paused) {
+            // 从暂停状态恢复,调用resume方法
+            syncResult = m_synchronizer->resume();
+        } else {
+            // 从停止状态开始,调用start方法
+            syncResult = m_synchronizer->start();
+        }
+        
+        if (syncResult != ErrorCode::SUCCESS) {
+            Logger::instance().error("Failed to start/resume synchronizer");
+            return ErrorCode::SYNC_ERROR;
+        }
     }
 
-    // 记录播放开始时间
-    m_playStartTime = std::chrono::steady_clock::now();
-    
-    // 如果是从停止状态开始播放,重置基准时间
+    // 根据当前状态设置播放开始时间
     if (m_state == PlayerState::Stopped) {
+        // 从停止状态开始播放,重置所有时间相关变量
         m_baseTime = 0;
         m_frameCount = 0;
         m_lastFrameCount = 0;
+        m_playStartTime = std::chrono::steady_clock::now();
         
         // 重置统计信息
         std::lock_guard<std::mutex> lock(m_mutex);
         m_stats = PlaybackStats();
         m_stats.playbackSpeed = m_playbackSpeed;
+    } else if (m_state == PlayerState::Paused) {
+        // 从暂停状态恢复播放,重新设置播放开始时间
+        // m_baseTime已经在pause()方法中正确更新,这里只需要重新设置开始时间
+        m_playStartTime = std::chrono::steady_clock::now();
+        
+        // 清除暂停标志并唤醒等待的线程,类似ffplay.c中的continue_read_thread机制
+        {
+            std::lock_guard<std::mutex> lock(m_pauseMutex);
+            m_paused = false;
+        }
+        m_pauseCondition.notify_all();
     }
     
     // 启动音频输出设备
     if (m_audioOutput && m_mediaInfo.hasAudio) {
         if (m_state == PlayerState::Paused) {
-            m_audioOutput->resume();
+            // 从暂停状态恢复音频
+            try {
+                m_audioOutput->resume();
+            } catch (const std::exception& e) {
+                Logger::instance().error("Failed to resume audio output: " + std::string(e.what()));
+                // 尝试重新初始化音频设备
+                try {
+                    m_audioOutput->stop();
+                    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+                    m_audioOutput->start();
+                } catch (const std::exception& e2) {
+                    Logger::instance().error("Failed to restart audio output: " + std::string(e2.what()));
+                    Logger::instance().warning("Continuing playback without audio");
+                }
+            }
         } else {
             Logger::instance().info("Starting audio output device...");
-            m_audioOutput->start();
-            
-            // 检查音频设备是否成功启动
-            if (!m_audioOutput->isPlaying()) {
-                Logger::instance().error("Audio output device failed to start");
-                // 不要因为音频失败而停止整个播放,继续播放视频
-                Logger::instance().warning("Continuing playback without audio");
-            } else {
-                Logger::instance().info("Audio output device started successfully");
-            }
+            try {
+                m_audioOutput->start();
+                
+                // 检查音频设备是否成功启动
+                if (!m_audioOutput->isPlaying()) {
+                    Logger::instance().error("Audio output device failed to start");
+                    // 不要因为音频失败而停止整个播放,继续播放视频
+                    Logger::instance().warning("Continuing playback without audio");
+                }
+            } catch (const std::exception& e) {
+                 Logger::instance().error("Exception starting audio output: " + std::string(e.what()));
+                 Logger::instance().warning("Continuing playback without audio");
+             }
         }
-        
-        // 设置音频参数
-        m_audioOutput->setVolume(m_volume);
-        m_audioOutput->setPlaybackSpeed(m_playbackSpeed);
-        
-        // 给音频输出设备更多时间初始化
-        std::this_thread::sleep_for(std::chrono::milliseconds(100));
-    }
-    
-    // 启动线程
-    m_threadsShouldStop = false;
-    
-    if (!startReadThread()) {
-        Logger::instance().error("Failed to start read thread");
-        return ErrorCode::THREAD_ERROR;
-    }
-    
-    if (!startDecodeThreads()) {
-        Logger::instance().error("Failed to start decode threads");
-        return ErrorCode::THREAD_ERROR;
-    }
-    
-    if (m_mediaInfo.hasVideo && m_videoStreamEnabled && !startVideoPlayThread()) {
-        Logger::instance().error("Failed to start video play thread");
-        return ErrorCode::THREAD_ERROR;
     }
     
-    if (m_mediaInfo.hasAudio && m_audioStreamEnabled && !startAudioPlayThread()) {
-        Logger::instance().error("Failed to start audio play thread");
-        return ErrorCode::THREAD_ERROR;
+    // 根据状态启动或恢复线程
+    if (m_state == PlayerState::Stopped) {
+        // 从停止状态开始,需要启动所有线程
+        
+        // 启动播放线程
+        if (m_mediaInfo.hasVideo && !startVideoPlayThread()) {
+            Logger::instance().error("Failed to start video play thread");
+            return ErrorCode::THREAD_ERROR;
+        }
+        
+        if (m_mediaInfo.hasAudio && !startAudioPlayThread()) {
+            Logger::instance().error("Failed to start audio play thread");
+            return ErrorCode::THREAD_ERROR;
+        }
+        
+        // 启动解码线程
+        if (!startDecodeThreads()) {
+            Logger::instance().error("Failed to start decode threads");
+            return ErrorCode::THREAD_ERROR;
+        }
+        
+        // 启动读取线程
+        if (!startReadThread()) {
+            Logger::instance().error("Failed to start read thread");
+            return ErrorCode::THREAD_ERROR;
+        }
+        
+        m_threadsRunning = true;
     }
-    
-    m_threadsRunning = true;
+    // 从暂停状态恢复时,线程已经在运行,只需要唤醒它们(已在上面完成)
     setState(PlayerState::Playing);
     
     Logger::instance().info("Playback started");
@@ -332,6 +352,17 @@ ErrorCode PlayerCoreV2::pause() {
         Logger::instance().debug("Not playing, cannot pause");
         return ErrorCode::INVALID_STATE;
     }
+    // 设置暂停标志,让线程在内部循环中等待,而不是停止线程
+    // 类似ffplay.c中的paused标志机制
+    {
+        std::lock_guard<std::mutex> lock(m_pauseMutex);
+        Logger::instance().info("Setting m_paused to true");
+        m_paused = true;
+        Logger::instance().info("m_paused set to: " + std::to_string(m_paused.load()));
+    }
+    // 立即通知所有等待的线程检查暂停状态
+    Logger::instance().info("Notifying all threads about pause state change");
+    m_pauseCondition.notify_all();
 
     // 暂停同步器
     if (m_synchronizer && m_synchronizer->pause() != ErrorCode::SUCCESS) {
@@ -351,9 +382,9 @@ ErrorCode PlayerCoreV2::pause() {
     if (m_audioOutput) {
         m_audioOutput->pause();
     }
-    
+
     setState(PlayerState::Paused);
-    Logger::instance().info("Playback paused");
+    Logger::instance().info("Playback paused (threads continue running)");
     return ErrorCode::SUCCESS;
 }
 
@@ -375,10 +406,17 @@ ErrorCode PlayerCoreV2::stop() {
         m_audioOutput->stop();
     }
     
-    // 清空OpenGL视频渲染器
-    if (m_openGLVideoRenderer) {
-        m_openGLVideoRenderer->Close();
+    // 通知关闭视频渲染器
+    if (m_eventCallback) {
+        m_eventCallback->onVideoRendererCloseRequired();
+    }
+    
+    // 清除暂停标志并唤醒所有等待的线程
+    {
+        std::lock_guard<std::mutex> lock(m_pauseMutex);
+        m_paused = false;
     }
+    m_pauseCondition.notify_all();
     
     // 停止所有线程
     stopAllThreads();
@@ -511,22 +549,20 @@ int64_t PlayerCoreV2::getCurrentTime() const {
         }
     }
 
-    return 0;
-
-    // // 回退到原来的计算方式(兼容性保证)
-    // if (m_state == PlayerState::Paused) {
-    //     return m_baseTime;
-    // }
+    // 回退到原来的计算方式(兼容性保证)
+    if (m_state == PlayerState::Paused) {
+        return m_baseTime;
+    }
 
-    // if (m_playStartTime.time_since_epoch().count() == 0) {
-    //     return m_baseTime;
-    // }
+    if (m_playStartTime.time_since_epoch().count() == 0) {
+        return m_baseTime;
+    }
 
-    // auto currentTime = std::chrono::steady_clock::now();
-    // auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(
-    //     currentTime - m_playStartTime).count();
+    auto currentTime = std::chrono::steady_clock::now();
+    auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(
+        currentTime - m_playStartTime).count();
 
-    // return m_baseTime + static_cast<int64_t>(elapsed * m_playbackSpeed);
+    return m_baseTime + static_cast<int64_t>(elapsed * m_playbackSpeed);
 }
 
 double PlayerCoreV2::getPlaybackSpeed() const {
@@ -619,9 +655,9 @@ SyncConfigV2 PlayerCoreV2::getSyncConfig() const {
     return SyncConfigV2();
 }
 
-void PlayerCoreV2::setOpenGLVideoRenderer(OpenGLVideoWidget* renderer) {
-    m_openGLVideoRenderer = renderer;
-}
+// void PlayerCoreV2::setOpenGLVideoRenderer(OpenGLVideoWidget* renderer) {
+//     m_openGLVideoRenderer = renderer;
+// }
 
 AVFrame* PlayerCoreV2::getNextVideoFrame() {
     if (!m_videoFrameQueue || m_state != PlayerState::Playing) {
@@ -948,6 +984,12 @@ void PlayerCoreV2::resetDecoders() {
 
 bool PlayerCoreV2::startReadThread() {
     try {
+        // 确保之前的线程已经完全停止
+        if (m_readThread.joinable()) {
+            Logger::instance().warning("Read thread still running, waiting for it to stop...");
+            m_readThread.join();
+        }
+        
         m_readThread = std::thread(&PlayerCoreV2::readThreadFunc, this);
         Logger::instance().info("Read thread started");
         return true;
@@ -960,11 +1002,23 @@ bool PlayerCoreV2::startReadThread() {
 bool PlayerCoreV2::startDecodeThreads() {
     try {
         if (m_mediaInfo.hasVideo) {
+            // 确保之前的视频解码线程已经完全停止
+            if (m_videoDecodeThread.joinable()) {
+                Logger::instance().warning("Video decode thread still running, waiting for it to stop...");
+                m_videoDecodeThread.join();
+            }
+            
             m_videoDecodeThread = std::thread(&PlayerCoreV2::videoDecodeThreadFunc, this);
             Logger::instance().info("Video decode thread started");
         }
         
         if (m_mediaInfo.hasAudio) {
+            // 确保之前的音频解码线程已经完全停止
+            if (m_audioDecodeThread.joinable()) {
+                Logger::instance().warning("Audio decode thread still running, waiting for it to stop...");
+                m_audioDecodeThread.join();
+            }
+            
             m_audioDecodeThread = std::thread(&PlayerCoreV2::audioDecodeThreadFunc, this);
             Logger::instance().info("Audio decode thread started");
         }
@@ -978,6 +1032,12 @@ bool PlayerCoreV2::startDecodeThreads() {
 
 bool PlayerCoreV2::startVideoPlayThread() {
     try {
+        // 确保之前的视频播放线程已经完全停止
+        if (m_videoPlayThread.joinable()) {
+            Logger::instance().warning("Video play thread still running, waiting for it to stop...");
+            m_videoPlayThread.join();
+        }
+        
         m_videoPlayThread = std::thread(&PlayerCoreV2::videoPlayThreadFunc, this);
         Logger::instance().info("Video play thread started");
         return true;
@@ -989,6 +1049,12 @@ bool PlayerCoreV2::startVideoPlayThread() {
 
 bool PlayerCoreV2::startAudioPlayThread() {
     try {
+        // 确保之前的音频播放线程已经完全停止
+        if (m_audioPlayThread.joinable()) {
+            Logger::instance().warning("Audio play thread still running, waiting for it to stop...");
+            m_audioPlayThread.join();
+        }
+        
         m_audioPlayThread = std::thread(&PlayerCoreV2::audioPlayThreadFunc, this);
         Logger::instance().info("Audio play thread started");
         return true;
@@ -1128,23 +1194,10 @@ void PlayerCoreV2::updatePerformanceStats() {
 }
 
 double PlayerCoreV2::calculateCpuUsage() {
-#ifdef _WIN32
-    FILETIME idleTime, kernelTime, userTime;
-    if (GetSystemTimes(&idleTime, &kernelTime, &userTime)) {
-        // 简化的CPU使用率计算
-        return 0.0; // 实际实现需要更复杂的逻辑
-    }
-#endif
     return 0.0;
 }
 
 double PlayerCoreV2::calculateMemoryUsage() {
-#ifdef _WIN32
-    PROCESS_MEMORY_COUNTERS pmc;
-    if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) {
-        return pmc.WorkingSetSize / (1024.0 * 1024.0); // MB
-    }
-#endif
     return 0.0;
 }
 
@@ -1153,25 +1206,26 @@ void PlayerCoreV2::stopAllThreads() {
     
     m_threadsShouldStop = true;
     
-    // 等待线程结束
-    if (m_readThread.joinable()) {
-        m_readThread.join();
-    }
-    if (m_videoDecodeThread.joinable()) {
-        m_videoDecodeThread.join();
-    }
-    if (m_audioDecodeThread.joinable()) {
-        m_audioDecodeThread.join();
-    }
-    if (m_videoPlayThread.joinable()) {
-        m_videoPlayThread.join();
-    }
-    if (m_audioPlayThread.joinable()) {
-        m_audioPlayThread.join();
-    }
+    // 唤醒所有等待的队列,确保线程能够检查停止标志
+    flushBuffers();
+    
+    // 等待线程结束,添加超时保护
+    auto joinWithTimeout = [](std::thread& t, const std::string& name) {
+        if (t.joinable()) {
+            Logger::instance().info("Waiting for " + name + " to stop...");
+            t.join();
+            Logger::instance().info(name + " stopped");
+        }
+    };
+    
+    joinWithTimeout(m_readThread, "read thread");
+    joinWithTimeout(m_videoDecodeThread, "video decode thread");
+    joinWithTimeout(m_audioDecodeThread, "audio decode thread");
+    joinWithTimeout(m_videoPlayThread, "video play thread");
+    joinWithTimeout(m_audioPlayThread, "audio play thread");
     
     m_threadsRunning = false;
-    Logger::instance().info("All threads stopped");
+    Logger::instance().info("All threads stopped successfully");
 }
 
 void PlayerCoreV2::flushBuffers() {
@@ -1203,6 +1257,21 @@ void PlayerCoreV2::readThreadFunc() {
     }
     
     while (!m_threadsShouldStop) {
+        // 检查暂停状态,类似ffplay.c中的paused检查
+        bool pausedState = m_paused.load();
+        Logger::instance().debug("Video play thread loop - m_paused: " + std::to_string(pausedState));
+        if (pausedState) {
+            Logger::instance().info("Video play thread entering pause wait");
+            std::unique_lock<std::mutex> lock(m_pauseMutex);
+            m_pauseCondition.wait(lock, [this] { return !m_paused || m_threadsShouldStop; });
+            if (m_threadsShouldStop) {
+                break;
+            }
+            Logger::instance().info("Video play thread exiting pause wait");
+            // 暂停状态结束后,继续下一次循环
+            continue;
+        }
+        
         // 检查是否需要seek
         if (m_seeking) {
             std::unique_lock<std::mutex> lock(m_seekMutex);
@@ -1350,6 +1419,21 @@ void PlayerCoreV2::videoDecodeThreadFunc() {
     int packetCount = 0;
     int frameCount = 0;
     while (!m_threadsShouldStop) {
+        // 检查暂停状态,类似ffplay.c中的paused检查
+        bool pausedState = m_paused.load();
+        Logger::instance().debug("Video decode thread loop - m_paused: "
+                                 + std::to_string(pausedState));
+        if (pausedState) {
+            Logger::instance().info("Video decode thread entering pause wait");
+            std::unique_lock<std::mutex> lock(m_pauseMutex);
+            m_pauseCondition.wait(lock, [this] { return !m_paused || m_threadsShouldStop; });
+            if (m_threadsShouldStop) {
+                break;
+            }
+            Logger::instance().info("Video decode thread exiting pause wait");
+            // 暂停状态结束后,继续下一次循环
+            continue;
+        }
         if (!m_videoPacketQueue || !m_videoFrameQueue || !m_videoDecoder) {
             std::this_thread::sleep_for(std::chrono::milliseconds(10));
             continue;
@@ -1455,6 +1539,22 @@ void PlayerCoreV2::audioDecodeThreadFunc() {
     int packetCount = 0;
     int frameCount = 0;
     while (!m_threadsShouldStop) {
+        // 检查暂停状态,类似ffplay.c中的paused检查
+        bool pausedState = m_paused.load();
+        Logger::instance().debug("Audio decode thread loop - m_paused: "
+                                 + std::to_string(pausedState));
+        if (pausedState) {
+            Logger::instance().info("Audio decode thread entering pause wait");
+            std::unique_lock<std::mutex> lock(m_pauseMutex);
+            m_pauseCondition.wait(lock, [this] { return !m_paused || m_threadsShouldStop; });
+            if (m_threadsShouldStop) {
+                break;
+            }
+            Logger::instance().info("Audio decode thread exiting pause wait");
+            // 暂停状态结束后,继续下一次循环
+            continue;
+        }
+
         if (!m_audioPacketQueue || !m_audioFrameQueue || !m_audioDecoder) {
             std::this_thread::sleep_for(std::chrono::milliseconds(10));
             continue;
@@ -1556,13 +1656,35 @@ void PlayerCoreV2::videoPlayThreadFunc() {
     AVFrame* lastFrame = nullptr;
 
     while (!m_threadsShouldStop) {
+        // 检查暂停状态,类似ffplay.c中的paused检查
+        bool pausedState = m_paused.load();
+        Logger::instance().debug("Video play thread loop - m_paused: "
+                                 + std::to_string(pausedState));
+        if (pausedState) {
+            Logger::instance().info("Video play thread entering pause wait");
+            std::unique_lock<std::mutex> lock(m_pauseMutex);
+            m_pauseCondition.wait(lock, [this] { return !m_paused || m_threadsShouldStop; });
+            if (m_threadsShouldStop) {
+                break;
+            }
+            Logger::instance().info("Video play thread exiting pause wait");
+            // 暂停状态结束后,继续下一次循环
+            continue;
+        }
+
         if (!m_videoFrameQueue || !m_synchronizer) {
             std::this_thread::sleep_for(std::chrono::milliseconds(10));
             continue;
         }
 
-        // 获取视频帧,使用超时避免无限阻塞
-        AVFrame* frame = m_videoFrameQueue->pop(10); // 减少超时时间以提高seek响应速度
+        // 在pop之前再次检查暂停状态,避免在pop期间阻塞
+        if (m_paused.load()) {
+            Logger::instance().debug("Video play thread detected pause before pop");
+            continue;
+        }
+
+        // 获取视频帧,使用更短的超时时间以提高暂停响应速度
+        AVFrame* frame = m_videoFrameQueue->pop(1); // 使用1ms超时以快速响应暂停
         if (!frame) {
             // 检查是否应该继续等待
             if (m_threadsShouldStop) {
@@ -1572,6 +1694,15 @@ void PlayerCoreV2::videoPlayThreadFunc() {
             continue;
         }
 
+        // 获取帧后立即检查暂停状态,如果已暂停则释放帧并继续
+        bool pausedAfterPop = m_paused.load();
+        Logger::instance().debug("Video play thread after pop - m_paused: " + std::to_string(pausedAfterPop));
+        if (pausedAfterPop) {
+            Logger::instance().info("Video play thread releasing frame due to pause");
+            av_frame_free(&frame);
+            continue;
+        }
+
         Logger::instance().debug("Video play thread got frame, pts=" + std::to_string(frame->pts));
 
         // 创建智能指针管理帧内存
@@ -1580,7 +1711,7 @@ void PlayerCoreV2::videoPlayThreadFunc() {
         // 使用同步器计算视频帧显示时间
         double pts = frame->pts * av_q2d(m_formatContext->streams[m_mediaInfo.videoStreamIndex]->time_base);
         
-        // 更新视频时钟
+        // 只在非暂停状态下更新时钟和处理帧
         m_synchronizer->setClock(av::utils::ClockType::VIDEO, pts, 0);
         
         // 计算帧持续时间
@@ -1600,17 +1731,17 @@ void PlayerCoreV2::videoPlayThreadFunc() {
         
         // 计算视频帧延迟并决定是否显示
         FrameDecision decision = m_synchronizer->synchronizeVideo(pts, 0, last_duration);
-
+        
         if (decision.action == FrameAction::DISPLAY) {
             // 如果需要延迟显示,等待指定时间
             if (decision.delay > 0.0) {
                 std::this_thread::sleep_for(std::chrono::microseconds(static_cast<int64_t>(decision.delay * 1000000)));
             }
             
-            // 显示帧
-            if (m_openGLVideoRenderer) {
-                m_openGLVideoRenderer->Render(framePtr.get());
-                Logger::instance().debug("Video frame displayed, pts=" + std::to_string(pts) + ", delay=" + std::to_string(decision.delay));
+            // 通知显示帧
+            if (m_eventCallback) {
+                m_eventCallback->onVideoFrameReady(framePtr.get());
+                Logger::instance().debug("Video frame ready for display, pts=" + std::to_string(pts) + ", delay=" + std::to_string(decision.delay));
             }
             
             // 更新上一帧指针
@@ -1636,13 +1767,35 @@ void PlayerCoreV2::audioPlayThreadFunc() {
 
     int frameCount = 0;
     while (!m_threadsShouldStop) {
+        // 检查暂停状态,类似ffplay.c中的paused检查
+        bool pausedState = m_paused.load();
+        Logger::instance().debug("Audio play thread loop - m_paused: "
+                                 + std::to_string(pausedState));
+        if (pausedState) {
+            Logger::instance().info("Audio play thread entering pause wait");
+            std::unique_lock<std::mutex> lock(m_pauseMutex);
+            m_pauseCondition.wait(lock, [this] { return !m_paused || m_threadsShouldStop; });
+            if (m_threadsShouldStop) {
+                break;
+            }
+            Logger::instance().info("Audio play thread exiting pause wait");
+            // 暂停状态结束后,继续下一次循环
+            continue;
+        }
+
         if (!m_audioFrameQueue || !m_synchronizer || !m_audioOutput) {
             std::this_thread::sleep_for(std::chrono::milliseconds(10));
             continue;
         }
 
-        // 获取音频帧,使用较短的超时时间以提高seek响应速度
-        AVFrame* frame = m_audioFrameQueue->pop(10); // 减少超时时间以提高seek响应速度
+        // 在pop之前再次检查暂停状态,避免在pop期间阻塞
+        if (m_paused.load()) {
+            Logger::instance().debug("Audio play thread detected pause before pop");
+            continue;
+        }
+
+        // 获取音频帧,使用更短的超时时间以提高暂停响应速度
+        AVFrame* frame = m_audioFrameQueue->pop(1); // 使用1ms超时以快速响应暂停
         if (!frame) {
             // 检查是否应该继续等待
             if (m_threadsShouldStop) {
@@ -1651,7 +1804,16 @@ void PlayerCoreV2::audioPlayThreadFunc() {
             std::this_thread::sleep_for(std::chrono::milliseconds(10));
             continue;
         }
-
+        
+        // 获取帧后立即检查暂停状态,如果已暂停则释放帧并继续
+        bool pausedAfterPop = m_paused.load();
+        Logger::instance().debug("Audio play thread after pop - m_paused: " + std::to_string(pausedAfterPop));
+        if (pausedAfterPop) {
+            Logger::instance().info("Audio play thread releasing frame due to pause");
+            av_frame_free(&frame);
+            continue;
+        }
+        
         // 检查是否是EOF帧
         if (frame->data[0] == nullptr && frame->nb_samples == 0) {
             Logger::instance().info("Audio play thread received EOF frame, playback completed");
@@ -1675,7 +1837,7 @@ void PlayerCoreV2::audioPlayThreadFunc() {
         double pts = frame->pts
                      * av_q2d(m_formatContext->streams[m_mediaInfo.audioStreamIndex]->time_base);
 
-        // 更新音频时钟
+        // 只在非暂停状态下更新音频时钟
         m_synchronizer->setClock(av::utils::ClockType::AUDIO, pts, 0);
 
         // 同步音频样本数量
@@ -1688,7 +1850,9 @@ void PlayerCoreV2::audioPlayThreadFunc() {
             Logger::instance().debug("Audio samples adjusted from " + std::to_string(originalSamples)
                                      + " to " + std::to_string(adjustedSamples) + " for sync");
         }
-
+        if (m_paused) {
+            continue;
+        }
         {
             Logger::instance().debug("Writing audio frame to output device");
             bool writeResult = m_audioOutput->writeFrame(framePtr);

+ 13 - 6
AV/code/player/player_core_v2.h

@@ -11,7 +11,6 @@
 #include "../utils/utils_packet_queue.h"
 #include "../utils/utils_synchronizer_v2.h"
 #include "audio_output.h"
-#include "../../AvRecorder/ui/opengl_video_widget.h"
 
 #include <memory>
 #include <atomic>
@@ -123,6 +122,11 @@ public:
     virtual void onEndOfFile() = 0;
     virtual void onSyncError(double error, const std::string& reason) = 0;
     virtual void onFrameDropped(int64_t count) = 0;
+    
+    // 视频渲染相关回调
+    virtual void onVideoFrameReady(AVFrame* frame) = 0;
+    virtual void onVideoRendererInitRequired(int width, int height) = 0;
+    virtual void onVideoRendererCloseRequired() = 0;
 };
 
 /**
@@ -173,9 +177,9 @@ public:
     void setSyncConfig(const SyncConfigV2& config);
     SyncConfigV2 getSyncConfig() const;
 
-    // OpenGL渲染器设置
-    void setOpenGLVideoRenderer(OpenGLVideoWidget* renderer);
-    OpenGLVideoWidget* getOpenGLVideoRenderer() const { return m_openGLVideoRenderer; }
+    // 视频渲染器设置(已废弃,请使用PlayerEventCallback中的视频渲染回调)
+    // void setOpenGLVideoRenderer(OpenGLVideoWidget* renderer);
+    // OpenGLVideoWidget* getOpenGLVideoRenderer() const { return m_openGLVideoRenderer; }
     
     // 帧获取接口(供UI渲染使用)
     AVFrame* getNextVideoFrame();   // 获取下一个视频帧
@@ -278,8 +282,8 @@ private:
     // 音频输出
     std::unique_ptr<AudioOutput> m_audioOutput;
     
-    // 视频渲染
-    OpenGLVideoWidget* m_openGLVideoRenderer = nullptr;
+    // 视频渲染(已移除直接依赖,改为使用回调)
+    // OpenGLVideoWidget* m_openGLVideoRenderer = nullptr;
     
     // 播放控制
     std::atomic<double> m_volume{1.0};
@@ -313,6 +317,9 @@ private:
     // 线程控制
     std::atomic<bool> m_threadsShouldStop{false};
     std::atomic<bool> m_threadsRunning{false};
+    std::atomic<bool> m_paused{false};  // 暂停标志,类似ffplay.c中的paused
+    std::condition_variable m_pauseCondition;  // 暂停条件变量,类似ffplay.c中的continue_read_thread
+    std::mutex m_pauseMutex;  // 暂停互斥锁
     
     // 初始化标志
     std::atomic<bool> m_initialized{false};

+ 21 - 15
AV/code/utils/utils_synchronizer_v2.cpp

@@ -1,4 +1,6 @@
 #include "utils_synchronizer_v2.h"
+#include "qdebug.h"
+#include "qglobal.h"
 #include <algorithm>
 #include <cmath>
 #include <iostream>
@@ -106,13 +108,13 @@ ErrorCode SynchronizerV2::pause() {
     if (m_paused) {
         return ErrorCode::SUCCESS;
     }
-    
-    // 设置时钟暂停状态
-    std::lock_guard<std::mutex> lock(m_clockMutex);
-    m_audioClock.paused = true;
-    m_videoClock.paused = true;
-    m_externalClock.paused = true;
-    
+    {
+        // 设置时钟暂停状态
+        std::lock_guard<std::mutex> lock(m_clockMutex);
+        m_audioClock.paused = true;
+        m_videoClock.paused = true;
+        m_externalClock.paused = true;
+    }
     m_paused = true;
     
     return ErrorCode::SUCCESS;
@@ -127,13 +129,14 @@ ErrorCode SynchronizerV2::resume() {
     if (!m_paused) {
         return ErrorCode::SUCCESS;
     }
-    
-    // 恢复时钟暂停状态
-    std::lock_guard<std::mutex> lock(m_clockMutex);
-    m_audioClock.paused = false;
-    m_videoClock.paused = false;
-    m_externalClock.paused = false;
-    
+    // 防止互斥死锁
+    {
+        // 恢复时钟暂停状态
+        std::lock_guard<std::mutex> lock(m_clockMutex);
+        m_audioClock.paused = false;
+        m_videoClock.paused = false;
+        m_externalClock.paused = false;
+    }
     // 更新外部时钟
     updateExternalClock();
     
@@ -250,7 +253,9 @@ void SynchronizerV2::setClock(ClockType type, double pts, int serial) {
 // 在指定时间设置时钟
 void SynchronizerV2::setClockAt(ClockType type, double pts, int serial, double time) {
     std::lock_guard<std::mutex> lock(m_clockMutex);
-    
+    if (m_paused) {
+        qDebug() << "setClockAt-->:" << (int) type << pts << serial << time;
+    }
     Clock* clock = nullptr;
     switch (type) {
         case ClockType::AUDIO:
@@ -629,6 +634,7 @@ std::string SynchronizerV2::getDebugInfo() const {
     ss << "  Streams: " << (m_hasAudio ? "Audio" : "No Audio")
        << ", " << (m_hasVideo ? "Video" : "No Video") << "\n";
     ss << "  Sync Strategy: " << strategyStr << "\n";
+    ss << "  CurrentTime: " << getCurrentTime() << "\n";
     ss << "  Master Clock Type: " << masterTypeStr << "\n";
     ss << "  Clocks (seconds):\n";
     ss << "    Audio: " << audioClock << "\n";

+ 122 - 208
AV/test_player_with_ui.cpp

@@ -6,6 +6,13 @@
 #include "code/base/logger.h"
 #include "code/player/player_core_v2.h"
 
+#include "../../AvRecorder/ui/opengl_video_widget.h"
+#include "qobject.h"
+extern "C" {
+#include <libavutil/frame.h>
+#include <libavutil/imgutils.h>
+}
+
 #include <QApplication>
 #include <QWidget>
 #include <QVBoxLayout>
@@ -27,6 +34,7 @@
 #include <QDateTime>
 #include <QFile>
 #include <QTextStream>
+#include <QMetaObject>
 
 using namespace av::player;
 using namespace av::utils;
@@ -34,7 +42,8 @@ using namespace av::utils;
 // 播放器事件回调类
 class UIPlayerCallback : public PlayerEventCallback {
 public:
-    UIPlayerCallback(QWidget* parent) : m_parent(parent) {}
+    UIPlayerCallback(QWidget* parent, OpenGLVideoWidget* videoRenderer) 
+        : m_parent(parent), m_videoRenderer(videoRenderer) {}
     
     void onStateChanged(PlayerState newState) override {
         std::string stateStr;
@@ -98,8 +107,55 @@ public:
         QMetaObject::invokeMethod(m_parent, "onPlayerEndOfFile", Qt::QueuedConnection);
     }
     
+    // 新增的视频渲染回调函数
+    void onVideoFrameReady(AVFrame* frameData) override
+    {
+        if (m_videoRenderer) {
+            // 将 frameData 转换为 AVFrame* 并进行深度拷贝
+            AVFrame* originalFrame = static_cast<AVFrame*>(frameData);
+            AVFrame* copiedFrame = av_frame_clone(originalFrame);
+            
+            if (copiedFrame) {
+                // 使用 QueuedConnection 避免死锁
+                // 当播放器暂停时,如果使用 BlockingQueuedConnection 可能导致死锁
+                // 因为暂停操作会等待播放线程停止,而播放线程可能正在等待UI线程响应
+                bool renderResult = false;
+                QMetaObject::invokeMethod(m_videoRenderer,
+                                          "Render",
+                                          Qt::QueuedConnection,
+                                          Q_ARG(AVFrame*, copiedFrame));
+
+                // 注意:使用QueuedConnection时,copiedFrame的释放需要在Render方法内部处理
+                // 这里不能立即释放,因为调用是异步的
+                // OpenGLVideoWidget::Render方法需要负责释放传入的AVFrame*
+            }
+        }
+    }
+
+    void onVideoRendererInitRequired(int width, int height) override
+    {
+        if (m_videoRenderer) {
+            Logger::instance().info("[EVENT] Video renderer init required: " + 
+                                  std::to_string(width) + "x" + std::to_string(height));
+            // QMetaObject::invokeMethod(m_videoRenderer, "Open", Qt::QueuedConnection,
+            //                         Q_ARG(int, width),
+            //                         Q_ARG(int, height),
+            //                         Q_ARG(int, pixelFormat),
+            //                         Q_ARG(double, fps));
+        }
+    }
+
+    void onVideoRendererCloseRequired() override
+    {
+        if (m_videoRenderer) {
+            Logger::instance().info("[EVENT] Video renderer close required");
+            // QMetaObject::invokeMethod(m_videoRenderer, "Close", Qt::QueuedConnection);
+        }
+    }
+
 private:
     QWidget* m_parent;
+    OpenGLVideoWidget* m_videoRenderer;
 };
 
 // 主播放器窗口类
@@ -206,13 +262,8 @@ public slots:
             if (info.hasVideo) {
                 infoText += QString("视频: %1x%2 @ %3fps\n")
                            .arg(info.width).arg(info.height).arg(info.fps, 0, 'f', 2);
-                           
-                // 初始化视频渲染器
-                // if (m_videoRenderer && !m_videoRenderer->isInitialized()) {
-                //     m_videoRenderer->initialize(info.width, info.height, AV_PIX_FMT_YUV420P, info.fps);
-                // }
             }
-            
+
             // 更新音频流复选框状态
             m_audioStreamCheckBox->setEnabled(info.hasAudio);
             if (!info.hasAudio) {
@@ -270,145 +321,9 @@ private slots:
             QMessageBox::information(this, "统计信息", "统计信息已刷新,详细信息已写入日志文件。");
         }
     }
-    
-    void exportStats() {
-        if (!m_player) return;
-        
-        // 获取保存文件名
-        QString fileName = QFileDialog::getSaveFileName(this,
-            "导出统计信息", "player_stats.txt",
-            "文本文件 (*.txt);;所有文件 (*.*)");
-            
-        if (fileName.isEmpty()) return;
-        
-        // 获取统计信息
-        auto stats = m_player->getStats();
-        auto mediaInfo = m_player->getMediaInfo();
-        auto debugInfo = QString::fromStdString(m_player->getDebugInfo());
-        
-        // 创建文件
-        QFile file(fileName);
-        if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
-            QMessageBox::critical(this, "错误", "无法创建文件: " + fileName);
-            return;
-        }
-        
-        QTextStream out(&file);
-        
-        // 写入时间戳
-        auto now = QDateTime::currentDateTime();
-        out << "播放器统计信息导出 - " << now.toString("yyyy-MM-dd HH:mm:ss") << "\n\n";
-        
-        // 写入媒体信息
-        out << "=== 媒体信息 ===\n";
-        out << "文件: " << QString::fromStdString(mediaInfo.filename) << "\n";
-        out << "时长: " << (mediaInfo.duration / 1000000.0) << " 秒\n";
-        if (mediaInfo.hasVideo) {
-            out << "视频: " << mediaInfo.width << "x" << mediaInfo.height << " @ " << mediaInfo.fps << " fps\n";
-        }
-        if (mediaInfo.hasAudio) {
-            out << "音频: " << mediaInfo.sampleRate << " Hz, " << mediaInfo.channels << " 通道\n";
-        }
-        out << "比特率: " << (mediaInfo.bitrate / 1000.0) << " kbps\n\n";
-        
-        // 写入播放统计
-        out << "=== 播放统计 ===\n";
-        out << "当前位置: " << (stats.currentTime / 1000000.0) << " 秒\n";
-        out << "总帧数: " << stats.totalFrames << "\n";
-        out << "丢帧数: " << stats.droppedFrames;
-        if (stats.totalFrames > 0) {
-            out << " (" << (stats.droppedFrames * 100.0 / stats.totalFrames) << "%)";
-        }
-        out << "\n";
-        out << "重复帧数: " << stats.duplicatedFrames << "\n";
-        out << "播放速度: " << stats.playbackSpeed << "x\n\n";
-        
-        // 写入队列状态
-        out << "=== 队列状态 ===\n";
-        out << "视频帧队列: " << stats.queuedVideoFrames << "\n";
-        out << "音频帧队列: " << stats.queuedAudioFrames << "\n";
-        out << "数据包队列: " << stats.queuedPackets << "\n\n";
-        
-        // 写入同步状态
-        out << "=== 同步状态 ===\n";
-        out << "当前同步误差: " << (stats.syncError * 1000) << " ms\n";
-        out << "平均同步误差: " << (stats.avgSyncError * 1000) << " ms\n";
-        out << "最大同步误差: " << (stats.maxSyncError * 1000) << " ms\n\n";
-        
-        // 写入详细时钟信息
-        out << "=== 时钟信息 ===\n";
-        if (m_player) {
-            auto debugInfo = QString::fromStdString(m_player->getDebugInfo());
-            QStringList lines = debugInfo.split('\n');
-            
-            for (const QString& line : lines) {
-                if (line.trimmed().startsWith("Audio:")) {
-                    QStringList parts = line.split(":");
-                    if (parts.size() >= 2) {
-                        bool ok;
-                        double value = parts[1].trimmed().toDouble(&ok);
-                        if (ok) {
-                            out << "音频时钟: " << value << " 秒\n";
-                        }
-                    }
-                } else if (line.trimmed().startsWith("Video:")) {
-                    QStringList parts = line.split(":");
-                    if (parts.size() >= 2) {
-                        bool ok;
-                        double value = parts[1].trimmed().toDouble(&ok);
-                        if (ok) {
-                            out << "视频时钟: " << value << " 秒\n";
-                        }
-                    }
-                } else if (line.trimmed().startsWith("External:")) {
-                    QStringList parts = line.split(":");
-                    if (parts.size() >= 2) {
-                        bool ok;
-                        double value = parts[1].trimmed().toDouble(&ok);
-                        if (ok) {
-                            out << "外部时钟: " << value << " 秒\n";
-                        }
-                    }
-                } else if (line.trimmed().startsWith("Master:")) {
-                    QStringList parts = line.split(":");
-                    if (parts.size() >= 2) {
-                        bool ok;
-                        double value = parts[1].trimmed().toDouble(&ok);
-                        if (ok) {
-                            out << "主时钟: " << value << " 秒\n";
-                        }
-                    }
-                } else if (line.contains("Master Clock Type:")) {
-                    QStringList parts = line.split(":");
-                    if (parts.size() >= 2) {
-                        out << "主时钟类型: " << parts[1].trimmed() << "\n";
-                    }
-                } else if (line.contains("Sync Strategy:")) {
-                    QStringList parts = line.split(":");
-                    if (parts.size() >= 2) {
-                        out << "同步策略: " << parts[1].trimmed() << "\n";
-                    }
-                }
-            }
-        }
-        out << "\n";
 
-        // 写入性能统计
-        out << "=== 性能统计 ===\n";
-        out << "CPU使用率: " << stats.cpuUsage << "%\n";
-        out << "内存使用: " << stats.memoryUsage << " MB\n";
-        out << "比特率: " << stats.bitrate << " kbps\n\n";
-        
-        // 写入调试信息
-        out << "=== 调试信息 ===\n";
-        out << debugInfo << "\n";
-        
-        file.close();
-        
-        QMessageBox::information(this, "导出成功", "统计信息已成功导出到: " + fileName);
-    }
-    
-    void playPause() {
+    void playPause()
+    {
         if (!m_player) return;
         
         auto state = m_player->getState();
@@ -418,17 +333,16 @@ private slots:
             m_player->play();
         }
     }
-    
-    void stop() {
+
+    void stop()
+    {
         if (m_player) {
             m_player->stop();
         }
     }
-    
-    void onProgressSliderPressed() {
-        m_seeking = true;
-    }
-    
+
+    void onProgressSliderPressed() { m_seeking = true; }
+
     void onProgressSliderReleased() {
         if (m_player && m_duration > 0) {
             int value = m_progressSlider->value();
@@ -559,17 +473,20 @@ private slots:
                         }
                     }
                 }
-                
-                syncText = QString("\n\n同步状态:\n当前误差: %1 ms\n平均误差: %2 ms\n最大误差: %3 ms\n\n时钟信息:\n音频时钟: %4\n视频时钟: %5\n外部时钟: %6\n主时钟: %7\n\n同步配置:\n主时钟类型: %8\n同步策略: %9")
-                          .arg(stats.syncError * 1000, 0, 'f', 1)
-                          .arg(stats.avgSyncError * 1000, 0, 'f', 1)
-                          .arg(stats.maxSyncError * 1000, 0, 'f', 1)
-                          .arg(audioClockStr)
-                          .arg(videoClockStr)
-                          .arg(externalClockStr)
-                          .arg(masterClockStr)
-                          .arg(masterTypeStr)
-                          .arg(syncStrategyStr);
+                statsText += debugInfo;
+
+                syncText = QString("\n\n同步状态:\n当前误差: %1 ms\n平均误差: %2 ms\n最大误差: %3 "
+                                   "ms\n\n时钟信息:\n音频时钟: %4\n视频时钟: %5\n外部时钟: "
+                                   "%6\n主时钟: %7\n\n同步配置:\n主时钟类型: %8\n同步策略: %9")
+                               .arg(stats.syncError * 1000, 0, 'f', 1)
+                               .arg(stats.avgSyncError * 1000, 0, 'f', 1)
+                               .arg(stats.maxSyncError * 1000, 0, 'f', 1)
+                               .arg(audioClockStr)
+                               .arg(videoClockStr)
+                               .arg(externalClockStr)
+                               .arg(masterClockStr)
+                               .arg(masterTypeStr)
+                               .arg(syncStrategyStr);
             } else {
                 syncText = syncText.arg(stats.syncError * 1000, 0, 'f', 1)
                                  .arg(stats.avgSyncError * 1000, 0, 'f', 1)
@@ -579,13 +496,13 @@ private slots:
             statsText += syncText;
             
             // 性能统计
-            statsText += QString("\n\n性能:\nCPU: %1%\n内存: %2 MB\n比特率: %3 kbps")
-                         .arg(stats.cpuUsage, 0, 'f', 1)
-                         .arg(stats.memoryUsage, 0, 'f', 1)
-                         .arg(stats.bitrate, 0, 'f', 0);
-            
+            // statsText += QString("\n\n性能:\nCPU: %1%\n内存: %2 MB\n比特率: %3 kbps")
+            //              .arg(stats.cpuUsage, 0, 'f', 1)
+            //              .arg(stats.memoryUsage, 0, 'f', 1)
+            //              .arg(stats.bitrate, 0, 'f', 0);
+
             m_statsLabel->setText(statsText);
-            
+
             // 更新时间显示和进度条
             if (!m_seeking && m_duration > 0) {
                 int64_t currentPosition = m_player->getCurrentTime();
@@ -710,9 +627,7 @@ private:
         // 添加刷新和导出按钮
         auto* refreshLayout = new QHBoxLayout();
         m_refreshStatsButton = new QPushButton("刷新统计");
-        m_exportStatsButton = new QPushButton("导出统计");
         refreshLayout->addWidget(m_refreshStatsButton);
-        refreshLayout->addWidget(m_exportStatsButton);
         refreshLayout->addStretch();
         statsLayout->addLayout(refreshLayout);
         
@@ -748,14 +663,14 @@ private:
         // 创建播放器实例
         m_player = std::make_unique<PlayerCoreV2>(syncConfig);
         
-        // 设置视频渲染器
-        m_player->setOpenGLVideoRenderer(m_videoRenderer);
+        // 注意:不再直接设置视频渲染器,而是通过回调机制处理
+        // m_player->setOpenGLVideoRenderer(m_videoRenderer); // 已废弃
         
         // 设置初始音量
         m_player->setVolume(m_volumeSlider->value() / 100.0);
         
-        // 创建事件回调
-        m_callback = std::make_unique<UIPlayerCallback>(this);
+        // 创建事件回调,传入视频渲染器
+        m_callback = std::make_unique<UIPlayerCallback>(this, m_videoRenderer);
         m_player->setEventCallback(m_callback.get());
         
         m_duration = 0;
@@ -787,7 +702,6 @@ private:
         
         // 连接统计按钮信号
         connect(m_refreshStatsButton, &QPushButton::clicked, this, &PlayerWindow::refreshStats);
-        connect(m_exportStatsButton, &QPushButton::clicked, this, &PlayerWindow::exportStats);
     }
     
     void loadFile(const std::string& filename) {
@@ -816,7 +730,6 @@ private:
     QPushButton* m_playButton;
     QPushButton* m_stopButton;
     QPushButton* m_refreshStatsButton;
-    QPushButton* m_exportStatsButton;
     QSlider* m_progressSlider;
     QSlider* m_volumeSlider;
     QLabel* m_stateLabel;
@@ -842,38 +755,39 @@ int main(int argc, char* argv[]) {
     // 初始化日志系统
     Logger::instance().initialize("test.log", LogLevel::DEBUG, false, false);
     Logger::instance().info("PlayerCoreV2 Example Started");
-    
-    try {
-        // 创建播放器窗口
-        PlayerWindow window;
-        window.show();
-        
-        // 如果有命令行参数,自动加载文件
-        // if (argc > 1) {
-        //     QTimer::singleShot(500, [&window, argv]() {
-        //         QMetaObject::invokeMethod(&window, "loadFile", Qt::QueuedConnection,
-        //                                 Q_ARG(std::string, std::string(argv[1])));
-        //     });
-        // } else {
-        //     // 默认加载测试文件
-        //     QTimer::singleShot(500, [&window]() {
-        //         std::string testFile = "C:/Users/zhuizhu/Videos/2.mp4";
-        //         QMetaObject::invokeMethod(&window, "loadFile", Qt::QueuedConnection,
-        //                                 Q_ARG(std::string, testFile));
-        //     });
-        // }
 
-        return app.exec();
-        
-    } catch (const std::exception& e) {
-        Logger::instance().error("Exception: " + std::string(e.what()));
-        QMessageBox::critical(nullptr, "错误", QString("发生异常: %1").arg(e.what()));
-        return 1;
-    } catch (...) {
-        Logger::instance().error("Unknown exception occurred");
-        QMessageBox::critical(nullptr, "错误", "发生未知异常");
-        return 1;
-    }
+    qRegisterMetaType<AVFrame*>("AVFrame*");
+    // try {
+    // 创建播放器窗口
+    PlayerWindow window;
+    window.show();
+
+    // 如果有命令行参数,自动加载文件
+    // if (argc > 1) {
+    //     QTimer::singleShot(500, [&window, argv]() {
+    //         QMetaObject::invokeMethod(&window, "loadFile", Qt::QueuedConnection,
+    //                                 Q_ARG(std::string, std::string(argv[1])));
+    //     });
+    // } else {
+    //     // 默认加载测试文件
+    //     QTimer::singleShot(500, [&window]() {
+    //         std::string testFile = "C:/Users/zhuizhu/Videos/2.mp4";
+    //         QMetaObject::invokeMethod(&window, "loadFile", Qt::QueuedConnection,
+    //                                 Q_ARG(std::string, testFile));
+    //     });
+    // }
+
+    return app.exec();
+
+    // } catch (const std::exception& e) {
+    //     Logger::instance().error("Exception: " + std::string(e.what()));
+    //     QMessageBox::critical(nullptr, "错误", QString("发生异常: %1").arg(e.what()));
+    //     return 1;
+    // } catch (...) {
+    //     Logger::instance().error("Unknown exception occurred");
+    //     QMessageBox::critical(nullptr, "错误", "发生未知异常");
+    //     return 1;
+    // }
 }
 
 #include "test_player_with_ui.moc"