|
@@ -32,6 +32,15 @@ PlayerController::PlayerController(QWidget* parent)
|
|
|
|
|
|
|
|
PlayerController::~PlayerController()
|
|
PlayerController::~PlayerController()
|
|
|
{
|
|
{
|
|
|
|
|
+ // 等待初始化线程安全退出
|
|
|
|
|
+ if (m_initThread.joinable()) {
|
|
|
|
|
+ {
|
|
|
|
|
+ std::lock_guard<std::mutex> lock(m_initMutex);
|
|
|
|
|
+ m_initInProgress = false;
|
|
|
|
|
+ }
|
|
|
|
|
+ m_initCv.notify_all();
|
|
|
|
|
+ m_initThread.join();
|
|
|
|
|
+ }
|
|
|
stopPlay();
|
|
stopPlay();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -41,14 +50,82 @@ void PlayerController::startToPlay(const QString& file)
|
|
|
if (isPlaying()) {
|
|
if (isPlaying()) {
|
|
|
if (m_currentFile == file)
|
|
if (m_currentFile == file)
|
|
|
return;
|
|
return;
|
|
|
-
|
|
|
|
|
waitStopPlay(file);
|
|
waitStopPlay(file);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
m_currentFile = file;
|
|
m_currentFile = file;
|
|
|
|
|
+ if (m_initInProgress) return; // 正在初始化,直接返回
|
|
|
|
|
+ m_initInProgress = true;
|
|
|
|
|
+ if (m_initThread.joinable()) m_initThread.join();
|
|
|
|
|
+ m_initThread = std::thread(&PlayerController::asyncInit, this, file);
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- if (!startPlay()) {
|
|
|
|
|
|
|
+void PlayerController::asyncInit(const QString& file)
|
|
|
|
|
+{
|
|
|
|
|
+ bool success = false;
|
|
|
|
|
+ // startPlay 的主体迁移到这里
|
|
|
|
|
+ QElapsedTimer timer;
|
|
|
|
|
+ timer.start();
|
|
|
|
|
+ if (file.isEmpty()) {
|
|
|
|
|
+ qWarning("Filename is invalid. Please select a valid media file.");
|
|
|
|
|
+ success = false;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ qInfo("Starting playback: %s", qUtf8Printable(toNativePath(file)));
|
|
|
|
|
+ if (!createReadThread()) {
|
|
|
|
|
+ qWarning("Packet read thread creation failed");
|
|
|
|
|
+ success = false;
|
|
|
|
|
+ } else if (!createVideoState(file)) {
|
|
|
|
|
+ qWarning("Video state creation failed");
|
|
|
|
|
+ readPacketStopped();
|
|
|
|
|
+ success = false;
|
|
|
|
|
+ } else if (!m_videoState) {
|
|
|
|
|
+ qWarning("Video state initialization error");
|
|
|
|
|
+ success = false;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ m_packetReadThread->set_video_state(m_videoState->get_state());
|
|
|
|
|
+ const bool hasVideo = playingHasVideo();
|
|
|
|
|
+ const bool hasAudio = playingHasAudio();
|
|
|
|
|
+ const bool hasSubtitle = playingHasSubtitle();
|
|
|
|
|
+ if (hasVideo) {
|
|
|
|
|
+ if (!createDecodeVideoThread() || !createVideoPlayThread()) {
|
|
|
|
|
+ qWarning("Video processing setup failed");
|
|
|
|
|
+ success = false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (hasAudio) {
|
|
|
|
|
+ if (!createDecodeAudioThread() || !createAudioPlayThread()) {
|
|
|
|
|
+ qWarning("Audio processing setup failed");
|
|
|
|
|
+ success = false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (hasSubtitle && !createDecodeSubtitleThread()) {
|
|
|
|
|
+ qWarning("Subtitle processing setup failed");
|
|
|
|
|
+ success = false;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 开始播放
|
|
|
|
|
+ if (hasAudio) {
|
|
|
|
|
+ // 音频设备初始化在独立线程中完成
|
|
|
|
|
+ startPlayThread();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ playStarted();
|
|
|
|
|
+ }
|
|
|
|
|
+ success = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ {
|
|
|
|
|
+ std::lock_guard<std::mutex> lock(m_initMutex);
|
|
|
|
|
+ m_initSuccess = success;
|
|
|
|
|
+ m_initInProgress = false;
|
|
|
|
|
+ }
|
|
|
|
|
+ m_initCv.notify_all();
|
|
|
|
|
+ onInitFinished(success);
|
|
|
|
|
+ qDebug("Playback initialized in %lld ms", timer.elapsed());
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void PlayerController::onInitFinished(bool success)
|
|
|
|
|
+{
|
|
|
|
|
+ // 这里可以发 Qt 信号或回调
|
|
|
|
|
+ if (!success) {
|
|
|
playFailed(m_currentFile);
|
|
playFailed(m_currentFile);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
@@ -58,6 +135,12 @@ void PlayerController::startToPlay(const QString& file)
|
|
|
void PlayerController::stopPlay()
|
|
void PlayerController::stopPlay()
|
|
|
{
|
|
{
|
|
|
deleteVideoState();
|
|
deleteVideoState();
|
|
|
|
|
+ m_packetReadThread.reset();
|
|
|
|
|
+ m_decodeVideoThread.reset();
|
|
|
|
|
+ m_decodeAudioThread.reset();
|
|
|
|
|
+ m_decodeSubtitleThread.reset();
|
|
|
|
|
+ m_videoPlayThread.reset();
|
|
|
|
|
+ m_audioPlayThread.reset();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void PlayerController::pausePlay()
|
|
void PlayerController::pausePlay()
|