zhuizhu 8 tháng trước cách đây
mục cha
commit
6fca0fb86b
1 tập tin đã thay đổi với 43 bổ sung34 xóa
  1. 43 34
      AvPlayer2/playercontroller.cpp

+ 43 - 34
AvPlayer2/playercontroller.cpp

@@ -8,13 +8,10 @@
 #include <cassert>
 #include <memory>
 
-#include "ffmpeg_init.h"
-#include "start_play_thread.h"
-#include "video_state.h"
-
 #include "audio_decode_thread.h"
 #include "audio_effect_helper.h"
 #include "audio_play_thread.h"
+#include "ffmpeg_init.h"
 #include "play_control_window.h"
 #include "read_thread.h"
 #include "start_play_thread.h"
@@ -44,40 +41,59 @@ PlayerController::~PlayerController()
 
 void PlayerController::startToPlay(const QString& file)
 {
-    std::lock_guard<std::mutex> lock(m_stopMutex);
-    qCDebug(playerControllerLog) << "[PlayerController] m_state" << (int) m_state.load();
-
-    // 自愈:如果状态为Playing但所有线程都已退出,强制Idle
-    if (m_state == PlayerState::Playing && areAllThreadsStopped()) {
-        stopAndResetThreads();
-        m_videoState.reset();
-        m_currentFile.clear();
-        m_state = PlayerState::Idle;
-        qCDebug(playerControllerLog)
-            << "[PlayerController] All threads stopped, force reset to Idle.";
+    // 使用局部变量保存当前状态,避免在锁外使用成员变量
+    PlayerState currentState = m_state;
+    QString currentFile = m_currentFile;
+
+    {
+        std::lock_guard<std::mutex> lock(m_stopMutex);
+        qCDebug(playerControllerLog) << "[PlayerController] m_state" << (int) m_state.load();
+        
+        // 自愈:如果状态为Playing但所有线程都已退出,强制Idle
+        if (m_state == PlayerState::Playing && areAllThreadsStopped()) {
+            stopAndResetThreads();
+            m_videoState.reset();
+            m_currentFile.clear();
+            m_state = PlayerState::Idle;
+            qCDebug(playerControllerLog)
+                << "[PlayerController] All threads stopped, force reset to Idle.";
+        }
+        
+        currentState = m_state;
+        currentFile = m_currentFile;
     }
 
     // 初始化中,忽略新请求
-    if (m_state == PlayerState::Initializing) {
+    if (currentState == PlayerState::Initializing) {
         qCDebug(playerControllerLog) << "Player is initializing. Ignoring request.";
         return;
     }
 
     // 正在播放中,检查是否需要切换文件
-    if (m_state == PlayerState::Playing) {
-        if (m_currentFile == file) {
+    if (currentState == PlayerState::Playing) {
+        if (currentFile == file) {
             qCDebug(playerControllerLog) << "Already playing the same file. Ignoring request.";
             return;
         } else {
             qCDebug(playerControllerLog)
                 << "Player is busy with another file, stopping and switching to:" << file;
+            // 在锁外调用stopPlay,避免死锁
             stopPlay();
-            // 这里直接 fallthrough 到 Idle 状态
+            // 停止后重新获取状态
+            currentState = PlayerState::Idle; // 假设stopPlay会将状态设为Idle
         }
     }
 
     // 空闲状态,开始新播放
-    if (m_state == PlayerState::Idle) {
+    if (currentState == PlayerState::Idle) {
+        std::lock_guard<std::mutex> lock(m_stopMutex);
+        
+        // 再次检查状态,确保在获取锁的过程中状态没有改变
+        if (m_state != PlayerState::Idle) {
+            qCDebug(playerControllerLog) << "State changed while waiting for lock. Current state:" << (int)m_state.load();
+            return;
+        }
+        
         // 确保所有线程已停止
         if (!areAllThreadsStopped()) {
             qCDebug(playerControllerLog) << "Some threads still running, stopping them first";
@@ -131,7 +147,7 @@ void PlayerController::asyncInit(const QString& file)
 
 void PlayerController::onAsyncInitFinished(const QString& file, bool success)
 {
-    std::lock_guard<std::mutex> lock(m_stopMutex);
+    // 移除互斥锁,避免与stopPlay产生死锁
     QElapsedTimer timer;
     timer.start();
 
@@ -224,7 +240,7 @@ void PlayerController::onAsyncInitFinished(const QString& file, bool success)
 
 void PlayerController::stopPlay()
 {
-    std::lock_guard<std::mutex> lock(m_stopMutex);
+    // 移除互斥锁,避免与startToPlay中的锁冲突
     if (m_state == PlayerState::Idle)
         return;
 
@@ -387,14 +403,9 @@ void PlayerController::readPacketStopped()
     dump();
     qCDebug(playerControllerLog) << "************* Read packets thread stopped signal received.";
 
-    auto state = m_videoState->get_state();
-    // if (state) {
-    //     state->abort_request = 1;
-    // }
-    if (m_videoState && m_videoState->get_state()) {
-        m_videoState->delete_video_state(); // stream_close
-    }
-
+    // 不在这里调用delete_video_state,避免与stopAndResetThreads中的调用重复
+    // 资源清理统一由stopAndResetThreads处理
+    
     emit audioStopped();
 }
 
@@ -643,13 +654,11 @@ void PlayerController::stopAndResetThreads()
     stopAndReset(m_audioPlayThread, "AudioPlay");
 
     // 解码前先 关闭流 不然会卡死异常
+    // 注意:这里是唯一调用delete_video_state的地方,readPacketStopped不再调用
+    // 以避免重复关闭导致的异常
     if (m_videoState && m_videoState->get_state()) {
         m_videoState->delete_video_state();
     }
-    // auto state = m_videoState->get_state();
-    // if (state) {
-    //     state->abort_request = 1;
-    // }
     stopAndReset(m_packetReadThread, "PacketRead");
 
     stopAndReset(m_decodeVideoThread, "DecodeVideo");