media_streaming_player.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "media/streaming/media_streaming_player.h"
  8. #include "media/streaming/media_streaming_file.h"
  9. #include "media/streaming/media_streaming_loader.h"
  10. #include "media/streaming/media_streaming_audio_track.h"
  11. #include "media/streaming/media_streaming_video_track.h"
  12. #include "media/audio/media_audio.h" // for SupportsSpeedControl()
  13. #include "media/media_common.h"
  14. #include "data/data_document.h" // for DocumentData::duration()
  15. namespace Media {
  16. namespace Streaming {
  17. namespace {
  18. constexpr auto kBufferFor = 3 * crl::time(1000);
  19. constexpr auto kLoadInAdvanceForRemote = 32 * crl::time(1000);
  20. constexpr auto kLoadInAdvanceForLocal = 5 * crl::time(1000);
  21. constexpr auto kMsFrequency = 1000; // 1000 ms per second.
  22. // If we played for 3 seconds and got stuck it looks like we're loading
  23. // slower than we're playing, so load full file in that case.
  24. //constexpr auto kLoadFullIfStuckAfterPlayback = 3 * crl::time(1000);
  25. [[nodiscard]] bool FullTrackReceived(const TrackState &state) {
  26. return (state.duration != kTimeUnknown)
  27. && (state.receivedTill == state.duration);
  28. }
  29. void SaveValidStateInformation(TrackState &to, TrackState &&from) {
  30. Expects(from.position != kTimeUnknown);
  31. Expects(from.receivedTill != kTimeUnknown);
  32. Expects(from.duration != kTimeUnknown);
  33. to.duration = from.duration;
  34. to.position = from.position;
  35. to.receivedTill = (to.receivedTill == kTimeUnknown)
  36. ? from.receivedTill
  37. : std::clamp(
  38. std::max(from.receivedTill, to.receivedTill),
  39. to.position,
  40. to.duration);
  41. }
  42. void SaveValidAudioInformation(
  43. AudioInformation &to,
  44. AudioInformation &&from) {
  45. SaveValidStateInformation(to.state, std::move(from.state));
  46. }
  47. void SaveValidVideoInformation(
  48. VideoInformation &to,
  49. VideoInformation &&from) {
  50. Expects(!from.size.isEmpty());
  51. Expects(!from.cover.isNull());
  52. SaveValidStateInformation(to.state, std::move(from.state));
  53. to.size = from.size;
  54. to.cover = std::move(from.cover);
  55. to.rotation = from.rotation;
  56. to.alpha = from.alpha;
  57. }
  58. void SaveValidStartInformation(Information &to, Information &&from) {
  59. if (from.audio.state.duration != kTimeUnknown) {
  60. SaveValidAudioInformation(to.audio, std::move(from.audio));
  61. }
  62. if (from.video.state.duration != kTimeUnknown) {
  63. SaveValidVideoInformation(to.video, std::move(from.video));
  64. }
  65. if (from.headerSize && !to.headerSize) {
  66. to.headerSize = from.headerSize;
  67. }
  68. }
  69. } // namespace
  70. Player::Player(std::shared_ptr<Reader> reader)
  71. : _file(std::make_unique<File>(std::move(reader)))
  72. , _remoteLoader(_file->isRemoteLoader())
  73. , _renderFrameTimer([=] { checkNextFrameRender(); }) {
  74. }
  75. not_null<FileDelegate*> Player::delegate() {
  76. return static_cast<FileDelegate*>(this);
  77. }
  78. void Player::checkNextFrameRender() {
  79. Expects(_nextFrameTime != kTimeUnknown);
  80. const auto now = crl::now();
  81. if (now < _nextFrameTime) {
  82. if (!_renderFrameTimer.isActive()) {
  83. _renderFrameTimer.callOnce(_nextFrameTime - now);
  84. }
  85. } else {
  86. _renderFrameTimer.cancel();
  87. renderFrame(now);
  88. }
  89. }
  90. void Player::checkNextFrameAvailability() {
  91. Expects(_video != nullptr);
  92. _nextFrameTime = _video->nextFrameDisplayTime();
  93. Assert(_nextFrameTime != kFrameDisplayTimeAlreadyDone);
  94. if (_nextFrameTime != kTimeUnknown) {
  95. checkNextFrameRender();
  96. }
  97. }
  98. void Player::renderFrame(crl::time now) {
  99. Expects(_video != nullptr);
  100. Expects(_nextFrameTime != kTimeUnknown);
  101. Expects(_nextFrameTime != kFrameDisplayTimeAlreadyDone);
  102. const auto position = _video->markFrameDisplayed(now);
  103. if (_options.waitForMarkAsShown) {
  104. _currentFrameTime = _nextFrameTime;
  105. _nextFrameTime = kFrameDisplayTimeAlreadyDone;
  106. } else {
  107. _video->markFrameShown();
  108. _nextFrameTime = kTimeUnknown;
  109. }
  110. Assert(position != kTimeUnknown);
  111. videoPlayedTill(position);
  112. }
  113. bool Player::markFrameShown() {
  114. Expects(_video != nullptr);
  115. if (_nextFrameTime == kFrameDisplayTimeAlreadyDone) {
  116. _nextFrameTime = kTimeUnknown;
  117. _video->addTimelineDelay(crl::now() - _currentFrameTime);
  118. }
  119. return _video->markFrameShown();
  120. }
  121. void Player::setLoaderPriority(int priority) {
  122. _file->setLoaderPriority(priority);
  123. }
  124. template <typename Track>
  125. void Player::trackReceivedTill(
  126. const Track &track,
  127. TrackState &state,
  128. crl::time position) {
  129. if (position == kTimeUnknown) {
  130. return;
  131. } else if (state.duration != kTimeUnknown) {
  132. if (state.receivedTill < position) {
  133. state.receivedTill = position;
  134. trackSendReceivedTill(track, state);
  135. }
  136. } else {
  137. state.receivedTill = position;
  138. }
  139. if (!_pauseReading
  140. && bothReceivedEnough(loadInAdvanceFor())
  141. && !receivedTillEnd()) {
  142. _pauseReading = true;
  143. }
  144. }
  145. template <typename Track>
  146. void Player::trackPlayedTill(
  147. const Track &track,
  148. TrackState &state,
  149. crl::time position) {
  150. const auto guard = base::make_weak(&_sessionGuard);
  151. trackReceivedTill(track, state, position);
  152. if (guard && position != kTimeUnknown) {
  153. state.position = position;
  154. const auto value = _options.loop
  155. ? (position % computeTotalDuration())
  156. : position;
  157. _updates.fire({ PlaybackUpdate<Track>{ value } });
  158. }
  159. if (_pauseReading
  160. && (!bothReceivedEnough(loadInAdvanceFor()) || receivedTillEnd())) {
  161. _pauseReading = false;
  162. _file->wake();
  163. }
  164. }
  165. template <typename Track>
  166. void Player::trackSendReceivedTill(
  167. const Track &track,
  168. TrackState &state) {
  169. Expects(state.duration != kTimeUnknown);
  170. Expects(state.receivedTill != kTimeUnknown);
  171. if (!_remoteLoader || _fullInCacheSinceStart.value_or(false)) {
  172. return;
  173. }
  174. const auto receivedTill = std::max(
  175. state.receivedTill,
  176. _previousReceivedTill);
  177. const auto value = _options.loop
  178. ? (receivedTill % computeTotalDuration())
  179. : receivedTill;
  180. _updates.fire({ PreloadedUpdate<Track>{ value } });
  181. }
  182. void Player::audioReceivedTill(crl::time position) {
  183. Expects(_audio != nullptr);
  184. trackReceivedTill(*_audio, _information.audio.state, position);
  185. checkResumeFromWaitingForData();
  186. }
  187. void Player::audioPlayedTill(crl::time position) {
  188. Expects(_audio != nullptr);
  189. trackPlayedTill(*_audio, _information.audio.state, position);
  190. }
  191. void Player::videoReceivedTill(crl::time position) {
  192. Expects(_video != nullptr);
  193. trackReceivedTill(*_video, _information.video.state, position);
  194. checkResumeFromWaitingForData();
  195. }
  196. void Player::videoPlayedTill(crl::time position) {
  197. Expects(_video != nullptr);
  198. trackPlayedTill(*_video, _information.video.state, position);
  199. }
  200. Mode Player::fileOpenMode() {
  201. return _options.mode;
  202. }
  203. bool Player::fileReady(int headerSize, Stream &&video, Stream &&audio) {
  204. _waitingForData = false;
  205. const auto weak = base::make_weak(&_sessionGuard);
  206. const auto ready = [=](const Information &data) {
  207. crl::on_main(weak, [=, data = data]() mutable {
  208. data.headerSize = headerSize;
  209. streamReady(std::move(data));
  210. });
  211. };
  212. const auto error = [=](Error error) {
  213. crl::on_main(weak, [=] {
  214. streamFailed(error);
  215. });
  216. };
  217. const auto mode = _options.mode;
  218. if ((mode != Mode::Audio && mode != Mode::Both)
  219. || audio.duration == kDurationUnavailable) {
  220. audio = Stream();
  221. }
  222. if (mode != Mode::Video && mode != Mode::Both) {
  223. video = Stream();
  224. }
  225. if (audio.duration == kDurationUnavailable) {
  226. LOG(("Streaming Error: Audio stream with unknown duration."));
  227. return false;
  228. } else if (audio.codec) {
  229. if (_options.audioId.audio() != nullptr) {
  230. _audioId = AudioMsgId(
  231. _options.audioId.audio(),
  232. _options.audioId.contextId(),
  233. AudioMsgId::CreateExternalPlayId());
  234. } else {
  235. _audioId = AudioMsgId::ForVideo();
  236. }
  237. _audio = std::make_unique<AudioTrack>(
  238. _options,
  239. std::move(audio),
  240. _audioId,
  241. ready,
  242. error);
  243. } else if (audio.index >= 0) {
  244. LOG(("Streaming Error: No codec for audio stream %1, mode %2."
  245. ).arg(audio.index
  246. ).arg(int(mode)));
  247. return false;
  248. } else {
  249. _audioId = AudioMsgId();
  250. }
  251. if (video.codec) {
  252. _video = std::make_unique<VideoTrack>(
  253. _options,
  254. std::move(video),
  255. _audioId,
  256. ready,
  257. error);
  258. } else if (video.index >= 0) {
  259. LOG(("Streaming Error: No codec for video stream %1, mode %2."
  260. ).arg(video.index
  261. ).arg(int(mode)));
  262. return false;
  263. }
  264. if ((mode == Mode::Audio && !_audio)
  265. || (mode == Mode::Video && !_video)
  266. || (!_audio && !_video)) {
  267. LOG(("Streaming Error: Required stream not found for mode %1."
  268. ).arg(int(mode)));
  269. return false;
  270. } else if (_audio
  271. && _video
  272. && _video->streamDuration() == kDurationUnavailable) {
  273. LOG(("Streaming Error: Both streams with unknown video duration."));
  274. return false;
  275. }
  276. _totalDuration = std::max(
  277. _audio ? _audio->streamDuration() : kTimeUnknown,
  278. _video ? _video->streamDuration() : kTimeUnknown);
  279. Ensures(_totalDuration > 1);
  280. return true;
  281. }
  282. void Player::fileError(Error error) {
  283. _waitingForData = false;
  284. crl::on_main(&_sessionGuard, [=] {
  285. fail(error);
  286. });
  287. }
  288. void Player::fileFullInCache(bool fullInCache) {
  289. crl::on_main(&_sessionGuard, [=] {
  290. if (!_fullInCacheSinceStart.has_value()) {
  291. _fullInCacheSinceStart = fullInCache;
  292. }
  293. _fullInCache.fire_copy(fullInCache);
  294. });
  295. }
  296. void Player::fileWaitingForData() {
  297. if (_waitingForData) {
  298. return;
  299. }
  300. _waitingForData = true;
  301. if (_audio) {
  302. _audio->waitForData();
  303. }
  304. if (_video) {
  305. _video->waitForData();
  306. }
  307. }
  308. bool Player::fileProcessPackets(
  309. base::flat_map<int, std::vector<FFmpeg::Packet>> &packets) {
  310. _waitingForData = false;
  311. for (auto &[index, list] : packets) {
  312. if (list.empty()) {
  313. continue;
  314. }
  315. if (_audio && _audio->streamIndex() == index) {
  316. //for (const auto &packet : list) {
  317. // // Maybe it is enough to count by list.back()?.. hope so.
  318. // accumulate_max(
  319. // _durationByLastAudioPacket,
  320. // durationByPacket(*_audio, packet));
  321. //}
  322. accumulate_max(
  323. _durationByLastAudioPacket,
  324. durationByPacket(*_audio, list.back()));
  325. const auto till = _loopingShift + std::clamp(
  326. FFmpeg::PacketPosition(
  327. list.back(),
  328. _audio->streamTimeBase()),
  329. crl::time(0),
  330. computeAudioDuration() - 1);
  331. crl::on_main(&_sessionGuard, [=] {
  332. audioReceivedTill(till);
  333. });
  334. _audio->process(base::take(list));
  335. } else if (_video && _video->streamIndex() == index) {
  336. //for (const auto &packet : list) {
  337. // // Maybe it is enough to count by list.back()?.. hope so.
  338. // accumulate_max(
  339. // _durationByLastVideoPacket,
  340. // durationByPacket(*_video, packet));
  341. //}
  342. accumulate_max(
  343. _durationByLastVideoPacket,
  344. durationByPacket(*_video, list.back()));
  345. const auto till = _loopingShift + std::clamp(
  346. FFmpeg::PacketPosition(
  347. list.back(),
  348. _video->streamTimeBase()),
  349. crl::time(0),
  350. computeVideoDuration() - 1);
  351. crl::on_main(&_sessionGuard, [=] {
  352. videoReceivedTill(till);
  353. });
  354. _video->process(base::take(list));
  355. } else {
  356. list.clear(); // Free non-needed packets.
  357. }
  358. }
  359. return fileReadMore();
  360. }
  361. void Player::fileProcessEndOfFile() {
  362. _waitingForData = false;
  363. _readTillEnd = true;
  364. setDurationByPackets();
  365. const auto generateEmptyQueue = [] {
  366. auto result = std::vector<FFmpeg::Packet>();
  367. result.emplace_back();
  368. return result;
  369. };
  370. if (_audio) {
  371. const auto till = _loopingShift + computeAudioDuration();
  372. crl::on_main(&_sessionGuard, [=] {
  373. audioReceivedTill(till);
  374. });
  375. _audio->process(generateEmptyQueue());
  376. }
  377. if (_video) {
  378. const auto till = _loopingShift + computeVideoDuration();
  379. crl::on_main(&_sessionGuard, [=] {
  380. videoReceivedTill(till);
  381. });
  382. _video->process(generateEmptyQueue());
  383. }
  384. }
  385. bool Player::fileReadMore() {
  386. if (_options.loop && _readTillEnd) {
  387. const auto duration = computeTotalDuration();
  388. if (duration == kDurationUnavailable) {
  389. LOG(("Streaming Error: "
  390. "Couldn't find out the real stream duration."));
  391. fileError(Error::InvalidData);
  392. return false;
  393. }
  394. _loopingShift += duration;
  395. _readTillEnd = false;
  396. return true;
  397. }
  398. return !_readTillEnd && !_pauseReading;
  399. }
  400. void Player::streamReady(Information &&information) {
  401. SaveValidStartInformation(_information, std::move(information));
  402. provideStartInformation();
  403. }
  404. void Player::streamFailed(Error error) {
  405. fail(error);
  406. }
  407. template <typename Track>
  408. int Player::durationByPacket(
  409. const Track &track,
  410. const FFmpeg::Packet &packet) {
  411. // We've set this value on the first cycle.
  412. if (_loopingShift || _totalDuration != kDurationUnavailable) {
  413. return 0;
  414. }
  415. const auto result = DurationByPacket(packet, track.streamTimeBase());
  416. if (result < 0) {
  417. fileError(Error::InvalidData);
  418. return 0;
  419. }
  420. Ensures(result > 0);
  421. return result;
  422. }
  423. void Player::setDurationByPackets() {
  424. if (_loopingShift || _totalDuration != kDurationUnavailable) {
  425. return;
  426. }
  427. const auto duration = std::max(
  428. _durationByLastAudioPacket,
  429. _durationByLastVideoPacket);
  430. if (duration > 1) {
  431. _durationByPackets = duration;
  432. } else {
  433. LOG(("Streaming Error: Bad total duration by packets: %1"
  434. ).arg(duration));
  435. fileError(Error::InvalidData);
  436. }
  437. }
  438. void Player::provideStartInformation() {
  439. Expects(_stage == Stage::Initializing);
  440. if ((_audio && _information.audio.state.duration == kTimeUnknown)
  441. || (_video && _information.video.state.duration == kTimeUnknown)) {
  442. return; // Not ready yet.
  443. } else if ((!_audio && !_video)
  444. || (!_audio && _options.mode == Mode::Audio)
  445. || (!_video && _options.mode == Mode::Video)) {
  446. fail(Error::OpenFailed);
  447. } else {
  448. _stage = Stage::Ready;
  449. if (_audio && _audioFinished) {
  450. // Audio was stopped before it was ready.
  451. _audio->stop();
  452. }
  453. // Don't keep the reference to the video cover.
  454. auto copy = _information;
  455. _information.video.cover = QImage();
  456. _updates.fire(Update{ std::move(copy) });
  457. if (_stage == Stage::Ready && !_paused) {
  458. _paused = true;
  459. updatePausedState();
  460. }
  461. }
  462. }
  463. void Player::fail(Error error) {
  464. _sessionLifetime = rpl::lifetime();
  465. const auto stopGuarded = crl::guard(&_sessionGuard, [=] { stop(); });
  466. _lastFailure = error;
  467. _updates.fire_error(std::move(error));
  468. stopGuarded();
  469. }
  470. void Player::play(const PlaybackOptions &options) {
  471. Expects(options.speed >= kSpeedMin && options.speed <= kSpeedMax);
  472. // Looping video with audio is not supported for now.
  473. Expects(!options.loop || (options.mode != Mode::Both));
  474. const auto previous = getCurrentReceivedTill(computeTotalDuration());
  475. stop(true);
  476. _lastFailure = std::nullopt;
  477. savePreviousReceivedTill(options, previous);
  478. _options = options;
  479. if (!Media::Audio::SupportsSpeedControl()) {
  480. _options.speed = 1.;
  481. }
  482. if (!_options.seekable) {
  483. _options.position = 0;
  484. }
  485. _stage = Stage::Initializing;
  486. _file->start(delegate(), {
  487. .position = _options.position,
  488. .durationOverride = options.durationOverride,
  489. .seekable = _options.seekable,
  490. .hwAllow = _options.hwAllowed,
  491. });
  492. }
  493. void Player::savePreviousReceivedTill(
  494. const PlaybackOptions &options,
  495. crl::time previousReceivedTill) {
  496. // Save previous 'receivedTill' values if we seek inside the range.
  497. _previousReceivedTill = ((options.position >= _options.position)
  498. && (options.mode == _options.mode)
  499. && (options.position < previousReceivedTill))
  500. ? previousReceivedTill
  501. : kTimeUnknown;
  502. }
  503. crl::time Player::loadInAdvanceFor() const {
  504. return _remoteLoader ? kLoadInAdvanceForRemote : kLoadInAdvanceForLocal;
  505. }
  506. crl::time Player::computeTotalDuration() const {
  507. if (_totalDuration != kDurationUnavailable) {
  508. return _totalDuration;
  509. } else if (const auto byPackets = _durationByPackets.load()) {
  510. return byPackets;
  511. }
  512. return kDurationUnavailable;
  513. }
  514. crl::time Player::computeAudioDuration() const {
  515. Expects(_audio != nullptr);
  516. const auto result = _audio->streamDuration();
  517. if (result != kDurationUnavailable) {
  518. return result;
  519. } else if ((_loopingShift || _readTillEnd)
  520. && _durationByLastAudioPacket) {
  521. // We looped, so it already holds full stream duration.
  522. return _durationByLastAudioPacket;
  523. }
  524. return kDurationUnavailable;
  525. }
  526. crl::time Player::computeVideoDuration() const {
  527. Expects(_video != nullptr);
  528. const auto result = _video->streamDuration();
  529. if (result != kDurationUnavailable) {
  530. return result;
  531. } else if ((_loopingShift || _readTillEnd)
  532. && _durationByLastVideoPacket) {
  533. // We looped, so it already holds full stream duration.
  534. return _durationByLastVideoPacket;
  535. }
  536. return kDurationUnavailable;
  537. }
  538. void Player::pause() {
  539. Expects(active());
  540. _pausedByUser = true;
  541. updatePausedState();
  542. }
  543. void Player::resume() {
  544. Expects(active());
  545. _pausedByUser = false;
  546. updatePausedState();
  547. }
  548. void Player::stop() {
  549. stop(false);
  550. }
  551. void Player::stopAudio() {
  552. if (!_video) {
  553. stop();
  554. } else if (_audio) {
  555. _audioFinished = true;
  556. if (_information.audio.state.duration != kTimeUnknown) {
  557. // Audio is ready.
  558. _audio->stop();
  559. }
  560. }
  561. }
  562. void Player::updatePausedState() {
  563. const auto paused = _pausedByUser || _pausedByWaitingForData;
  564. if (_paused == paused) {
  565. return;
  566. }
  567. _paused = paused;
  568. if (!_paused && _stage == Stage::Ready) {
  569. const auto guard = base::make_weak(&_sessionGuard);
  570. start();
  571. if (!guard) {
  572. return;
  573. }
  574. }
  575. if (_stage != Stage::Started) {
  576. return;
  577. }
  578. if (_paused) {
  579. _pausedTime = crl::now();
  580. //if (_pausedByWaitingForData
  581. // && _pausedTime - _startedTime > kLoadFullIfStuckAfterPlayback) {
  582. // _loadFull = true;
  583. //}
  584. if (_audio) {
  585. _audio->pause(_pausedTime);
  586. }
  587. if (_video) {
  588. _video->pause(_pausedTime);
  589. }
  590. } else {
  591. _startedTime = crl::now();
  592. if (_audio) {
  593. _audio->resume(_startedTime);
  594. }
  595. if (_video) {
  596. _video->resume(_startedTime);
  597. }
  598. }
  599. }
  600. bool Player::trackReceivedEnough(
  601. const TrackState &state,
  602. crl::time amount) const {
  603. return (!_options.loop && FullTrackReceived(state))
  604. || (state.position != kTimeUnknown
  605. && (state.position + std::min(amount, state.duration)
  606. <= state.receivedTill));
  607. }
  608. bool Player::bothReceivedEnough(crl::time amount) const {
  609. const auto &info = _information;
  610. return (!_audio || trackReceivedEnough(info.audio.state, amount))
  611. && (!_video || trackReceivedEnough(info.video.state, amount));
  612. }
  613. bool Player::receivedTillEnd() const {
  614. if (_options.loop) {
  615. return false;
  616. }
  617. return (!_video || FullTrackReceived(_information.video.state))
  618. && (!_audio || FullTrackReceived(_information.audio.state));
  619. }
  620. void Player::checkResumeFromWaitingForData() {
  621. if (_pausedByWaitingForData && bothReceivedEnough(kBufferFor)) {
  622. _pausedByWaitingForData = false;
  623. updatePausedState();
  624. _updates.fire({ WaitingForData{ false } });
  625. }
  626. }
  627. void Player::start() {
  628. Expects(_stage == Stage::Ready);
  629. _stage = Stage::Started;
  630. const auto guard = base::make_weak(&_sessionGuard);
  631. _file->speedEstimate() | rpl::start_with_next([=](SpeedEstimate value) {
  632. _updates.fire({ value });
  633. }, _sessionLifetime);
  634. rpl::merge(
  635. _audio ? _audio->waitingForData() : nullptr,
  636. _video ? _video->waitingForData() : nullptr
  637. ) | rpl::filter([=] {
  638. return !bothReceivedEnough(kBufferFor);
  639. }) | rpl::start_with_next([=] {
  640. _pausedByWaitingForData = true;
  641. updatePausedState();
  642. _updates.fire({ WaitingForData{ true } });
  643. }, _sessionLifetime);
  644. if (guard && _audio && !_audioFinished) {
  645. _audio->playPosition(
  646. ) | rpl::start_with_next_done([=](crl::time position) {
  647. audioPlayedTill(position);
  648. }, [=] {
  649. Expects(_stage == Stage::Started);
  650. _audioFinished = true;
  651. if (!_video || _videoFinished) {
  652. _updates.fire({ Finished() });
  653. }
  654. }, _sessionLifetime);
  655. }
  656. if (guard && _video) {
  657. _video->checkNextFrame(
  658. ) | rpl::start_with_next_done([=] {
  659. checkVideoStep();
  660. }, [=] {
  661. Assert(_stage == Stage::Started);
  662. _videoFinished = true;
  663. if (!_audio || _audioFinished) {
  664. _updates.fire({ Finished() });
  665. }
  666. }, _sessionLifetime);
  667. crl::on_main_update_requests(
  668. ) | rpl::filter([=] {
  669. return !_videoFinished;
  670. }) | rpl::start_with_next([=] {
  671. checkVideoStep();
  672. }, _sessionLifetime);
  673. }
  674. if (guard && _audio) {
  675. if (_audioFinished) {
  676. if (!_video || _videoFinished) {
  677. _updates.fire({ Finished() });
  678. }
  679. } else {
  680. trackSendReceivedTill(*_audio, _information.audio.state);
  681. }
  682. }
  683. if (guard && _video) {
  684. trackSendReceivedTill(*_video, _information.video.state);
  685. }
  686. }
  687. void Player::checkVideoStep() {
  688. if (_nextFrameTime == kFrameDisplayTimeAlreadyDone) {
  689. return;
  690. } else if (_nextFrameTime != kTimeUnknown) {
  691. checkNextFrameRender();
  692. } else {
  693. checkNextFrameAvailability();
  694. }
  695. }
  696. void Player::stop(bool stillActive) {
  697. _file->stop(stillActive);
  698. _sessionLifetime = rpl::lifetime();
  699. _stage = Stage::Uninitialized;
  700. _audio = nullptr;
  701. _video = nullptr;
  702. invalidate_weak_ptrs(&_sessionGuard);
  703. _pausedByUser = _pausedByWaitingForData = _paused = false;
  704. _renderFrameTimer.cancel();
  705. _nextFrameTime = kTimeUnknown;
  706. _audioFinished = false;
  707. _videoFinished = false;
  708. _pauseReading = false;
  709. _readTillEnd = false;
  710. _loopingShift = 0;
  711. _durationByPackets = 0;
  712. _durationByLastAudioPacket = 0;
  713. _durationByLastVideoPacket = 0;
  714. const auto header = _information.headerSize;
  715. _information = Information();
  716. _information.headerSize = header;
  717. }
  718. std::optional<Error> Player::failed() const {
  719. return _lastFailure;
  720. }
  721. bool Player::playing() const {
  722. return (_stage == Stage::Started)
  723. && !paused()
  724. && !finished()
  725. && !failed();
  726. }
  727. bool Player::buffering() const {
  728. return _pausedByWaitingForData;
  729. }
  730. bool Player::paused() const {
  731. return _pausedByUser && active();
  732. }
  733. bool Player::finished() const {
  734. return (_stage == Stage::Started)
  735. && (!_audio || _audioFinished)
  736. && (!_video || _videoFinished);
  737. }
  738. float64 Player::speed() const {
  739. return _options.speed;
  740. }
  741. void Player::setSpeed(float64 speed) {
  742. Expects(speed >= kSpeedMin && speed <= kSpeedMax);
  743. if (!Media::Audio::SupportsSpeedControl()) {
  744. speed = 1.;
  745. }
  746. if (!EqualSpeeds(_options.speed, speed)) {
  747. _options.speed = speed;
  748. if (active()) {
  749. if (_audio) {
  750. _audio->setSpeed(speed);
  751. }
  752. if (_video) {
  753. _video->setSpeed(speed);
  754. }
  755. }
  756. }
  757. }
  758. void Player::setWaitForMarkAsShown(bool wait) {
  759. if (_options.waitForMarkAsShown != wait) {
  760. _options.waitForMarkAsShown = wait;
  761. if (_video) {
  762. _video->setWaitForMarkAsShown(wait);
  763. }
  764. }
  765. }
  766. bool Player::active() const {
  767. return (_stage != Stage::Uninitialized) && !finished() && !failed();
  768. }
  769. bool Player::ready() const {
  770. return (_stage != Stage::Uninitialized)
  771. && (_stage != Stage::Initializing);
  772. }
  773. rpl::producer<Update, Error> Player::updates() const {
  774. return _updates.events();
  775. }
  776. rpl::producer<bool> Player::fullInCache() const {
  777. return _fullInCache.events();
  778. }
  779. int64 Player::fileSize() const {
  780. return _file->size();
  781. }
  782. QSize Player::videoSize() const {
  783. return _information.video.size;
  784. }
  785. QImage Player::frame(
  786. const FrameRequest &request,
  787. const Instance *instance) const {
  788. Expects(_video != nullptr);
  789. return _video->frame(request, instance);
  790. }
  791. FrameWithInfo Player::frameWithInfo(
  792. const FrameRequest &request,
  793. const Instance *instance) const {
  794. Expects(_video != nullptr);
  795. return _video->frameWithInfo(request, instance);
  796. }
  797. FrameWithInfo Player::frameWithInfo(const Instance *instance) const {
  798. Expects(_video != nullptr);
  799. return _video->frameWithInfo(instance);
  800. }
  801. QImage Player::currentFrameImage() const {
  802. Expects(_video != nullptr);
  803. return _video->currentFrameImage();
  804. }
  805. void Player::unregisterInstance(not_null<const Instance*> instance) {
  806. if (_video) {
  807. _video->unregisterInstance(instance);
  808. }
  809. }
  810. Media::Player::TrackState Player::prepareLegacyState() const {
  811. using namespace Media::Player;
  812. auto result = Media::Player::TrackState();
  813. result.id = _audioId.externalPlayId() ? _audioId : _options.audioId;
  814. result.state = (_lastFailure == Error::OpenFailed
  815. || _lastFailure == Error::NotStreamable)
  816. ? State::StoppedAtStart
  817. : _lastFailure
  818. ? State::StoppedAtError
  819. : finished()
  820. ? State::StoppedAtEnd
  821. : (_stage == Stage::Uninitialized)
  822. ? State::Stopped
  823. : paused()
  824. ? State::Paused
  825. : State::Playing;
  826. result.position = std::max(
  827. _information.audio.state.position,
  828. _information.video.state.position);
  829. result.length = computeTotalDuration();
  830. if (result.position == kTimeUnknown) {
  831. result.position = _options.position;
  832. } else if (_options.loop && result.length > 0) {
  833. result.position %= result.length;
  834. }
  835. result.receivedTill = (_remoteLoader
  836. && !_fullInCacheSinceStart.value_or(false))
  837. ? getCurrentReceivedTill(result.length)
  838. : 0;
  839. result.frequency = kMsFrequency;
  840. result.fileHeaderSize = _information.headerSize;
  841. if (result.length == kTimeUnknown) {
  842. const auto document = _options.audioId.audio();
  843. const auto duration = document ? document->duration() : 0;
  844. if (duration > 0) {
  845. result.length = duration;
  846. } else {
  847. result.length = std::max(
  848. crl::time(result.position),
  849. crl::time(0));
  850. }
  851. }
  852. return result;
  853. }
  854. crl::time Player::getCurrentReceivedTill(crl::time duration) const {
  855. const auto forTrack = [&](const TrackState &state) {
  856. return (state.duration > 0 && state.receivedTill == state.duration)
  857. ? std::max(state.receivedTill, duration)
  858. : state.receivedTill;
  859. };
  860. const auto previous = std::max(_previousReceivedTill, crl::time(0));
  861. const auto result = std::min(
  862. std::max(forTrack(_information.audio.state), previous),
  863. std::max(forTrack(_information.video.state), previous));
  864. return (result >= 0 && duration > 1 && _options.loop)
  865. ? (result % duration)
  866. : result;
  867. }
  868. void Player::lock() {
  869. ++_locks;
  870. }
  871. void Player::unlock() {
  872. Expects(_locks > 0);
  873. --_locks;
  874. if (!_locks) {
  875. stopAudio();
  876. if (active()) {
  877. setSpeed(1.);
  878. }
  879. setWaitForMarkAsShown(true);
  880. }
  881. }
  882. bool Player::locked() const {
  883. return (_locks > 0);
  884. }
  885. rpl::lifetime &Player::lifetime() {
  886. return _lifetime;
  887. }
  888. Player::~Player() {
  889. // The order of field destruction is important.
  890. //
  891. // We are forced to maintain the correct order in the stop() method,
  892. // because it can be called even before the player destruction.
  893. //
  894. // So instead of maintaining it in the class definition as well we
  895. // simply call stop() here, after that the destruction is trivial.
  896. stop();
  897. }
  898. } // namespace Streaming
  899. } // namespace Media