#ifndef AVPLAYER2_PLAYERCONTROLLER_H #define AVPLAYER2_PLAYERCONTROLLER_H #pragma once #include #include #include #include #include #include #include #include #include #include "audio_play_thread.h" #include Q_DECLARE_LOGGING_CATEGORY(playerControllerLog) // 前置声明 class ReadThread; class VideoDecodeThread; class AudioDecodeThread; class SubtitleDecodeThread; class AudioPlayThread; class VideoPlayThread; class VideoStateData; class StartPlayThread; class StopWaitingThread; struct VideoState; class OpenGLVideoWidget; /** * @brief 媒体播放控制器 * * 负责协调音视频解码和播放线程,管理播放状态和用户交互 */ class PlayerController : public QObject { Q_OBJECT public: /** * @brief 播放器状态枚举 */ enum class PlayerState { Idle, ///< 空闲状态 Initializing, ///< 初始化中 Playing, ///< 播放中 Stopping ///< 停止中 }; explicit PlayerController(QWidget* parent = nullptr); ~PlayerController(); //-------------------------------------------------------------------------- // 播放控制公共接口 //-------------------------------------------------------------------------- /** * @brief 开始播放指定文件 * @param file 媒体文件路径 */ void startToPlay(const QString& file); /** * @brief 停止当前播放 */ void stopPlay(); /** * @brief 暂停/继续播放 */ void pausePlay(); /** * @brief 静音控制 * @param mute 是否静音 */ void playMute(bool mute); /** * @brief 开始拖动进度条 */ void playStartSeek(); /** * @brief 快退 */ void playSeekPre(); /** * @brief 快进 */ void playSeekNext(); /** * @brief 设置音量 * @param volume 音量值 * @param maxValue 最大音量值 */ void setVolume(int volume, int maxValue = 100); /** * @brief 设置播放速度 * @param speed 播放速度倍率 */ void setPlaySpeed(double speed); /** * @brief 是否正在播放 * @return 播放状态 */ bool isPlaying() const; /** * @brief 获取当前播放文件路径 * @return 文件路径 */ QString playingFile() const; /** * @brief 当前媒体是否包含视频流 * @return 是否有视频 */ bool playingHasVideo(); /** * @brief 当前媒体是否包含音频流 * @return 是否有音频 */ bool playingHasAudio(); /** * @brief 当前媒体是否包含字幕流 * @return 是否有字幕 */ bool playingHasSubtitle(); //-------------------------------------------------------------------------- // 状态访问接口 //-------------------------------------------------------------------------- /** * @brief 获取视频状态对象 * @return VideoState指针 */ VideoState* state(); /** * @brief 获取设备音量 * @return 音量值(0.0-1.0) */ float deviceVolume() const; /** * @brief 设置设备音量 * @param volume 音量值(0.0-1.0) */ void setDeviceVolume(float volume); /** * @brief 打印所有线程状态信息 */ void dump() const; 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); void videoSeekEx(double value = 0, double maxValue = 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 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); protected slots: void onFrameReady(AVFrame* frame); private slots: void onAsyncInitFinished(const QString& file, bool success); private: //-------------------------------------------------------------------------- // 线程类型枚举 //-------------------------------------------------------------------------- enum class ThreadType { Video, Audio, Read, DecodeVideo, DecodeAudio, DecodeSubtitle, BeforePlay, StopWaiting }; std::unordered_map m_threadMutexes; //-------------------------------------------------------------------------- // 核心播放逻辑 //-------------------------------------------------------------------------- void allThreadStart(); // 线程管理辅助方法 void stopAndResetThreads(); bool areAllThreadsStopped() const; //-------------------------------------------------------------------------- // 线程创建方法 //-------------------------------------------------------------------------- bool createVideoState(const QString& file); 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); //-------------------------------------------------------------------------- // 初始化相关(已移除异步逻辑) //-------------------------------------------------------------------------- mutable std::mutex m_stopMutex; //-------------------------------------------------------------------------- // 状态机 //-------------------------------------------------------------------------- std::atomic m_state{PlayerState::Idle}; //-------------------------------------------------------------------------- // 多媒体线程 //-------------------------------------------------------------------------- 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::thread m_eventThread; ///< 事件处理线程 QString m_currentFile; ///< 当前播放文件路径 }; #endif // AVPLAYER2_PLAYERCONTROLLER_H