#pragma once #include #include #include #include #include #include #include #include #include #include "AVPlayer2/audio_play_thread.h" class ReadThread; class VideoDecodeThread; class AudioDecodeThread; class SubtitleDecodeThread; class AudioPlayThread; class VideoPlayThread; class VideoStateData; class StartPlayThread; class StopWaitingThread; struct VideoState; class OpenGLVideoWidget; class PlayerController : public QObject { Q_OBJECT public: enum class PlayerState { Idle, Initializing, Playing, Stopping }; explicit PlayerController(QWidget* parent = nullptr); ~PlayerController(); // 播放控制接口 void startToPlay(const QString& file); void stopPlay(); void pausePlay(); void playMute(bool mute); void playStartSeek(); void playSeekPre(); void playSeekNext(); void setVolume(int volume, int maxValue = 100); void setPlaySpeed(double speed); bool isPlaying() const; QString playingFile() const; bool playingHasVideo(); bool playingHasAudio(); bool playingHasSubtitle(); // 状态访问接口 VideoState* state(); 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(); void decodeVideoStopped(); void decodeAudioStopped(); void decodeSubtitleStopped(); void audioPlayStopped(); void videoPlayStopped(); // 播放状态回调 void playStarted(bool success = true); void playFailed(const QString& file); // 线程管理 void setThreads(); void startSendData(bool send = true); void videoSeek(double pos = 0, double incr = 0); signals: // 线程控制信号 void startToPlaySignal(); void stopAudioPlayThread(); void stopVideoPlayThread(); void stopDecodeThread(); void stopReadPacketThread(); void waitStopAudioPlayThread(); void waitStopVideoPlayThread(); void audioStopped(); // 音频结束 void videoStopped(); // 视频结束 void playbackFinished(); // 新增:播放自然结束 // 多媒体数据处理 void frameReady(AVFrame*); void audioData(const AudioData& data); void subtitleReady(const QString& text); // UI更新信号 void setPlayControlWnd(bool set); void updatePlayControlVolume(); void updatePlayControlStatus(); void updatePlayTime(); void playSeek(); void showMessage(const QString& message, const QString& windowTitle, const QString& styleSheet); void requestFullscreen(bool fullscreen); void requestHideStatusBar(bool hide); void asyncInitFinished(const QString& file, bool success); private slots: void onAsyncInitFinished(const QString& file, bool success); private: // 核心播放逻辑 bool startPlay(); void waitStopPlay(const QString& file); void allThreadStart(); // 线程创建方法 bool createVideoState(const QString& file); void deleteVideoState(); bool createReadThread(); bool createDecodeVideoThread(); bool createDecodeAudioThread(); bool createDecodeSubtitleThread(); bool createVideoPlayThread(); bool createAudioPlayThread(); bool startPlayThread(); // 避免UI冻结的线程 // 播放辅助方法 void videoSeekInc(double incr); void printDecodeContext(const AVCodecContext* videoCtx, bool isVideo = true) const; void displayStatusMessage(const QString& message); QSize displayVideoSize(AVCodecContext* videoCtx) const; void setVolumeUpdown(bool increase = true, float unit = 0.05f); QString strippedName(const QString& fullPath) const; void hideCursor(bool hide = true); bool cursorInWindow(QWidget* widget); // 异步初始化相关 void asyncInit(const QString& file); std::thread m_initThread; std::atomic m_initInProgress{false}; std::atomic m_initSuccess{false}; std::mutex m_stopMutex; // 状态机 std::atomic m_state{PlayerState::Idle}; private: // 多媒体线程 std::unique_ptr m_packetReadThread; std::unique_ptr m_decodeVideoThread; std::unique_ptr m_decodeAudioThread; std::unique_ptr m_decodeSubtitleThread; std::unique_ptr m_audioPlayThread; std::unique_ptr m_videoPlayThread; // 状态管理 std::unique_ptr m_videoState; std::unique_ptr m_beforePlayThread; std::unique_ptr m_stopPlayWaitingThread; QString m_currentFile; // 更清晰的命名 void checkAndResetState(); };