zhuizhu 8 bulan lalu
induk
melakukan
dde93ff879

+ 0 - 2
AvPlayer2/AvPlayer2.pri

@@ -22,7 +22,6 @@ HEADERS += \
     $$PWD/start_play_thread.h \
     $$PWD/stopplay_waiting_thread.h \
     $$PWD/subtitle_decode_thread.h \
-    $$PWD/thread_manager.h \
     $$PWD/version.h \
     $$PWD/video_decode_thread.h \
     $$PWD/video_play_thread.h \
@@ -50,7 +49,6 @@ SOURCES += \
     $$PWD/start_play_thread.cpp \
     $$PWD/stopplay_waiting_thread.cpp \
     $$PWD/subtitle_decode_thread.cpp \
-    $$PWD/thread_manager.cpp \
     $$PWD/video_decode_thread.cpp \
     $$PWD/video_play_thread.cpp \
     $$PWD/video_state.cpp

+ 1 - 1
AvPlayer2/audio_decode_thread.cpp

@@ -55,7 +55,7 @@ void AudioDecodeThread::run()
             qCDebug(playerControllerAudioDecodeThread) << "[AudioDecodeThread] abort_request set, exit.";
             break;
         }
-        if (m_exit && *m_exit) {
+        if (isExit()) {
             qCDebug(playerControllerAudioDecodeThread) << "[AudioDecodeThread] m_exit set, exit.";
             break;
         }

+ 0 - 5
AvPlayer2/audio_decode_thread.h

@@ -5,15 +5,10 @@
 
 #include "ThreadBase.h"
 #include "packets_sync.h"
-#include <atomic>
 
 class AudioDecodeThread : public ThreadBase
 {
 public:
-    AudioDecodeThread(const AudioDecodeThread&) = delete;
-    AudioDecodeThread& operator=(const AudioDecodeThread&) = delete;
-    AudioDecodeThread(AudioDecodeThread&&) = delete;
-    AudioDecodeThread& operator=(AudioDecodeThread&&) = delete;
     explicit AudioDecodeThread(VideoState* pState = nullptr);
     ~AudioDecodeThread();
 

+ 2 - 2
AvPlayer2/audio_play_thread.cpp

@@ -164,7 +164,7 @@ void AudioPlayThread::run()
     int audio_size;
     int loop_count = 0;
     for (;;) {
-        if (m_exit && *m_exit) {
+        if (isExit()) {
             qCDebug(playerControllerAudioPlayThread) << "[AudioPlayThread] m_exit set, exit.";
             break;
         }
@@ -175,7 +175,7 @@ void AudioPlayThread::run()
         if (is->paused) {
             qCDebug(playerControllerAudioPlayThread) << "[AudioPlayThread] paused, wait.";
             std::unique_lock<std::mutex> lock(m_mutex);
-            m_cv.wait_for(lock, std::chrono::milliseconds(10), [this] { return m_exit && *m_exit; });
+            m_cv.wait_for(lock, std::chrono::milliseconds(10), [this] { return isExit(); });
             continue;
         }
         qCDebug(playerControllerAudioPlayThread)

+ 3 - 9
AvPlayer2/mainwindowa.cpp

@@ -1,12 +1,4 @@
-// ***********************************************************/
-// mainwindow.cpp
-//
-//      Copy Right @ Steven Huang. All rights reserved.
-//
-// mainwindow of player
-// ***********************************************************/
-
-#include "mainwindowa.h"
+#include "mainwindowa.h"
 #include "common.h"
 
 #include <QApplication>
@@ -311,6 +303,8 @@ MainWindowA::MainWindowA(QWidget* parent)
     connect(m_playerController, &PlayerController::playSeek, this, &MainWindowA::play_seek);
 
     hide_play_control(false);
+
+    m_playerController->startToPlay("C:/Users/zhuizhu/Videos/1.mp4");
 }
 
 MainWindowA::~MainWindowA()

+ 12 - 15
AvPlayer2/packets_sync.cpp

@@ -1,18 +1,6 @@
-// ***********************************************************/
-// packets_sync.cpp
-//
-//      Copy Right @ Steven Huang. All rights reserved.
-//
-// packets A/V synchronization struct and operations definition.
-// This code is referenced from ffplay.c in Ffmpeg library.
-// ***********************************************************/
-
 #include "packets_sync.h"
 
 int framedrop = -1;
-// static int decoder_reorder_pts = -1;
-// static int display_disable = 1;
-// static int64_t audio_callback_time;
 
 int packet_queue_init(PacketQueue* q)
 {
@@ -484,7 +472,6 @@ int decoder_decode_frame(Decoder* d, AVFrame* frame, AVSubtitle* sub)
         do {
             if (d->queue->nb_packets == 0)
                 d->empty_queue_cond->wakeAll();
-
             if (d->packet_pending) {
                 d->packet_pending = 0;
             } else {
@@ -516,11 +503,21 @@ int decoder_decode_frame(Decoder* d, AVFrame* frame, AVSubtitle* sub)
             }
             av_packet_unref(d->pkt);
         } else {
+            if (d->pkt->buf && !d->pkt->opaque_ref) {
+                FrameData* fd;
+
+                d->pkt->opaque_ref = av_buffer_allocz(sizeof(*fd));
+                if (!d->pkt->opaque_ref)
+                    return AVERROR(ENOMEM);
+                fd = (FrameData*) d->pkt->opaque_ref->data;
+                fd->pkt_pos = d->pkt->pos;
+            }
+
             if (avcodec_send_packet(d->avctx, d->pkt) == AVERROR(EAGAIN)) {
                 av_log(d->avctx,
                        AV_LOG_ERROR,
-                       "Receive_frame and send_packet both returned EAGAIN, which is "
-                       "an API violation.\n");
+                       "Receive_frame and send_packet both returned EAGAIN, which is an API "
+                       "violation.\n");
                 d->packet_pending = 1;
             } else {
                 av_packet_unref(d->pkt);

+ 142 - 71
AvPlayer2/playercontroller.cpp

@@ -30,10 +30,7 @@ PlayerController::PlayerController(QWidget* parent)
     : QObject(parent)
 {
     ffmpeg_init();
-    connect(this,
-            &PlayerController::asyncInitFinished,
-            this,
-            &PlayerController::onAsyncInitFinished);
+
     m_state = PlayerState::Idle;
 }
 
@@ -48,11 +45,56 @@ 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();
+    qDebug() << "[PlayerController] checkAndResetState: "
+             << "m_packetReadThread:" << (bool) m_packetReadThread
+             << "m_decodeVideoThread:" << (bool) m_decodeVideoThread
+             << "m_decodeAudioThread:" << (bool) m_decodeAudioThread
+             << "m_audioPlayThread:" << (bool) m_audioPlayThread
+             << "m_videoPlayThread:" << (bool) m_videoPlayThread
+             << "m_decodeSubtitleThread:" << (bool) m_decodeSubtitleThread << Qt::endl
+             << "m_packetReadThread:"
+             << (m_packetReadThread ? m_packetReadThread->isRunning() : false)
+             << "m_decodeVideoThread:"
+             << (m_decodeVideoThread ? m_decodeVideoThread->isRunning() : false)
+             << "m_decodeAudioThread:"
+             << (m_decodeAudioThread ? m_decodeAudioThread->isRunning() : false)
+             << "m_audioPlayThread:" << (m_audioPlayThread ? m_audioPlayThread->isRunning() : false)
+             << "m_videoPlayThread:" << (m_videoPlayThread ? m_videoPlayThread->isRunning() : false)
+             << "m_decodeSubtitleThread:"
+             << (m_decodeSubtitleThread ? m_decodeSubtitleThread->isRunning() : false);
     // 自愈:如果状态为Playing但所有线程都已退出,强制Idle
     if (m_state == PlayerState::Playing) {
-        if (!m_packetReadThread && !m_decodeVideoThread && !m_decodeAudioThread
-            && !m_audioPlayThread && !m_videoPlayThread && !m_decodeSubtitleThread) {
-            m_videoState.reset();
+        // 检查线程指针是否存在并且是否正在运行
+        bool allThreadsStopped = 
+            (!m_packetReadThread || !m_packetReadThread->isRunning()) &&
+            (!m_decodeVideoThread || !m_decodeVideoThread->isRunning()) &&
+            (!m_decodeAudioThread || !m_decodeAudioThread->isRunning()) &&
+            (!m_audioPlayThread || !m_audioPlayThread->isRunning()) &&
+            (!m_videoPlayThread || !m_videoPlayThread->isRunning()) &&
+            (!m_decodeSubtitleThread || !m_decodeSubtitleThread->isRunning());
+            
+        if (allThreadsStopped) {
+            auto stopAndReset = [](auto& threadPtr) {
+                if (threadPtr) {
+                    qCDebug(playerControllerLog)
+                        << "[stopAndReset] try stop/join thread, isRunning="
+                        << threadPtr->isRunning();
+                    threadPtr->stop();
+                    threadPtr->join();
+                    qCDebug(playerControllerLog) << "[stopAndReset] thread joined and will reset.";
+                    threadPtr.reset();
+                }
+            };
+            stopAndReset(m_stopPlayWaitingThread);
+            stopAndReset(m_beforePlayThread);
+            stopAndReset(m_packetReadThread);
+            stopAndReset(m_decodeVideoThread);
+            stopAndReset(m_decodeAudioThread);
+            stopAndReset(m_decodeSubtitleThread);
+            stopAndReset(m_videoPlayThread);
+            stopAndReset(m_audioPlayThread);
+
             m_currentFile.clear();
             m_state = PlayerState::Idle;
             qCDebug(playerControllerLog)
@@ -75,6 +117,42 @@ void PlayerController::startToPlay(const QString& file)
         }
     }
     if (m_state == PlayerState::Idle) {
+        bool allThreadsStopped = (!m_packetReadThread || !m_packetReadThread->isRunning())
+                                 && (!m_decodeVideoThread || !m_decodeVideoThread->isRunning())
+                                 && (!m_decodeAudioThread || !m_decodeAudioThread->isRunning())
+                                 && (!m_audioPlayThread || !m_audioPlayThread->isRunning())
+                                 && (!m_videoPlayThread || !m_videoPlayThread->isRunning())
+                                 && (!m_decodeSubtitleThread
+                                     || !m_decodeSubtitleThread->isRunning());
+
+        if (allThreadsStopped) {
+            auto stopAndReset = [](auto& threadPtr) {
+                if (threadPtr) {
+                    qCDebug(playerControllerLog)
+                        << "[stopAndReset] try stop/join thread, isRunning="
+                        << threadPtr->isRunning();
+                    threadPtr->stop();
+                    threadPtr->join();
+                    qCDebug(playerControllerLog) << "[stopAndReset] thread joined and will reset.";
+                    threadPtr.reset();
+                }
+            };
+            m_videoState.reset();
+            stopAndReset(m_stopPlayWaitingThread);
+            stopAndReset(m_beforePlayThread);
+            stopAndReset(m_packetReadThread);
+            stopAndReset(m_decodeVideoThread);
+            stopAndReset(m_decodeAudioThread);
+            stopAndReset(m_decodeSubtitleThread);
+            stopAndReset(m_videoPlayThread);
+            stopAndReset(m_audioPlayThread);
+
+            m_currentFile.clear();
+            m_state = PlayerState::Idle;
+            qCDebug(playerControllerLog)
+                << "[PlayerController] All threads stopped, force reset to Idle.";
+        }
+
         qCDebug(playerControllerLog) << "Player is idle. Starting playback for:" << file;
         m_state = PlayerState::Initializing;
         m_currentFile = file;
@@ -99,7 +177,7 @@ void PlayerController::asyncInit(const QString& file)
         success = true;
     }
     m_initSuccess = success;
-    emit asyncInitFinished(file, success);
+    onAsyncInitFinished(file, success);
     qCDebug(playerControllerLog) << "[Init] asyncInit finished in " << timer.elapsed() << " ms";
 }
 
@@ -111,13 +189,6 @@ void PlayerController::onAsyncInitFinished(const QString& file, bool success)
         m_state = PlayerState::Idle;
         return;
     }
-    qCDebug(playerControllerLog) << "[Init] createReadThread...";
-    if (!createReadThread()) {
-        qCWarning(playerControllerLog) << "Packet read thread creation failed";
-        playFailed(m_currentFile);
-        m_state = PlayerState::Idle;
-        return;
-    }
     qCDebug(playerControllerLog) << "[Init] createVideoState...";
     if (!createVideoState(m_currentFile)) {
         qCWarning(playerControllerLog) << "Video state creation failed";
@@ -127,6 +198,13 @@ void PlayerController::onAsyncInitFinished(const QString& file, bool success)
         return;
     }
     assert(m_videoState);
+    qCDebug(playerControllerLog) << "[Init] createReadThread...";
+    if (!createReadThread()) {
+        qCWarning(playerControllerLog) << "Packet read thread creation failed";
+        playFailed(m_currentFile);
+        m_state = PlayerState::Idle;
+        return;
+    }
     if (!m_videoState) {
         qCWarning(playerControllerLog) << "Video state initialization error";
         playFailed(m_currentFile);
@@ -177,23 +255,7 @@ void PlayerController::stopPlay()
     if (m_state == PlayerState::Idle)
         return;
     m_state = PlayerState::Stopping;
-    auto stopAndReset = [](auto& threadPtr) {
-        if (threadPtr) {
-            qCDebug(playerControllerLog) << "[stopAndReset] try stop/join thread, isRunning=" << threadPtr->isRunning();
-            threadPtr->stop();
-            threadPtr->join();
-            qCDebug(playerControllerLog) << "[stopAndReset] thread joined and will reset.";
-            threadPtr.reset();
-        }
-    };
-    stopAndReset(m_stopPlayWaitingThread);
-    stopAndReset(m_beforePlayThread);
-    stopAndReset(m_packetReadThread);
-    stopAndReset(m_decodeVideoThread);
-    stopAndReset(m_decodeAudioThread);
-    stopAndReset(m_decodeSubtitleThread);
-    stopAndReset(m_videoPlayThread);
-    stopAndReset(m_audioPlayThread);
+
     m_videoState.reset();
     m_currentFile.clear();
     m_state = PlayerState::Idle;
@@ -318,40 +380,46 @@ void PlayerController::playFailed(const QString& file)
 void PlayerController::readPacketStopped()
 {
     qCDebug(playerControllerLog) << "************* Read packets thread stopped signal received.";
-    m_packetReadThread.reset();
+    //m_packetReadThread.reset();
     checkAndResetState();
+
+    // stopPlay();
+    if (m_videoState) {
+        m_videoState->delete_video_state();
+    }
+
     emit audioStopped();
 }
 void PlayerController::decodeVideoStopped()
 {
     qCDebug(playerControllerLog) << "************* Video decode thread stopped.";
-    m_decodeVideoThread.reset();
+    //m_decodeVideoThread.reset();
     checkAndResetState();
 }
 void PlayerController::decodeAudioStopped()
 {
     qCDebug(playerControllerLog) << "************* Audio decode thread stopped.";
-    m_decodeAudioThread.reset();
+    //m_decodeAudioThread.reset();
     checkAndResetState();
 }
 void PlayerController::decodeSubtitleStopped()
 {
     qCDebug(playerControllerLog) << "************* Subtitle decode thread stopped.";
-    m_decodeSubtitleThread.reset();
+    //m_decodeSubtitleThread.reset();
     checkAndResetState();
 }
 void PlayerController::audioPlayStopped()
 {
     qCDebug(playerControllerLog) << "************* Audio play thread stopped.";
     emit audioStopped();
-    m_audioPlayThread.reset();
+    //m_audioPlayThread.reset();
     checkAndResetState();
 }
 void PlayerController::videoPlayStopped()
 {
     qCDebug(playerControllerLog) << "************* Video play thread stopped.";
     emit videoStopped();
-    m_videoPlayThread.reset();
+    // m_videoPlayThread.reset();
     checkAndResetState();
 }
 
@@ -473,8 +541,10 @@ bool PlayerController::startPlay()
 bool PlayerController::waitStopPlay(const QString& file)
 {
     m_stopPlayWaitingThread = std::make_unique<StopWaitingThread>(this, file.toStdString());
+
     m_stopPlayWaitingThread->setOnFinished([this]() {
         // 可根据需要添加额外处理
+        //m_stopPlayWaitingThread.reset();
     });
     m_stopPlayWaitingThread->start();
     qCDebug(playerControllerLog) << "++++++++++ StopPlay waiting thread started";
@@ -485,7 +555,11 @@ void PlayerController::allThreadStart()
 {
     // 启动所有创建的线程
     if (m_packetReadThread) {
-        m_packetReadThread->start();
+        if (!m_videoState || !m_videoState->get_state()) {
+            qCWarning(playerControllerLog) << "VideoState invalid, skip starting read thread";
+        } else {
+            m_packetReadThread->start();
+        }
         qCDebug(playerControllerLog) << "++++++++++ Read packets thread started";
     }
 
@@ -542,24 +616,24 @@ void PlayerController::videoSeekInc(double increment)
 // 新增自愈机制辅助函数
 void PlayerController::checkAndResetState()
 {
-    std::lock_guard<std::mutex> lock(m_stopMutex);
-    if (!m_packetReadThread && !m_decodeVideoThread && !m_decodeAudioThread && !m_audioPlayThread
-        && !m_videoPlayThread && !m_decodeSubtitleThread) {
-        m_videoState.reset();
-        m_currentFile.clear();
-        m_state = PlayerState::Idle;
-        qCDebug(playerControllerLog)
-            << "[PlayerController] All threads stopped, state reset to Idle.";
-        emit playbackFinished(); // 新增:通知UI
-    } else {
-        qCDebug(playerControllerLog) << "[PlayerController] checkAndResetState: "
-                                     << "m_packetReadThread:" << (bool) m_packetReadThread
-                                     << "m_decodeVideoThread:" << (bool) m_decodeVideoThread
-                                     << "m_decodeAudioThread:" << (bool) m_decodeAudioThread
-                                     << "m_audioPlayThread:" << (bool) m_audioPlayThread
-                                     << "m_videoPlayThread:" << (bool) m_videoPlayThread
-                                     << "m_decodeSubtitleThread:" << (bool) m_decodeSubtitleThread;
-    }
+    // std::lock_guard<std::mutex> lock(m_stopMutex);
+    // if (!m_packetReadThread && !m_decodeVideoThread && !m_decodeAudioThread && !m_audioPlayThread
+    //     && !m_videoPlayThread && !m_decodeSubtitleThread) {
+    //     m_videoState.reset();
+    //     m_currentFile.clear();
+    //     m_state = PlayerState::Idle;
+    //     qCDebug(playerControllerLog)
+    //         << "[PlayerController] All threads stopped, state reset to Idle.";
+    //     emit playbackFinished(); // 新增:通知UI
+    // } else {
+    //     qCDebug(playerControllerLog) << "[PlayerController] checkAndResetState: "
+    //                                  << "m_packetReadThread:" << (bool) m_packetReadThread
+    //                                  << "m_decodeVideoThread:" << (bool) m_decodeVideoThread
+    //                                  << "m_decodeAudioThread:" << (bool) m_decodeAudioThread
+    //                                  << "m_audioPlayThread:" << (bool) m_audioPlayThread
+    //                                  << "m_videoPlayThread:" << (bool) m_videoPlayThread
+    //                                  << "m_decodeSubtitleThread:" << (bool) m_decodeSubtitleThread;
+    // }
 }
 
 // 线程创建方法
@@ -594,8 +668,10 @@ bool PlayerController::createReadThread()
         return false;
     m_packetReadThread = std::make_unique<ReadThread>(m_videoState ? m_videoState->get_state()
                                                                    : nullptr);
-    m_packetReadThread->setOnFinished(
-        [this]() { QMetaObject::invokeMethod(this, "readPacketStopped", Qt::QueuedConnection); });
+    m_packetReadThread->setOnFinished([this]() {
+
+        readPacketStopped();
+    });
     return true;
 }
 
@@ -609,8 +685,7 @@ bool PlayerController::createDecodeVideoThread()
         return false;
 
     m_decodeVideoThread = std::make_unique<VideoDecodeThread>(state);
-    m_decodeVideoThread->setOnFinished(
-        [this]() { QMetaObject::invokeMethod(this, "decodeVideoStopped", Qt::QueuedConnection); });
+    m_decodeVideoThread->setOnFinished([this]() { decodeVideoStopped(); });
 
     auto codecContext = m_videoState->get_contex(AVMEDIA_TYPE_VIDEO);
 
@@ -644,8 +719,7 @@ bool PlayerController::createDecodeAudioThread()
         return false;
 
     m_decodeAudioThread = std::make_unique<AudioDecodeThread>(state);
-    m_decodeAudioThread->setOnFinished(
-        [this]() { QMetaObject::invokeMethod(this, "decodeAudioStopped", Qt::QueuedConnection); });
+    m_decodeAudioThread->setOnFinished([this]() { decodeAudioStopped(); });
 
     auto codecContext = m_videoState->get_contex(AVMEDIA_TYPE_AUDIO);
 
@@ -678,9 +752,7 @@ bool PlayerController::createDecodeSubtitleThread()
         return false;
 
     m_decodeSubtitleThread = std::make_unique<SubtitleDecodeThread>(state);
-    m_decodeSubtitleThread->setOnFinished([this]() {
-        QMetaObject::invokeMethod(this, "decodeSubtitleStopped", Qt::QueuedConnection);
-    });
+    m_decodeSubtitleThread->setOnFinished([this]() { decodeSubtitleStopped(); });
 
     auto codecContext = m_videoState->get_contex(AVMEDIA_TYPE_SUBTITLE);
 
@@ -713,8 +785,7 @@ bool PlayerController::createVideoPlayThread()
         return false;
 
     m_videoPlayThread = std::make_unique<VideoPlayThread>(state);
-    m_videoPlayThread->setOnFinished(
-        [this]() { QMetaObject::invokeMethod(this, "videoPlayStopped", Qt::QueuedConnection); });
+    m_videoPlayThread->setOnFinished([this]() { videoPlayStopped(); });
     m_videoPlayThread->setOnFrameReady([this](AVFrame* frame) { this->onFrameReady(frame); });
     m_videoPlayThread->setOnSubtitleReady([this](const QString& text) {
         // TODO: 实现 PlayerController::onSubtitleReady(const QString&) 处理字幕
@@ -743,8 +814,7 @@ bool PlayerController::createAudioPlayThread()
         return false;
 
     m_audioPlayThread = std::make_unique<AudioPlayThread>(state);
-    m_audioPlayThread->setOnFinished(
-        [this]() { QMetaObject::invokeMethod(this, "audioPlayStopped", Qt::QueuedConnection); });
+    m_audioPlayThread->setOnFinished([this]() { audioPlayStopped(); });
     m_audioPlayThread->setOnUpdatePlayTime([this]() {
         // TODO: 实现 PlayerController::onUpdatePlayTime() 处理播放时间更新
         // onUpdatePlayTime();
@@ -773,7 +843,8 @@ bool PlayerController::startPlayThread()
     if (m_beforePlayThread)
         return false;
 
-    m_beforePlayThread = std::make_unique<StartPlayThread>(this);
+    m_beforePlayThread = std::make_unique<StartPlayThread>(m_audioPlayThread.get(), m_videoState.get());
+
     m_beforePlayThread->setOnFinished([this]() {
         qCDebug(playerControllerLog) << "[StartPlayThread] finished, call playStarted()";
         playStarted();

+ 13 - 5
AvPlayer2/playercontroller.h

@@ -13,6 +13,7 @@
 #include <functional>
 #include <memory>
 #include <thread>
+#include <unordered_map>
 
 #include <QLoggingCategory>
 #include "AVPlayer2/audio_play_thread.h"
@@ -63,11 +64,6 @@ public:
     float deviceVolume() const;
     void setDeviceVolume(float volume);
 
-    // 线程访问接口
-    AudioPlayThread* audioPlayThread() const { return m_audioPlayThread.get(); }
-    VideoPlayThread* videoPlayThread() const { return m_videoPlayThread.get(); }
-    VideoStateData* videoStateData() const { return m_videoState.get(); }
-
 public slots:
     // 线程生命周期管理
     void readPacketStopped();
@@ -124,6 +120,18 @@ private slots:
     void onAsyncInitFinished(const QString& file, bool success);
 
 private:
+    enum class ThreadType {
+        Video,
+        Audio,
+        Read,
+        DecodeVideo,
+        DecodeAudio,
+        DecodeSubtitle,
+        BeforePlay,
+        StopWaiting
+    };
+    std::unordered_map<ThreadType, std::mutex> m_threadMutexes;
+
     // 核心播放逻辑
     bool startPlay();
     bool waitStopPlay(const QString& file);

+ 5 - 11
AvPlayer2/read_thread.cpp

@@ -34,12 +34,6 @@ void ReadThread::set_video_state(VideoState* pState)
     m_pPlayData = pState;
 }
 
-void ReadThread::stop()
-{
-    *m_exit = true;
-    m_cv.notify_all();
-}
-
 int ReadThread::loop_read()
 {
     int ret = -1;
@@ -64,7 +58,7 @@ int ReadThread::loop_read()
     is->read_thread_exit = 0;
 
     for (;;) {
-        if (m_exit && *m_exit) {
+        if (isExit()) {
             qCDebug(playerControllerReadThread) << "[ReadThread] m_exit set, break.";
             break;
         }
@@ -142,7 +136,7 @@ int ReadThread::loop_read()
                 << "[ReadThread] queues full, waiting... audioq:" << is->audioq.size
                 << ", videoq:" << is->videoq.size << ", subtitleq:" << is->subtitleq.size;
             std::unique_lock<std::mutex> lock(m_mutex);
-            m_cv.wait_for(lock, std::chrono::milliseconds(10), [this] { return m_exit && *m_exit; });
+            m_cv.wait_for(lock, std::chrono::milliseconds(10), [this] { return isExit(); });
             continue;
         }
 
@@ -173,7 +167,7 @@ int ReadThread::loop_read()
             }
 
             std::unique_lock<std::mutex> lock(m_mutex);
-            m_cv.wait_for(lock, std::chrono::milliseconds(10), [this] { return m_exit && *m_exit; });
+            m_cv.wait_for(lock, std::chrono::milliseconds(10), [this] { return isExit(); });
             continue;
         } else {
             is->eof = 0;
@@ -182,8 +176,7 @@ int ReadThread::loop_read()
                 << ", pts:" << pkt->pts;
         }
 
-        /* check if packet is in play range specified by user, then queue, otherwise
-     * discard */
+        /* check if packet is in play range specified by user, then queue, otherwise discard */
         stream_start_time = is->ic->streams[pkt->stream_index]->start_time;
         pkt_ts = pkt->pts == AV_NOPTS_VALUE ? pkt->dts : pkt->pts;
         pkt_in_play_range = duration == AV_NOPTS_VALUE
@@ -216,6 +209,7 @@ int ReadThread::loop_read()
         << ", m_exit:" << (m_exit ? m_exit->load() : -1);
     qCDebug(playerControllerReadThread) << "[ReadThread] loop_read exit, set read_thread_exit = -1";
     is->read_thread_exit = -1;
+
     av_packet_free(&pkt);
     return 0;
 }

+ 0 - 5
AvPlayer2/read_thread.h

@@ -11,13 +11,8 @@ class ReadThread : public ThreadBase
 public:
     explicit ReadThread(VideoState* pState = nullptr);
     ~ReadThread();
-    ReadThread(const ReadThread&) = delete;
-    ReadThread& operator=(const ReadThread&) = delete;
-    ReadThread(ReadThread&&) = delete;
-    ReadThread& operator=(ReadThread&&) = delete;
 
     void set_video_state(VideoState* pState = nullptr); // call before start
-    void stop() override;
 
 protected:
     int loop_read();

+ 12 - 22
AvPlayer2/start_play_thread.cpp

@@ -1,45 +1,35 @@
-// ***********************************************************/
-// start_play_thread.cpp
-//
-//      Copy Right @ Steven Huang. All rights reserved.
-//
-// start play thread. Do the audio device initialization work
-// which is time-consuming to avoid GUI freezing.
-// ***********************************************************/
-
 #include "start_play_thread.h"
+
+#include "AVPlayer2/audio_play_thread.h"
 #include "AVPlayer2/video_state.h"
-#include "playercontroller.h"
+
 #include <QLoggingCategory>
 Q_LOGGING_CATEGORY(playerControllerStartPlayThread, "player.controller.StartPlayThread")
 
-StartPlayThread::StartPlayThread(PlayerController* playerController)
-    : m_playerController(playerController)
+StartPlayThread::StartPlayThread(AudioPlayThread* audioPlayThread, VideoStateData* videoStateData)
+    : m_audioPlayThread(audioPlayThread), m_videoStateData(videoStateData)
 {}
 
 StartPlayThread::~StartPlayThread() {}
 
-void StartPlayThread::stop()
-{
-    *m_exit = true;
-    m_cv.notify_all();
-}
-
 void StartPlayThread::run()
 {
-    assert(m_playerController);
-    if (m_exit && *m_exit) return;
+    assert(m_videoStateData);
+    assert(m_audioPlayThread);
+
+    if (isExit())
+        return;
     bool ret = false;
 
     float vol = 1.0;
     AVSampleFormat sample_fmt = AV_SAMPLE_FMT_S16; // play out format
 
-    VideoStateData* pVideoStateData = m_playerController->videoStateData();
+    VideoStateData* pVideoStateData = m_videoStateData;
     if (pVideoStateData) {
         AVCodecContext* pAudio = pVideoStateData->get_contex(AVMEDIA_TYPE_AUDIO);
         VideoState* pState = pVideoStateData->get_state();
         if (pAudio) {
-            auto* pThread = m_playerController->audioPlayThread();
+            auto* pThread = m_audioPlayThread;
             if (pThread) {
                 ret = pThread->init_device(pAudio->sample_rate,
                                            pAudio->ch_layout.nb_channels,

+ 5 - 10
AvPlayer2/start_play_thread.h

@@ -3,25 +3,20 @@
 #pragma once
 
 #include "ThreadBase.h"
-#include <atomic>
 
-class PlayerController;
+class AudioPlayThread;
+class VideoStateData;
 
 class StartPlayThread : public ThreadBase
 {
 public:
-    StartPlayThread(const StartPlayThread&) = delete;
-    StartPlayThread& operator=(const StartPlayThread&) = delete;
-    StartPlayThread(StartPlayThread&&) = delete;
-    StartPlayThread& operator=(StartPlayThread&&) = delete;
-    explicit StartPlayThread(PlayerController *playerController);
+    explicit StartPlayThread(AudioPlayThread* audioPlayThread, VideoStateData* videoStateData);
     ~StartPlayThread();
 
-    void stop() override;
-
 protected:
     void run() override;
-    PlayerController *m_playerController;
+    AudioPlayThread* m_audioPlayThread;
+    VideoStateData* m_videoStateData;
 };
 
 #endif // AVPLAYER2_START_PLAY_THREAD_H

+ 2 - 6
AvPlayer2/stopplay_waiting_thread.cpp

@@ -16,11 +16,6 @@ StopWaitingThread::StopWaitingThread(PlayerController* parent, const std::string
 
 StopWaitingThread::~StopWaitingThread() {}
 
-void StopWaitingThread::stop()
-{
-    *m_exit = true;
-    m_cv.notify_all();
-}
 
 void StopWaitingThread::run()
 {
@@ -28,7 +23,8 @@ void StopWaitingThread::run()
     if (!m_parent) return;
     m_parent->stopPlay();
     while (m_parent->isPlaying()) {
-        if (m_exit && *m_exit) break;
+        if (isExit())
+            break;
         std::this_thread::sleep_for(std::chrono::milliseconds(2));
     }
     if (!m_exit) {

+ 0 - 6
AvPlayer2/stopplay_waiting_thread.h

@@ -12,15 +12,9 @@ class PlayerController;
 class StopWaitingThread : public ThreadBase
 {
 public:
-    StopWaitingThread(const StopWaitingThread&) = delete;
-    StopWaitingThread& operator=(const StopWaitingThread&) = delete;
-    StopWaitingThread(StopWaitingThread&&) = delete;
-    StopWaitingThread& operator=(StopWaitingThread&&) = delete;
     explicit StopWaitingThread(PlayerController* parent, const std::string& file = "");
     ~StopWaitingThread();
 
-    void stop() override;
-
 protected:
     void run() override;
 

+ 1 - 1
AvPlayer2/subtitle_decode_thread.cpp

@@ -35,7 +35,7 @@ void SubtitleDecodeThread::run()
 
     for (;;)
     {
-        if (m_exit && *m_exit)
+        if (isExit())
             break;
         if (!(sp = frame_queue_peek_writable(&is->subpq)))
             return;

+ 0 - 5
AvPlayer2/subtitle_decode_thread.h

@@ -13,11 +13,6 @@ public:
     explicit SubtitleDecodeThread(VideoState* pState = nullptr);
     ~SubtitleDecodeThread();
 
-    SubtitleDecodeThread(const SubtitleDecodeThread&) = delete;
-    SubtitleDecodeThread& operator=(const SubtitleDecodeThread&) = delete;
-    SubtitleDecodeThread(SubtitleDecodeThread&&) = delete;
-    SubtitleDecodeThread& operator=(SubtitleDecodeThread&&) = delete;
-
     void stop() override;
 
 protected:

+ 1 - 1
AvPlayer2/video_decode_thread.cpp

@@ -52,7 +52,7 @@ void VideoDecodeThread::run()
             << "[VideoDecodeThread] loop start, loop_count:" << loop_count
             << ", m_exit:" << (m_exit ? m_exit->load() : -1)
             << ", abort_request:" << is->abort_request;
-        if (m_exit && *m_exit) {
+        if (isExit()) {
             qCDebug(playerControllerVideoDecodeThread) << "[VideoDecodeThread] m_exit set, exit.";
             break;
         }

+ 0 - 5
AvPlayer2/video_decode_thread.h

@@ -14,11 +14,6 @@ public:
 
     void stop() override;
 
-    VideoDecodeThread(const VideoDecodeThread&) = delete;
-    VideoDecodeThread& operator=(const VideoDecodeThread&) = delete;
-    VideoDecodeThread(VideoDecodeThread&&) = delete;
-    VideoDecodeThread& operator=(VideoDecodeThread&&) = delete;
-
 protected:
     void run() override;
 

+ 2 - 2
AvPlayer2/video_play_thread.cpp

@@ -47,7 +47,7 @@ void VideoPlayThread::run()
     double remaining_time = 0.0;
     int loop_count = 0;
     for (;;) {
-        if (m_exit && *m_exit) {
+        if (isExit()) {
             qCDebug(playerControllerVideoPlayThread) << "[VideoPlayThread] m_exit set, exit.";
             break;
         }
@@ -62,7 +62,7 @@ void VideoPlayThread::run()
         if (is->paused) {
             qCDebug(playerControllerVideoPlayThread) << "[VideoPlayThread] paused, wait.";
             std::unique_lock<std::mutex> lock(m_mutex);
-            m_cv.wait_for(lock, std::chrono::milliseconds(10), [this] { return m_exit && *m_exit; });
+            m_cv.wait_for(lock, std::chrono::milliseconds(10), [this] { return isExit(); });
             continue;
         }
         qCDebug(playerControllerVideoPlayThread) << "[VideoPlayThread] call video_refresh, loop:" << loop_count << ", pictq size:" << (is ? is->pictq.size : -1) << ", remaining_time:" << remaining_time;

+ 0 - 6
AvPlayer2/video_play_thread.h

@@ -23,12 +23,6 @@ public:
     explicit VideoPlayThread(VideoState* pState = nullptr);
     ~VideoPlayThread();
 
-    // 禁止拷贝
-    VideoPlayThread(const VideoPlayThread&) = delete;
-    VideoPlayThread& operator=(const VideoPlayThread&) = delete;
-    VideoPlayThread(VideoPlayThread&&) = delete;
-    VideoPlayThread& operator=(VideoPlayThread&&) = delete;
-
     bool init_resample_param(AVCodecContext* pVideo, bool bHardware = false);
     void stop() override;
 

+ 88 - 52
AvPlayer2/video_state.cpp

@@ -67,7 +67,11 @@ void VideoStateData::print_state() const
         qDebug("[VideoState]Clock(v:%p,a:%p,s:%p)", &is->vidclk, &is->audclk, &is->extclk);
     }
 }
-
+int decode_interrupt_cb(void* ctx)
+{
+    VideoState* is = (VideoState*) ctx;
+    return is->abort_request;
+}
 int VideoStateData::open_media(VideoState* is)
 {
     assert(is);
@@ -89,7 +93,7 @@ int VideoStateData::open_media(VideoState* is)
         goto fail;
     }
 
-    ic->interrupt_callback.callback = nullptr; // decode_interrupt_cb;
+    ic->interrupt_callback.callback = decode_interrupt_cb;
     ic->interrupt_callback.opaque = is;
 
     err = avformat_open_input(&ic, is->filename, is->iformat, nullptr);
@@ -98,16 +102,55 @@ int VideoStateData::open_media(VideoState* is)
         ret = -1;
         goto fail;
     }
-
+    // if (!av_dict_get(format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
+    //     av_dict_set(&format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
+    //     scan_all_pmts_set = 1;
+    // }
+    // err = avformat_open_input(&ic, is->filename, is->iformat, &format_opts);
+    // if (err < 0) {
+    //     print_error(is->filename, err);
+    //     ret = -1;
+    //     goto fail;
+    // }
+    // if (scan_all_pmts_set)
+    //     av_dict_set(&format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE);
+    // remove_avoptions(&format_opts, codec_opts);
+
+    // ret = check_avoptions(format_opts);
+    // if (ret < 0)
+    //     goto fail;
     is->ic = ic;
 
-    //ic->flags |= AVFMT_FLAG_GENPTS; // gen pts
+    // if (genpts)
+    // ic->flags |= AVFMT_FLAG_GENPTS;
 
-    av_format_inject_global_side_data(ic);
+    // if (find_stream_info) {
+    //     AVDictionary **opts;
+    //     int orig_nb_streams = ic->nb_streams;
+
+    //     err = setup_find_stream_info_opts(ic, codec_opts, &opts);
+    //     if (err < 0) {
+    //         av_log(NULL, AV_LOG_ERROR,
+    //                "Error setting up avformat_find_stream_info() options\n");
+    //         ret = err;
+    //         goto fail;
+    //     }
+
+    //     err = avformat_find_stream_info(ic, opts);
 
-    //AVDictionary** opts = setup_find_stream_info_opts(ic, codec_opts);
-    //int orig_nb_streams = ic->nb_streams;
+    //     for (i = 0; i < orig_nb_streams; i++)
+    //         av_dict_free(&opts[i]);
+    //     av_freep(&opts);
 
+    //     if (err < 0) {
+    //         av_log(NULL, AV_LOG_WARNING,
+    //                "%s: could not find codec parameters\n", is->filename);
+    //         ret = -1;
+    //         goto fail;
+    //     }
+    // }
+
+    av_format_inject_global_side_data(ic);
     err = avformat_find_stream_info(ic, nullptr);
     if (err < 0) {
         av_log(nullptr, AV_LOG_WARNING, "%s: could not find codec parameters\n", is->filename);
@@ -115,15 +158,17 @@ int VideoStateData::open_media(VideoState* is)
         goto fail;
     }
 
-    if (ic->pb)
-        ic->pb->eof_reached = 0; // FIXME hack, ffplay maybe should not use
-                                 // avio_feof() to test for the end
-
+    if (ic->pb) {
+        // FIXME hack, ffplay maybe should not use avio_feof() to test for the end
+        ic->pb->eof_reached = 0;
+    }
     // if (seek_by_bytes < 0)
-    //	seek_by_bytes = (ic->iformat->flags & AVFMT_TS_DISCONT) &&
-    //strcmp("ogg", ic->iformat->name);
+    //     seek_by_bytes = !(ic->iformat->flags & AVFMT_NO_BYTE_SEEK) &&
+    //                     !!(ic->iformat->flags & AVFMT_TS_DISCONT) &&
+    //                     strcmp("ogg", ic->iformat->name);
+
+    // is->max_frame_duration = (ic->iformat->flags & AVFMT_TS_DISCONT) ? 10.0 : 3600.0;
 
-    //is->max_frame_duration = (ic->iformat->flags & AVFMT_TS_DISCONT) ? 10.0 : 3600.0;
     is->max_frame_duration = 2.0;
 
     /* if seeking requested, we execute it */
@@ -136,7 +181,7 @@ int VideoStateData::open_media(VideoState* is)
             timestamp += ic->start_time;
         ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0);
         if (ret < 0) {
-            av_log(nullptr,
+            av_log(NULL,
                    AV_LOG_WARNING,
                    "%s: could not seek to position %0.3f\n",
                    is->filename,
@@ -146,6 +191,7 @@ int VideoStateData::open_media(VideoState* is)
 
     is->realtime = is_realtime(ic);
 
+    // if (show_status)
     av_dump_format(ic, 0, is->filename, 0);
 
     for (i = 0; i < ic->nb_streams; i++) {
@@ -167,21 +213,24 @@ int VideoStateData::open_media(VideoState* is)
         }
     }
 
+    // if (!video_disable)
     st_index[AVMEDIA_TYPE_VIDEO]
-        = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, st_index[AVMEDIA_TYPE_VIDEO], -1, nullptr, 0);
+        = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, st_index[AVMEDIA_TYPE_VIDEO], -1, NULL, 0);
+    // if (!audio_disable)
     st_index[AVMEDIA_TYPE_AUDIO] = av_find_best_stream(ic,
                                                        AVMEDIA_TYPE_AUDIO,
                                                        st_index[AVMEDIA_TYPE_AUDIO],
                                                        st_index[AVMEDIA_TYPE_VIDEO],
-                                                       nullptr,
+                                                       NULL,
                                                        0);
+    // if (!video_disable && !subtitle_disable)
     st_index[AVMEDIA_TYPE_SUBTITLE] = av_find_best_stream(ic,
                                                           AVMEDIA_TYPE_SUBTITLE,
                                                           st_index[AVMEDIA_TYPE_SUBTITLE],
                                                           (st_index[AVMEDIA_TYPE_AUDIO] >= 0
                                                                ? st_index[AVMEDIA_TYPE_AUDIO]
                                                                : st_index[AVMEDIA_TYPE_VIDEO]),
-                                                          nullptr,
+                                                          NULL,
                                                           0);
 
     /* open the streams */
@@ -267,7 +316,7 @@ VideoState* VideoStateData::stream_open(const char* filename, const AVInputForma
     is->audio_volume = startup_volume;
     is->muted = 0;
     is->av_sync_type = av_sync_type;
-    // is->read_tid = m_pReadThreadId;
+    // is->read_tid = SDL_CreateThread(read_thread, "read_thread", is);;
     is->read_thread_exit = -1;
     is->loop = int(m_bLoopPlay);
 
@@ -309,22 +358,6 @@ void VideoStateData::threads_setting(VideoState* is, const Threads& threads)
     is->threads.subtitle_decode_tid = threads.subtitle_decode_tid;
 }
 
-void VideoStateData::read_thread_exit_wait(VideoState* is)
-{
-    if (!is)
-        return;
-
-    if (is->read_thread_exit != 0)
-        return;
-
-    if (is->threads.read_tid) {
-        av_log(nullptr, AV_LOG_INFO, "read thread wait before!\n");
-        is->threads.read_tid->join();
-        av_log(nullptr, AV_LOG_INFO, "read thread wait after!\n");
-        is->threads.read_tid = nullptr;
-    }
-}
-
 void VideoStateData::threads_exit_wait(VideoState* is)
 {
     if (!is)
@@ -352,15 +385,18 @@ void VideoStateData::stream_close(VideoState* is)
 
     is->abort_request = 1;
 
-    read_thread_exit_wait(is);
-
-    // if (is->read_thread_exit == 0)
-    //{
-    //	// SDL_WaitThread(is->read_tid, nullptr);
-    //	//((QThread*)(is->read_tid))->wait();
-    //	/*if (m_pReadThreadId)
-    //		m_pReadThreadId->wait();*/
-    //}
+    // SDL_WaitThread(is->read_tid, NULL);
+    {
+        if (is->read_thread_exit != 0)
+            return;
+
+        if (is->threads.read_tid) {
+            av_log(nullptr, AV_LOG_INFO, "read thread wait before!\n");
+            is->threads.read_tid->join();
+            av_log(nullptr, AV_LOG_INFO, "read thread wait after!\n");
+            is->threads.read_tid = nullptr;
+        }
+    }
 
     /* close each stream */
     if (is->audio_stream >= 0)
@@ -370,7 +406,7 @@ void VideoStateData::stream_close(VideoState* is)
     if (is->subtitle_stream >= 0)
         stream_component_close(is, is->subtitle_stream);
 
-    threads_exit_wait(is); // read and decode threads exit here.
+    threads_exit_wait(is); // 这里插入线程关闭 ?
 
     avformat_close_input(&is->ic);
 
@@ -383,21 +419,21 @@ void VideoStateData::stream_close(VideoState* is)
     frame_queue_destory(&is->sampq);
     frame_queue_destory(&is->subpq);
 
+    // SDL_DestroyCond(is->continue_read_thread);
     if (is->continue_read_thread) {
         delete is->continue_read_thread;
         is->continue_read_thread = nullptr;
     }
 
-    // SDL_DestroyCond(is->continue_read_thread);
     sws_freeContext(is->img_convert_ctx);
     sws_freeContext(is->sub_convert_ctx);
     av_free(is->filename);
-    /*if (is->vis_texture)
-          SDL_DestroyTexture(is->vis_texture);
-  if (is->vid_texture)
-          SDL_DestroyTexture(is->vid_texture);
-  if (is->sub_texture)
-          SDL_DestroyTexture(is->sub_texture);*/
+    // if (is->vis_texture)
+    //     SDL_DestroyTexture(is->vis_texture);
+    // if (is->vid_texture)
+    //     SDL_DestroyTexture(is->vid_texture);
+    // if (is->sub_texture)
+    //     SDL_DestroyTexture(is->sub_texture);
 
     av_free(is);
 }

+ 1 - 1
AvPlayer2/video_state.h

@@ -39,7 +39,7 @@ private:
     bool open_hardware(AVCodecContext* avctx, const AVCodec* codec, const char* device = "dxva2");
     void close_hardware();
     int hw_decoder_init(AVCodecContext* ctx, const enum AVHWDeviceType type);
-    void read_thread_exit_wait(VideoState* is);
+
     void threads_exit_wait(VideoState* is);
 
 private:

+ 5 - 6
main.cpp

@@ -53,12 +53,11 @@ namespace avrecorder::video { void InitWinRTCapture(); }
 int main(int argc, char* argv[])
 {
     // QLoggingCategory::setFilterRules(QStringLiteral("player.controller.debug=true\n"));
-    QLoggingCategory::setFilterRules("*.debug=false\n"
-                                     "*.info=false\n"
-                                     "*.warning=false\n"
-                                     "*.critical=false\n"
-                                     "player.controller.PlayerController.debug=true\n"
-                                     "player.controller.VideoDecodeThread.debug=true\n");
+    // QLoggingCategory::setFilterRules("*.debug=false\n"
+    //                                  "*.info=false\n"
+    //                                  "*.warning=false\n"
+    //                                  "*.critical=false\n"
+    //                                  "player.controller.*.debug=true\n");
 
     // 打开日志文件(覆盖模式)
     g_logFile.setFileName("log.txt");