playercontroller.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880
  1. #include "playercontroller.h"
  2. #include "common.h"
  3. #include <QApplication>
  4. #include <QElapsedTimer>
  5. #include <QStatusBar>
  6. #include <cassert>
  7. #include <memory>
  8. #include "ffmpeg_init.h"
  9. #include "start_play_thread.h"
  10. #include "video_state.h"
  11. #include "audio_decode_thread.h"
  12. #include "audio_effect_helper.h"
  13. #include "audio_play_thread.h"
  14. #include "play_control_window.h"
  15. #include "read_thread.h"
  16. #include "start_play_thread.h"
  17. #include "stopplay_waiting_thread.h"
  18. #include "subtitle_decode_thread.h"
  19. #include "video_decode_thread.h"
  20. #include "video_play_thread.h"
  21. #include "video_state.h"
  22. Q_LOGGING_CATEGORY(playerControllerLog, "player.controller")
  23. PlayerController::PlayerController(QWidget* parent)
  24. : QObject(parent)
  25. {
  26. ffmpeg_init();
  27. m_state = PlayerState::Idle;
  28. }
  29. PlayerController::~PlayerController()
  30. {
  31. if (m_initThread.joinable()) {
  32. m_initThread.join();
  33. }
  34. stopPlay();
  35. }
  36. void PlayerController::startToPlay(const QString& file)
  37. {
  38. std::lock_guard<std::mutex> lock(m_stopMutex);
  39. qCDebug(playerControllerLog) << "[PlayerController] m_state" << (int) m_state.load();
  40. qDebug() << "[PlayerController] checkAndResetState: "
  41. << "m_packetReadThread:" << (bool) m_packetReadThread
  42. << "m_decodeVideoThread:" << (bool) m_decodeVideoThread
  43. << "m_decodeAudioThread:" << (bool) m_decodeAudioThread
  44. << "m_audioPlayThread:" << (bool) m_audioPlayThread
  45. << "m_videoPlayThread:" << (bool) m_videoPlayThread
  46. << "m_decodeSubtitleThread:" << (bool) m_decodeSubtitleThread << Qt::endl
  47. << "m_packetReadThread:"
  48. << (m_packetReadThread ? m_packetReadThread->isRunning() : false)
  49. << "m_decodeVideoThread:"
  50. << (m_decodeVideoThread ? m_decodeVideoThread->isRunning() : false)
  51. << "m_decodeAudioThread:"
  52. << (m_decodeAudioThread ? m_decodeAudioThread->isRunning() : false)
  53. << "m_audioPlayThread:" << (m_audioPlayThread ? m_audioPlayThread->isRunning() : false)
  54. << "m_videoPlayThread:" << (m_videoPlayThread ? m_videoPlayThread->isRunning() : false)
  55. << "m_decodeSubtitleThread:"
  56. << (m_decodeSubtitleThread ? m_decodeSubtitleThread->isRunning() : false);
  57. // 自愈:如果状态为Playing但所有线程都已退出,强制Idle
  58. if (m_state == PlayerState::Playing) {
  59. // 检查线程指针是否存在并且是否正在运行
  60. bool allThreadsStopped =
  61. (!m_packetReadThread || !m_packetReadThread->isRunning()) &&
  62. (!m_decodeVideoThread || !m_decodeVideoThread->isRunning()) &&
  63. (!m_decodeAudioThread || !m_decodeAudioThread->isRunning()) &&
  64. (!m_audioPlayThread || !m_audioPlayThread->isRunning()) &&
  65. (!m_videoPlayThread || !m_videoPlayThread->isRunning()) &&
  66. (!m_decodeSubtitleThread || !m_decodeSubtitleThread->isRunning());
  67. if (allThreadsStopped) {
  68. auto stopAndReset = [](auto& threadPtr) {
  69. if (threadPtr) {
  70. qCDebug(playerControllerLog)
  71. << "[stopAndReset] try stop/join thread, isRunning="
  72. << threadPtr->isRunning();
  73. threadPtr->stop();
  74. threadPtr->join();
  75. qCDebug(playerControllerLog) << "[stopAndReset] thread joined and will reset.";
  76. threadPtr.reset();
  77. }
  78. };
  79. stopAndReset(m_stopPlayWaitingThread);
  80. stopAndReset(m_beforePlayThread);
  81. stopAndReset(m_packetReadThread);
  82. stopAndReset(m_decodeVideoThread);
  83. stopAndReset(m_decodeAudioThread);
  84. stopAndReset(m_decodeSubtitleThread);
  85. stopAndReset(m_videoPlayThread);
  86. stopAndReset(m_audioPlayThread);
  87. m_currentFile.clear();
  88. m_state = PlayerState::Idle;
  89. qCDebug(playerControllerLog)
  90. << "[PlayerController] All threads stopped, force reset to Idle.";
  91. }
  92. }
  93. if (m_state == PlayerState::Initializing) {
  94. qCDebug(playerControllerLog) << "Player is initializing. Ignoring request.";
  95. return;
  96. }
  97. if (m_state == PlayerState::Playing) {
  98. if (m_currentFile == file) {
  99. qCDebug(playerControllerLog) << "Already playing the same file. Ignoring request.";
  100. return;
  101. } else {
  102. qCDebug(playerControllerLog)
  103. << "Player is busy with another file, stopping and switching to:" << file;
  104. stopPlay();
  105. // 这里直接 fallthrough 到 Idle 状态
  106. }
  107. }
  108. if (m_state == PlayerState::Idle) {
  109. bool allThreadsStopped = (!m_packetReadThread || !m_packetReadThread->isRunning())
  110. && (!m_decodeVideoThread || !m_decodeVideoThread->isRunning())
  111. && (!m_decodeAudioThread || !m_decodeAudioThread->isRunning())
  112. && (!m_audioPlayThread || !m_audioPlayThread->isRunning())
  113. && (!m_videoPlayThread || !m_videoPlayThread->isRunning())
  114. && (!m_decodeSubtitleThread
  115. || !m_decodeSubtitleThread->isRunning());
  116. if (allThreadsStopped) {
  117. auto stopAndReset = [](auto& threadPtr) {
  118. if (threadPtr) {
  119. qCDebug(playerControllerLog)
  120. << "[stopAndReset] try stop/join thread, isRunning="
  121. << threadPtr->isRunning();
  122. threadPtr->stop();
  123. threadPtr->join();
  124. qCDebug(playerControllerLog) << "[stopAndReset] thread joined and will reset.";
  125. threadPtr.reset();
  126. }
  127. };
  128. m_videoState.reset();
  129. stopAndReset(m_stopPlayWaitingThread);
  130. stopAndReset(m_beforePlayThread);
  131. stopAndReset(m_packetReadThread);
  132. stopAndReset(m_decodeVideoThread);
  133. stopAndReset(m_decodeAudioThread);
  134. stopAndReset(m_decodeSubtitleThread);
  135. stopAndReset(m_videoPlayThread);
  136. stopAndReset(m_audioPlayThread);
  137. m_currentFile.clear();
  138. m_state = PlayerState::Idle;
  139. qCDebug(playerControllerLog)
  140. << "[PlayerController] All threads stopped, force reset to Idle.";
  141. }
  142. qCDebug(playerControllerLog) << "Player is idle. Starting playback for:" << file;
  143. m_state = PlayerState::Initializing;
  144. m_currentFile = file;
  145. if (m_initThread.joinable()) {
  146. m_initThread.join();
  147. }
  148. m_initThread = std::thread(&PlayerController::asyncInit, this, file);
  149. }
  150. }
  151. void PlayerController::asyncInit(const QString& file)
  152. {
  153. bool success = false;
  154. QElapsedTimer timer;
  155. timer.start();
  156. qCDebug(playerControllerLog) << "[Init] asyncInit started";
  157. if (file.isEmpty()) {
  158. qCWarning(playerControllerLog) << "Filename is invalid. Please select a valid media file.";
  159. success = false;
  160. } else {
  161. qCInfo(playerControllerLog) << "Check file: " << toNativePath(file);
  162. success = true;
  163. }
  164. m_initSuccess = success;
  165. onAsyncInitFinished(file, success);
  166. qCDebug(playerControllerLog) << "[Init] asyncInit finished in " << timer.elapsed() << " ms";
  167. }
  168. void PlayerController::onAsyncInitFinished(const QString& file, bool success)
  169. {
  170. std::lock_guard<std::mutex> lock(m_stopMutex);
  171. if (!success) {
  172. playFailed(m_currentFile);
  173. m_state = PlayerState::Idle;
  174. return;
  175. }
  176. qCDebug(playerControllerLog) << "[Init] createVideoState...";
  177. if (!createVideoState(m_currentFile)) {
  178. qCWarning(playerControllerLog) << "Video state creation failed";
  179. readPacketStopped();
  180. playFailed(m_currentFile);
  181. m_state = PlayerState::Idle;
  182. return;
  183. }
  184. assert(m_videoState);
  185. qCDebug(playerControllerLog) << "[Init] createReadThread...";
  186. if (!createReadThread()) {
  187. qCWarning(playerControllerLog) << "Packet read thread creation failed";
  188. playFailed(m_currentFile);
  189. m_state = PlayerState::Idle;
  190. return;
  191. }
  192. if (!m_videoState) {
  193. qCWarning(playerControllerLog) << "Video state initialization error";
  194. playFailed(m_currentFile);
  195. m_state = PlayerState::Idle;
  196. return;
  197. }
  198. m_packetReadThread->set_video_state(m_videoState->get_state());
  199. const bool hasVideo = playingHasVideo();
  200. const bool hasAudio = playingHasAudio();
  201. const bool hasSubtitle = playingHasSubtitle();
  202. if (hasVideo) {
  203. if (!createDecodeVideoThread() || !createVideoPlayThread()) {
  204. qCWarning(playerControllerLog) << "Video processing setup failed";
  205. playFailed(m_currentFile);
  206. stopPlay();
  207. m_state = PlayerState::Idle;
  208. return;
  209. }
  210. }
  211. if (hasAudio) {
  212. if (!createDecodeAudioThread() || !createAudioPlayThread()) {
  213. qCWarning(playerControllerLog) << "Audio processing setup failed";
  214. playFailed(m_currentFile);
  215. stopPlay();
  216. m_state = PlayerState::Idle;
  217. return;
  218. }
  219. }
  220. if (hasSubtitle && !createDecodeSubtitleThread()) {
  221. qCWarning(playerControllerLog) << "Subtitle processing setup failed";
  222. playFailed(m_currentFile);
  223. stopPlay();
  224. m_state = PlayerState::Idle;
  225. return;
  226. }
  227. if (hasAudio) {
  228. startPlayThread();
  229. } else {
  230. playStarted();
  231. }
  232. emit startToPlaySignal();
  233. m_state = PlayerState::Playing;
  234. }
  235. void PlayerController::stopPlay()
  236. {
  237. std::lock_guard<std::mutex> lock(m_stopMutex);
  238. if (m_state == PlayerState::Idle)
  239. return;
  240. m_state = PlayerState::Stopping;
  241. m_videoState.reset();
  242. m_currentFile.clear();
  243. m_state = PlayerState::Idle;
  244. }
  245. void PlayerController::pausePlay()
  246. {
  247. if (!m_videoState)
  248. return;
  249. if (auto state = m_videoState->get_state())
  250. toggle_pause(state, !state->paused);
  251. emit updatePlayControlStatus();
  252. }
  253. void PlayerController::playMute(bool mute)
  254. {
  255. if (!m_videoState)
  256. return;
  257. if (auto state = m_videoState->get_state())
  258. toggle_mute(state, mute);
  259. }
  260. void PlayerController::playStartSeek()
  261. {
  262. emit playSeek();
  263. pausePlay();
  264. }
  265. void PlayerController::playSeekPre()
  266. {
  267. videoSeekInc(-2);
  268. }
  269. void PlayerController::playSeekNext()
  270. {
  271. videoSeekInc(2);
  272. }
  273. void PlayerController::setVolume(int volume, int maxValue)
  274. {
  275. if (!m_audioPlayThread)
  276. return;
  277. const float vol = static_cast<float>(volume) / maxValue;
  278. m_audioPlayThread->set_device_volume(vol);
  279. }
  280. void PlayerController::setPlaySpeed(double speed)
  281. {
  282. if (m_videoState) {
  283. if (auto state = m_videoState->get_state()) {
  284. #if USE_AVFILTER_AUDIO
  285. set_audio_playspeed(state, speed);
  286. #endif
  287. }
  288. }
  289. }
  290. // 状态访问接口
  291. QString PlayerController::playingFile() const
  292. {
  293. return isPlaying() ? m_currentFile : QString();
  294. }
  295. bool PlayerController::isPlaying() const
  296. {
  297. return m_state == PlayerState::Playing;
  298. }
  299. bool PlayerController::playingHasVideo()
  300. {
  301. return m_videoState ? m_videoState->has_video() : false;
  302. }
  303. bool PlayerController::playingHasAudio()
  304. {
  305. return m_videoState ? m_videoState->has_audio() : false;
  306. }
  307. bool PlayerController::playingHasSubtitle()
  308. {
  309. return m_videoState ? m_videoState->has_subtitle() : false;
  310. }
  311. VideoState* PlayerController::state()
  312. {
  313. return m_videoState ? m_videoState->get_state() : nullptr;
  314. }
  315. float PlayerController::deviceVolume() const
  316. {
  317. return m_audioPlayThread ? m_audioPlayThread->get_device_volume() : 0.0f;
  318. }
  319. void PlayerController::setDeviceVolume(float volume)
  320. {
  321. if (m_audioPlayThread)
  322. m_audioPlayThread->set_device_volume(volume);
  323. }
  324. // 播放状态回调槽函数
  325. void PlayerController::playStarted(bool success)
  326. {
  327. if (!success) {
  328. qCWarning(playerControllerLog) << "Audio device initialization failed!";
  329. return;
  330. }
  331. allThreadStart();
  332. setThreads();
  333. }
  334. void PlayerController::playFailed(const QString& file)
  335. {
  336. emit showMessage(QString("Playback failed: %1").arg(toNativePath(file)), "Warning", "");
  337. }
  338. // 线程 finished 槽函数只做日志和信号
  339. void PlayerController::readPacketStopped()
  340. {
  341. qCDebug(playerControllerLog) << "************* Read packets thread stopped signal received.";
  342. //m_packetReadThread.reset();
  343. checkAndResetState();
  344. // stopPlay();
  345. if (m_videoState) {
  346. m_videoState->delete_video_state();
  347. }
  348. emit audioStopped();
  349. }
  350. void PlayerController::decodeVideoStopped()
  351. {
  352. qCDebug(playerControllerLog) << "************* Video decode thread stopped.";
  353. //m_decodeVideoThread.reset();
  354. checkAndResetState();
  355. }
  356. void PlayerController::decodeAudioStopped()
  357. {
  358. qCDebug(playerControllerLog) << "************* Audio decode thread stopped.";
  359. //m_decodeAudioThread.reset();
  360. checkAndResetState();
  361. }
  362. void PlayerController::decodeSubtitleStopped()
  363. {
  364. qCDebug(playerControllerLog) << "************* Subtitle decode thread stopped.";
  365. //m_decodeSubtitleThread.reset();
  366. checkAndResetState();
  367. }
  368. void PlayerController::audioPlayStopped()
  369. {
  370. qCDebug(playerControllerLog) << "************* Audio play thread stopped.";
  371. emit audioStopped();
  372. //m_audioPlayThread.reset();
  373. checkAndResetState();
  374. }
  375. void PlayerController::videoPlayStopped()
  376. {
  377. qCDebug(playerControllerLog) << "************* Video play thread stopped.";
  378. emit videoStopped();
  379. // m_videoPlayThread.reset();
  380. checkAndResetState();
  381. }
  382. // 线程管理槽函数
  383. void PlayerController::setThreads()
  384. {
  385. if (!m_videoState)
  386. return;
  387. Threads threads;
  388. threads.read_tid = m_packetReadThread.get();
  389. threads.video_decode_tid = m_decodeVideoThread.get();
  390. threads.audio_decode_tid = m_decodeAudioThread.get();
  391. threads.video_play_tid = m_videoPlayThread.get();
  392. threads.audio_play_tid = m_audioPlayThread.get();
  393. threads.subtitle_decode_tid = m_decodeSubtitleThread.get();
  394. m_videoState->threads_setting(m_videoState->get_state(), threads);
  395. }
  396. void PlayerController::startSendData(bool send)
  397. {
  398. if (m_audioPlayThread)
  399. m_audioPlayThread->send_visual_open(send);
  400. }
  401. void PlayerController::videoSeek(double position, double increment)
  402. {
  403. if (!m_videoState)
  404. return;
  405. auto state = m_videoState->get_state();
  406. if (!state)
  407. return;
  408. if (state->ic->start_time != AV_NOPTS_VALUE
  409. && position < state->ic->start_time / static_cast<double>(AV_TIME_BASE)) {
  410. position = state->ic->start_time / static_cast<double>(AV_TIME_BASE);
  411. }
  412. stream_seek(state,
  413. static_cast<int64_t>(position * AV_TIME_BASE),
  414. static_cast<int64_t>(increment * AV_TIME_BASE),
  415. 0);
  416. }
  417. // 核心私有实现
  418. bool PlayerController::startPlay()
  419. {
  420. QElapsedTimer timer;
  421. timer.start();
  422. if (m_currentFile.isEmpty()) {
  423. qCWarning(playerControllerLog) << "Filename is invalid. Please select a valid media file.";
  424. return false;
  425. }
  426. qCInfo(playerControllerLog) << "Starting playback:" << toNativePath(m_currentFile);
  427. // 创建数据包读取线程
  428. if (!createReadThread()) {
  429. qCWarning(playerControllerLog) << "Packet read thread creation failed";
  430. return false;
  431. }
  432. // 创建视频状态对象
  433. if (!createVideoState(m_currentFile)) {
  434. qCWarning(playerControllerLog) << "Video state creation failed";
  435. readPacketStopped();
  436. return false;
  437. }
  438. // 检查状态有效性
  439. assert(m_videoState);
  440. if (!m_videoState) {
  441. qCWarning(playerControllerLog) << "Video state initialization error";
  442. return false;
  443. }
  444. m_packetReadThread->set_video_state(m_videoState->get_state());
  445. const bool hasVideo = playingHasVideo();
  446. const bool hasAudio = playingHasAudio();
  447. const bool hasSubtitle = playingHasSubtitle();
  448. // 创建视频相关线程
  449. if (hasVideo) {
  450. if (!createDecodeVideoThread() || !createVideoPlayThread()) {
  451. qCWarning(playerControllerLog) << "Video processing setup failed";
  452. return false;
  453. }
  454. }
  455. // 创建音频相关线程
  456. if (hasAudio) {
  457. if (!createDecodeAudioThread() || !createAudioPlayThread()) {
  458. qCWarning(playerControllerLog) << "Audio processing setup failed";
  459. return false;
  460. }
  461. }
  462. // 创建字幕线程
  463. if (hasSubtitle && !createDecodeSubtitleThread()) {
  464. qCWarning(playerControllerLog) << "Subtitle processing setup failed";
  465. return false;
  466. }
  467. // 开始播放
  468. if (hasAudio) {
  469. startPlayThread(); // 异步启动(处理音频设备初始化)
  470. } else {
  471. playStarted(); // 同步启动(无音频流)
  472. }
  473. qCDebug(playerControllerLog) << "Playback initialized in " << timer.elapsed() << " ms";
  474. return true;
  475. }
  476. bool PlayerController::waitStopPlay(const QString& file)
  477. {
  478. m_stopPlayWaitingThread = std::make_unique<StopWaitingThread>(this, file.toStdString());
  479. m_stopPlayWaitingThread->setOnFinished([this]() {
  480. // 可根据需要添加额外处理
  481. //m_stopPlayWaitingThread.reset();
  482. });
  483. m_stopPlayWaitingThread->start();
  484. qCDebug(playerControllerLog) << "++++++++++ StopPlay waiting thread started";
  485. return true;
  486. }
  487. void PlayerController::allThreadStart()
  488. {
  489. // 启动所有创建的线程
  490. if (m_packetReadThread) {
  491. if (!m_videoState || !m_videoState->get_state()) {
  492. qCWarning(playerControllerLog) << "VideoState invalid, skip starting read thread";
  493. } else {
  494. m_packetReadThread->start();
  495. }
  496. qCDebug(playerControllerLog) << "++++++++++ Read packets thread started";
  497. }
  498. if (m_decodeVideoThread) {
  499. m_decodeVideoThread->start();
  500. qCDebug(playerControllerLog) << "++++++++++ Video decode thread started";
  501. }
  502. if (m_decodeAudioThread) {
  503. m_decodeAudioThread->start();
  504. qCDebug(playerControllerLog) << "++++++++++ Audio decode thread started";
  505. }
  506. if (m_decodeSubtitleThread) {
  507. m_decodeSubtitleThread->start();
  508. qCDebug(playerControllerLog) << "++++++++++ Subtitle decode thread started";
  509. }
  510. if (m_videoPlayThread) {
  511. m_videoPlayThread->start();
  512. qCDebug(playerControllerLog) << "++++++++++ Video play thread started";
  513. }
  514. if (m_audioPlayThread) {
  515. m_audioPlayThread->start();
  516. qCDebug(playerControllerLog) << "++++++++++ Audio play thread started";
  517. }
  518. // 通知UI更新
  519. emit setPlayControlWnd(true);
  520. emit updatePlayControlVolume();
  521. emit updatePlayControlStatus();
  522. }
  523. // 辅助函数
  524. void PlayerController::videoSeekInc(double increment)
  525. {
  526. if (!m_videoState)
  527. return;
  528. auto state = m_videoState->get_state();
  529. if (!state)
  530. return;
  531. double position = get_master_clock(state);
  532. if (std::isnan(position)) {
  533. position = static_cast<double>(state->seek_pos) / AV_TIME_BASE;
  534. }
  535. position += increment;
  536. videoSeek(position, increment);
  537. }
  538. // 新增自愈机制辅助函数
  539. void PlayerController::checkAndResetState()
  540. {
  541. // std::lock_guard<std::mutex> lock(m_stopMutex);
  542. // if (!m_packetReadThread && !m_decodeVideoThread && !m_decodeAudioThread && !m_audioPlayThread
  543. // && !m_videoPlayThread && !m_decodeSubtitleThread) {
  544. // m_videoState.reset();
  545. // m_currentFile.clear();
  546. // m_state = PlayerState::Idle;
  547. // qCDebug(playerControllerLog)
  548. // << "[PlayerController] All threads stopped, state reset to Idle.";
  549. // emit playbackFinished(); // 新增:通知UI
  550. // } else {
  551. // qCDebug(playerControllerLog) << "[PlayerController] checkAndResetState: "
  552. // << "m_packetReadThread:" << (bool) m_packetReadThread
  553. // << "m_decodeVideoThread:" << (bool) m_decodeVideoThread
  554. // << "m_decodeAudioThread:" << (bool) m_decodeAudioThread
  555. // << "m_audioPlayThread:" << (bool) m_audioPlayThread
  556. // << "m_videoPlayThread:" << (bool) m_videoPlayThread
  557. // << "m_decodeSubtitleThread:" << (bool) m_decodeSubtitleThread;
  558. // }
  559. }
  560. // 线程创建方法
  561. bool PlayerController::createVideoState(const QString& file)
  562. {
  563. const bool useHardware = false; // 待实现:来自UI设置
  564. const bool loop = false; // 待实现:来自UI设置
  565. if (m_videoState)
  566. return false;
  567. m_videoState = std::make_unique<VideoStateData>(useHardware, loop);
  568. const int ret = m_videoState->create_video_state(file.toUtf8().constData());
  569. if (ret < 0) {
  570. m_videoState.reset();
  571. qCWarning(playerControllerLog) << "Video state creation failed (error: " << ret << ")";
  572. return false;
  573. }
  574. return true;
  575. }
  576. void PlayerController::deleteVideoState()
  577. {
  578. m_videoState.reset();
  579. }
  580. bool PlayerController::createReadThread()
  581. {
  582. if (m_packetReadThread)
  583. return false;
  584. m_packetReadThread = std::make_unique<ReadThread>(m_videoState ? m_videoState->get_state()
  585. : nullptr);
  586. m_packetReadThread->setOnFinished([this]() {
  587. readPacketStopped();
  588. });
  589. return true;
  590. }
  591. bool PlayerController::createDecodeVideoThread()
  592. {
  593. if (!m_videoState || m_decodeVideoThread)
  594. return false;
  595. auto state = m_videoState->get_state();
  596. if (!state)
  597. return false;
  598. m_decodeVideoThread = std::make_unique<VideoDecodeThread>(state);
  599. m_decodeVideoThread->setOnFinished([this]() { decodeVideoStopped(); });
  600. auto codecContext = m_videoState->get_contex(AVMEDIA_TYPE_VIDEO);
  601. // 初始化视频解码器
  602. int ret = decoder_init(&state->viddec,
  603. codecContext,
  604. &state->videoq,
  605. state->continue_read_thread);
  606. if (ret < 0) {
  607. qCWarning(playerControllerLog) << "Video decoder initialization failed (error: " << ret << ")";
  608. return false;
  609. }
  610. ret = decoder_start(&state->viddec, m_decodeVideoThread.get(), "video_decoder");
  611. if (ret < 0) {
  612. qCWarning(playerControllerLog) << "Video decoder start failed (error: " << ret << ")";
  613. return false;
  614. }
  615. state->queue_attachments_req = 1;
  616. return true;
  617. }
  618. bool PlayerController::createDecodeAudioThread()
  619. {
  620. if (!m_videoState || m_decodeAudioThread)
  621. return false;
  622. auto state = m_videoState->get_state();
  623. if (!state)
  624. return false;
  625. m_decodeAudioThread = std::make_unique<AudioDecodeThread>(state);
  626. m_decodeAudioThread->setOnFinished([this]() { decodeAudioStopped(); });
  627. auto codecContext = m_videoState->get_contex(AVMEDIA_TYPE_AUDIO);
  628. // 初始化音频解码器
  629. int ret = decoder_init(&state->auddec,
  630. codecContext,
  631. &state->audioq,
  632. state->continue_read_thread);
  633. if (ret < 0) {
  634. qCWarning(playerControllerLog) << "Audio decoder initialization failed (error: " << ret << ")";
  635. return false;
  636. }
  637. ret = decoder_start(&state->auddec, m_decodeAudioThread.get(), "audio_decoder");
  638. if (ret < 0) {
  639. qCWarning(playerControllerLog) << "Audio decoder start failed (error: " << ret << ")";
  640. return false;
  641. }
  642. return true;
  643. }
  644. bool PlayerController::createDecodeSubtitleThread()
  645. {
  646. if (!m_videoState || m_decodeSubtitleThread)
  647. return false;
  648. auto state = m_videoState->get_state();
  649. if (!state)
  650. return false;
  651. m_decodeSubtitleThread = std::make_unique<SubtitleDecodeThread>(state);
  652. m_decodeSubtitleThread->setOnFinished([this]() { decodeSubtitleStopped(); });
  653. auto codecContext = m_videoState->get_contex(AVMEDIA_TYPE_SUBTITLE);
  654. // 初始化字幕解码器
  655. int ret = decoder_init(&state->subdec,
  656. codecContext,
  657. &state->subtitleq,
  658. state->continue_read_thread);
  659. if (ret < 0) {
  660. qCWarning(playerControllerLog) << "Subtitle decoder initialization failed (error: " << ret << ")";
  661. return false;
  662. }
  663. ret = decoder_start(&state->subdec, m_decodeSubtitleThread.get(), "subtitle_decoder");
  664. if (ret < 0) {
  665. qCWarning(playerControllerLog) << "Subtitle decoder start failed (error: " << ret << ")";
  666. return false;
  667. }
  668. return true;
  669. }
  670. bool PlayerController::createVideoPlayThread()
  671. {
  672. if (!m_videoState || m_videoPlayThread)
  673. return false;
  674. auto state = m_videoState->get_state();
  675. if (!state)
  676. return false;
  677. m_videoPlayThread = std::make_unique<VideoPlayThread>(state);
  678. m_videoPlayThread->setOnFinished([this]() { videoPlayStopped(); });
  679. m_videoPlayThread->setOnFrameReady([this](AVFrame* frame) { this->onFrameReady(frame); });
  680. m_videoPlayThread->setOnSubtitleReady([this](const QString& text) {
  681. // TODO: 实现 PlayerController::onSubtitleReady(const QString&) 处理字幕
  682. // onSubtitleReady(text);
  683. });
  684. // 初始化参数
  685. auto videoContext = m_videoState->get_contex(AVMEDIA_TYPE_VIDEO);
  686. const bool useHardware = m_videoState->is_hardware_decode();
  687. if (!m_videoPlayThread->init_resample_param(videoContext, useHardware)) {
  688. qCWarning(playerControllerLog) << "Video resample parameters initialization failed";
  689. return false;
  690. }
  691. return true;
  692. }
  693. bool PlayerController::createAudioPlayThread()
  694. {
  695. if (!m_videoState || m_audioPlayThread)
  696. return false;
  697. auto state = m_videoState->get_state();
  698. if (!state)
  699. return false;
  700. m_audioPlayThread = std::make_unique<AudioPlayThread>(state);
  701. m_audioPlayThread->setOnFinished([this]() { audioPlayStopped(); });
  702. m_audioPlayThread->setOnUpdatePlayTime([this]() {
  703. // TODO: 实现 PlayerController::onUpdatePlayTime() 处理播放时间更新
  704. // onUpdatePlayTime();
  705. });
  706. m_audioPlayThread->setOnDataVisualReady([this](const AudioData& data) {
  707. // TODO: 实现 PlayerController::onDataVisualReady(const AudioData&) 处理可视化数据
  708. // onDataVisualReady(data);
  709. });
  710. // 连接信号
  711. // connect(m_audioPlayThread.get(),
  712. // &AudioPlayThread::update_play_time,
  713. // this,
  714. // &PlayerController::updatePlayTime);
  715. // connect(m_audioPlayThread.get(),
  716. // &AudioPlayThread::data_visual_ready,
  717. // this,
  718. // &PlayerController::audioData);
  719. // 音频设备初始化在独立线程中完成
  720. return true;
  721. }
  722. bool PlayerController::startPlayThread()
  723. {
  724. if (m_beforePlayThread)
  725. return false;
  726. m_beforePlayThread = std::make_unique<StartPlayThread>(m_audioPlayThread.get(), m_videoState.get());
  727. m_beforePlayThread->setOnFinished([this]() {
  728. qCDebug(playerControllerLog) << "[StartPlayThread] finished, call playStarted()";
  729. playStarted();
  730. });
  731. m_beforePlayThread->start();
  732. qCDebug(playerControllerLog) << "++++++++++ StartPlay thread (audio init) started";
  733. return true;
  734. }
  735. // 调试辅助函数
  736. void PlayerController::printDecodeContext(const AVCodecContext* codecCtx, bool isVideo) const
  737. {
  738. if (!codecCtx)
  739. return;
  740. qCInfo(playerControllerLog) << (isVideo ? "Video" : "Audio") << " codec: " << codecCtx->codec->name;
  741. qCInfo(playerControllerLog) << " Type:" << codecCtx->codec_type << "ID:" << codecCtx->codec_id << "Tag:" << codecCtx->codec_tag;
  742. if (isVideo) {
  743. qCInfo(playerControllerLog) << " Dimensions: " << codecCtx->width << "x" << codecCtx->height;
  744. } else {
  745. qCInfo(playerControllerLog) << " Sample rate: " << codecCtx->sample_rate << " Hz, Channels: " << codecCtx->ch_layout.nb_channels << ", Format: " << codecCtx->sample_fmt;
  746. qCInfo(playerControllerLog) << " Frame size: " << codecCtx->frame_size << ", Block align: " << codecCtx->block_align;
  747. }
  748. }
  749. // 在合适位置实现 onFrameReady
  750. void PlayerController::onFrameReady(AVFrame* frame)
  751. {
  752. // 这里可以做帧处理、缓存、同步等操作
  753. emit frameReady(frame); // 直接转发给 UI 层
  754. }