PlaybackManager.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. /*
  2. * Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Format.h>
  7. #include <LibCore/Timer.h>
  8. #include <LibVideo/Containers/Matroska/MatroskaDemuxer.h>
  9. #include <LibVideo/VP9/Decoder.h>
  10. #include "PlaybackManager.h"
  11. namespace Video {
  12. #define TRY_OR_FATAL_ERROR(expression) \
  13. ({ \
  14. auto&& _fatal_expression = (expression); \
  15. if (_fatal_expression.is_error()) { \
  16. dispatch_fatal_error(_fatal_expression.release_error()); \
  17. return; \
  18. } \
  19. static_assert(!::AK::Detail::IsLvalueReference<decltype(_fatal_expression.release_value())>, \
  20. "Do not return a reference from a fallible expression"); \
  21. _fatal_expression.release_value(); \
  22. })
  23. class DefaultPlaybackTimer final : public PlaybackTimer {
  24. public:
  25. static ErrorOr<NonnullOwnPtr<DefaultPlaybackTimer>> create(int interval_ms, Function<void()>&& timeout_handler)
  26. {
  27. auto timer = TRY(Core::Timer::create_single_shot(interval_ms, move(timeout_handler)));
  28. return adopt_nonnull_own_or_enomem(new (nothrow) DefaultPlaybackTimer(move(timer)));
  29. }
  30. virtual void start() override { m_timer->start(); }
  31. virtual void start(int interval_ms) override { m_timer->start(interval_ms); }
  32. private:
  33. explicit DefaultPlaybackTimer(NonnullRefPtr<Core::Timer> timer)
  34. : m_timer(move(timer))
  35. {
  36. }
  37. NonnullRefPtr<Core::Timer> m_timer;
  38. };
  39. DecoderErrorOr<NonnullOwnPtr<PlaybackManager>> PlaybackManager::from_file(StringView filename, PlaybackTimerCreator playback_timer_creator)
  40. {
  41. auto demuxer = TRY(Matroska::MatroskaDemuxer::from_file(filename));
  42. return create_with_demuxer(move(demuxer), move(playback_timer_creator));
  43. }
  44. DecoderErrorOr<NonnullOwnPtr<PlaybackManager>> PlaybackManager::from_data(ReadonlyBytes data, PlaybackTimerCreator playback_timer_creator)
  45. {
  46. auto demuxer = TRY(Matroska::MatroskaDemuxer::from_data(data));
  47. return create_with_demuxer(move(demuxer), move(playback_timer_creator));
  48. }
  49. DecoderErrorOr<NonnullOwnPtr<PlaybackManager>> PlaybackManager::create_with_demuxer(NonnullOwnPtr<Demuxer> demuxer, PlaybackTimerCreator playback_timer_creator)
  50. {
  51. auto video_tracks = TRY(demuxer->get_tracks_for_type(TrackType::Video));
  52. if (video_tracks.is_empty())
  53. return DecoderError::with_description(DecoderErrorCategory::Invalid, "No video track is present"sv);
  54. auto track = video_tracks[0];
  55. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Selecting video track number {}", track.identifier());
  56. return make<PlaybackManager>(demuxer, track, make<VP9::Decoder>(), move(playback_timer_creator));
  57. }
  58. PlaybackManager::PlaybackManager(NonnullOwnPtr<Demuxer>& demuxer, Track video_track, NonnullOwnPtr<VideoDecoder>&& decoder, PlaybackTimerCreator playback_timer_creator)
  59. : m_demuxer(move(demuxer))
  60. , m_selected_video_track(video_track)
  61. , m_decoder(move(decoder))
  62. , m_frame_queue(make<VideoFrameQueue>())
  63. , m_playback_handler(make<SeekingStateHandler>(*this, false, Time::zero(), SeekMode::Fast))
  64. {
  65. if (playback_timer_creator) {
  66. m_present_timer = playback_timer_creator(0, [&] { timer_callback(); }).release_value_but_fixme_should_propagate_errors();
  67. m_decode_timer = playback_timer_creator(0, [&] { on_decode_timer(); }).release_value_but_fixme_should_propagate_errors();
  68. } else {
  69. m_present_timer = DefaultPlaybackTimer::create(0, [&] { timer_callback(); }).release_value_but_fixme_should_propagate_errors();
  70. m_decode_timer = DefaultPlaybackTimer::create(0, [&] { on_decode_timer(); }).release_value_but_fixme_should_propagate_errors();
  71. }
  72. TRY_OR_FATAL_ERROR(m_playback_handler->on_enter());
  73. }
  74. void PlaybackManager::resume_playback()
  75. {
  76. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Resuming playback.");
  77. TRY_OR_FATAL_ERROR(m_playback_handler->play());
  78. }
  79. void PlaybackManager::pause_playback()
  80. {
  81. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Pausing playback.");
  82. if (!m_playback_handler->is_playing())
  83. warnln("Cannot pause.");
  84. TRY_OR_FATAL_ERROR(m_playback_handler->pause());
  85. }
  86. Time PlaybackManager::current_playback_time()
  87. {
  88. return m_playback_handler->current_time();
  89. }
  90. Time PlaybackManager::duration()
  91. {
  92. auto duration_result = m_demuxer->duration();
  93. if (duration_result.is_error())
  94. dispatch_decoder_error(duration_result.release_error());
  95. return duration_result.release_value();
  96. }
  97. void PlaybackManager::dispatch_fatal_error(Error error)
  98. {
  99. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Encountered fatal error: {}", error.string_literal());
  100. // FIXME: For threading, this will have to use a pre-allocated event to send to the main loop
  101. // to be able to gracefully handle OOM.
  102. if (on_fatal_playback_error)
  103. on_fatal_playback_error(move(error));
  104. }
  105. void PlaybackManager::dispatch_decoder_error(DecoderError error)
  106. {
  107. switch (error.category()) {
  108. case DecoderErrorCategory::EndOfStream:
  109. dbgln_if(PLAYBACK_MANAGER_DEBUG, "{}", error.string_literal());
  110. TRY_OR_FATAL_ERROR(m_playback_handler->stop());
  111. if (on_end_of_stream)
  112. on_end_of_stream();
  113. break;
  114. default:
  115. dbgln("Playback error encountered: {}", error.string_literal());
  116. TRY_OR_FATAL_ERROR(m_playback_handler->stop());
  117. if (on_decoder_error)
  118. on_decoder_error(move(error));
  119. break;
  120. }
  121. }
  122. void PlaybackManager::dispatch_new_frame(RefPtr<Gfx::Bitmap> frame)
  123. {
  124. if (on_video_frame)
  125. on_video_frame(move(frame));
  126. }
  127. bool PlaybackManager::dispatch_frame_queue_item(FrameQueueItem&& item)
  128. {
  129. if (item.is_error()) {
  130. dispatch_decoder_error(item.release_error());
  131. return true;
  132. }
  133. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Sent frame for presentation with timestamp {}ms", item.timestamp().to_milliseconds());
  134. dispatch_new_frame(item.bitmap());
  135. return false;
  136. }
  137. void PlaybackManager::dispatch_state_change()
  138. {
  139. if (on_playback_state_change)
  140. on_playback_state_change();
  141. }
  142. void PlaybackManager::timer_callback()
  143. {
  144. TRY_OR_FATAL_ERROR(m_playback_handler->on_timer_callback());
  145. }
  146. void PlaybackManager::seek_to_timestamp(Time target_timestamp, SeekMode seek_mode)
  147. {
  148. TRY_OR_FATAL_ERROR(m_playback_handler->seek(target_timestamp, seek_mode));
  149. }
  150. Optional<Time> PlaybackManager::seek_demuxer_to_most_recent_keyframe(Time timestamp, Optional<Time> earliest_available_sample)
  151. {
  152. // FIXME: When the demuxer is getting samples off the main thread in the future, this needs to
  153. // mutex so that seeking can't happen while that thread is getting a sample.
  154. auto result = m_demuxer->seek_to_most_recent_keyframe(m_selected_video_track, timestamp, move(earliest_available_sample));
  155. if (result.is_error())
  156. dispatch_decoder_error(result.release_error());
  157. return result.release_value();
  158. }
  159. void PlaybackManager::restart_playback()
  160. {
  161. seek_to_timestamp(Time::zero());
  162. }
  163. void PlaybackManager::start_timer(int milliseconds)
  164. {
  165. m_present_timer->start(milliseconds);
  166. }
  167. bool PlaybackManager::decode_and_queue_one_sample()
  168. {
  169. if (m_frame_queue->size() >= FRAME_BUFFER_COUNT) {
  170. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Frame queue is full, stopping");
  171. return false;
  172. }
  173. #if PLAYBACK_MANAGER_DEBUG
  174. auto start_time = Time::now_monotonic();
  175. #endif
  176. auto enqueue_error = [&](DecoderError&& error, Time timestamp) {
  177. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Enqueued decoder error: {}", error.string_literal());
  178. m_frame_queue->enqueue(FrameQueueItem::error_marker(move(error), timestamp));
  179. };
  180. #define TRY_OR_ENQUEUE_ERROR(expression, timestamp) \
  181. ({ \
  182. auto&& _temporary_result = (expression); \
  183. if (_temporary_result.is_error()) { \
  184. enqueue_error(_temporary_result.release_error(), (timestamp)); \
  185. return false; \
  186. } \
  187. static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_result.release_value())>, \
  188. "Do not return a reference from a fallible expression"); \
  189. _temporary_result.release_value(); \
  190. })
  191. auto frame_sample = TRY_OR_ENQUEUE_ERROR(m_demuxer->get_next_video_sample_for_track(m_selected_video_track), Time::min());
  192. OwnPtr<VideoFrame> decoded_frame = nullptr;
  193. while (!decoded_frame) {
  194. TRY_OR_ENQUEUE_ERROR(m_decoder->receive_sample(frame_sample->data()), frame_sample->timestamp());
  195. while (true) {
  196. auto frame_result = m_decoder->get_decoded_frame();
  197. if (frame_result.is_error()) {
  198. if (frame_result.error().category() == DecoderErrorCategory::NeedsMoreInput)
  199. break;
  200. enqueue_error(frame_result.release_error(), frame_sample->timestamp());
  201. return false;
  202. }
  203. decoded_frame = frame_result.release_value();
  204. VERIFY(decoded_frame);
  205. }
  206. }
  207. auto& cicp = decoded_frame->cicp();
  208. cicp.adopt_specified_values(frame_sample->container_cicp());
  209. cicp.default_code_points_if_unspecified({ ColorPrimaries::BT709, TransferCharacteristics::BT709, MatrixCoefficients::BT709, VideoFullRangeFlag::Studio });
  210. // BT.601, BT.709 and BT.2020 have a similar transfer function to sRGB, so other applications
  211. // (Chromium, VLC) forgo transfer characteristics conversion. We will emulate that behavior by
  212. // handling those as sRGB instead, which causes no transfer function change in the output,
  213. // unless display color management is later implemented.
  214. switch (cicp.transfer_characteristics()) {
  215. case TransferCharacteristics::BT601:
  216. case TransferCharacteristics::BT709:
  217. case TransferCharacteristics::BT2020BitDepth10:
  218. case TransferCharacteristics::BT2020BitDepth12:
  219. cicp.set_transfer_characteristics(TransferCharacteristics::SRGB);
  220. break;
  221. default:
  222. break;
  223. }
  224. auto bitmap = TRY_OR_ENQUEUE_ERROR(decoded_frame->to_bitmap(), frame_sample->timestamp());
  225. m_frame_queue->enqueue(FrameQueueItem::frame(bitmap, frame_sample->timestamp()));
  226. #if PLAYBACK_MANAGER_DEBUG
  227. auto end_time = Time::now_monotonic();
  228. dbgln("Decoding sample at {}ms took {}ms, queue contains {} items", frame_sample->timestamp().to_milliseconds(), (end_time - start_time).to_milliseconds(), m_frame_queue->size());
  229. #endif
  230. return true;
  231. }
  232. void PlaybackManager::on_decode_timer()
  233. {
  234. if (!decode_and_queue_one_sample()) {
  235. // Note: When threading is implemented, this must be dispatched via an event loop.
  236. TRY_OR_FATAL_ERROR(m_playback_handler->on_buffer_filled());
  237. return;
  238. }
  239. // Continually decode until buffering is complete
  240. m_decode_timer->start(0);
  241. }
  242. Time PlaybackManager::PlaybackStateHandler::current_time() const
  243. {
  244. return m_manager.m_last_present_in_media_time;
  245. }
  246. ErrorOr<void> PlaybackManager::PlaybackStateHandler::seek(Time target_timestamp, SeekMode seek_mode)
  247. {
  248. return replace_handler_and_delete_this<SeekingStateHandler>(is_playing(), target_timestamp, seek_mode);
  249. }
  250. ErrorOr<void> PlaybackManager::PlaybackStateHandler::stop()
  251. {
  252. return replace_handler_and_delete_this<StoppedStateHandler>();
  253. }
  254. template<class T, class... Args>
  255. ErrorOr<void> PlaybackManager::PlaybackStateHandler::replace_handler_and_delete_this(Args... args)
  256. {
  257. auto temp_handler = TRY(adopt_nonnull_own_or_enomem<PlaybackStateHandler>(new (nothrow) T(m_manager, args...)));
  258. m_manager.m_playback_handler.swap(temp_handler);
  259. #if PLAYBACK_MANAGER_DEBUG
  260. m_has_exited = true;
  261. dbgln("Changing state from {} to {}", temp_handler->name(), m_manager.m_playback_handler->name());
  262. #endif
  263. TRY(m_manager.m_playback_handler->on_enter());
  264. m_manager.dispatch_state_change();
  265. return {};
  266. }
  267. PlaybackManager& PlaybackManager::PlaybackStateHandler::manager() const
  268. {
  269. #if PLAYBACK_MANAGER_DEBUG
  270. VERIFY(!m_has_exited);
  271. #endif
  272. return m_manager;
  273. }
  274. class PlaybackManager::ResumingStateHandler : public PlaybackManager::PlaybackStateHandler {
  275. public:
  276. ResumingStateHandler(PlaybackManager& manager, bool playing)
  277. : PlaybackStateHandler(manager)
  278. , m_playing(playing)
  279. {
  280. }
  281. ~ResumingStateHandler() override = default;
  282. protected:
  283. ErrorOr<void> assume_next_state()
  284. {
  285. if (!m_playing)
  286. return replace_handler_and_delete_this<PausedStateHandler>();
  287. return replace_handler_and_delete_this<PlayingStateHandler>();
  288. }
  289. ErrorOr<void> play() override
  290. {
  291. m_playing = true;
  292. manager().dispatch_state_change();
  293. return {};
  294. }
  295. bool is_playing() const override { return m_playing; }
  296. ErrorOr<void> pause() override
  297. {
  298. m_playing = false;
  299. manager().dispatch_state_change();
  300. return {};
  301. }
  302. bool m_playing { false };
  303. };
  304. class PlaybackManager::PlayingStateHandler : public PlaybackManager::PlaybackStateHandler {
  305. public:
  306. PlayingStateHandler(PlaybackManager& manager)
  307. : PlaybackStateHandler(manager)
  308. {
  309. }
  310. ~PlayingStateHandler() override = default;
  311. private:
  312. ErrorOr<void> on_enter() override
  313. {
  314. m_last_present_in_real_time = Time::now_monotonic();
  315. return on_timer_callback();
  316. }
  317. StringView name() override { return "Playing"sv; }
  318. bool is_playing() const override { return true; };
  319. PlaybackState get_state() const override { return PlaybackState::Playing; }
  320. ErrorOr<void> pause() override
  321. {
  322. manager().m_last_present_in_media_time = current_time();
  323. return replace_handler_and_delete_this<PausedStateHandler>();
  324. }
  325. ErrorOr<void> buffer() override
  326. {
  327. manager().m_last_present_in_media_time = current_time();
  328. return replace_handler_and_delete_this<BufferingStateHandler>(true);
  329. }
  330. Time current_time() const override
  331. {
  332. return manager().m_last_present_in_media_time + (Time::now_monotonic() - m_last_present_in_real_time);
  333. }
  334. ErrorOr<void> on_timer_callback() override
  335. {
  336. auto set_presentation_timer = [&]() {
  337. auto frame_time_ms = (manager().m_next_frame->timestamp() - current_time()).to_milliseconds();
  338. VERIFY(frame_time_ms <= NumericLimits<int>::max());
  339. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Time until next frame is {}ms", frame_time_ms);
  340. manager().start_timer(max(static_cast<int>(frame_time_ms), 0));
  341. };
  342. if (manager().m_next_frame.has_value() && current_time() < manager().m_next_frame->timestamp()) {
  343. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Current time {}ms is too early to present the next frame at {}ms, delaying", current_time().to_milliseconds(), manager().m_next_frame->timestamp().to_milliseconds());
  344. set_presentation_timer();
  345. return {};
  346. }
  347. Optional<FrameQueueItem> future_frame_item;
  348. bool should_present_frame = false;
  349. // Skip frames until we find a frame past the current playback time, and keep the one that precedes it to display.
  350. while (!manager().m_frame_queue->is_empty()) {
  351. future_frame_item.emplace(manager().m_frame_queue->dequeue());
  352. manager().m_decode_timer->start(0);
  353. if (future_frame_item->timestamp() >= current_time() || future_frame_item->timestamp() == FrameQueueItem::no_timestamp) {
  354. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Should present frame, future {} is error or after {}ms", future_frame_item->debug_string(), current_time().to_milliseconds());
  355. should_present_frame = true;
  356. break;
  357. }
  358. if (manager().m_next_frame.has_value()) {
  359. dbgln_if(PLAYBACK_MANAGER_DEBUG, "At {}ms: Dropped {} in favor of {}", current_time().to_milliseconds(), manager().m_next_frame->debug_string(), future_frame_item->debug_string());
  360. manager().m_skipped_frames++;
  361. }
  362. manager().m_next_frame.emplace(future_frame_item.release_value());
  363. }
  364. // If we don't have both of these items, we can't present, since we need to set a timer for
  365. // the next frame. Check if we need to buffer based on the current state.
  366. if (!manager().m_next_frame.has_value() || !future_frame_item.has_value()) {
  367. #if PLAYBACK_MANAGER_DEBUG
  368. StringBuilder debug_string_builder;
  369. debug_string_builder.append("We don't have "sv);
  370. if (!manager().m_next_frame.has_value()) {
  371. debug_string_builder.append("a frame to present"sv);
  372. if (!future_frame_item.has_value())
  373. debug_string_builder.append(" or a future frame"sv);
  374. } else {
  375. debug_string_builder.append("a future frame"sv);
  376. }
  377. debug_string_builder.append(", checking for error and buffering"sv);
  378. dbgln_if(PLAYBACK_MANAGER_DEBUG, debug_string_builder.to_deprecated_string());
  379. #endif
  380. if (future_frame_item.has_value()) {
  381. if (future_frame_item->is_error()) {
  382. manager().dispatch_decoder_error(future_frame_item.release_value().release_error());
  383. return {};
  384. }
  385. manager().m_next_frame.emplace(future_frame_item.release_value());
  386. }
  387. TRY(buffer());
  388. return {};
  389. }
  390. // If we have a frame, send it for presentation.
  391. if (should_present_frame) {
  392. auto now = Time::now_monotonic();
  393. manager().m_last_present_in_media_time += now - m_last_present_in_real_time;
  394. m_last_present_in_real_time = now;
  395. if (manager().dispatch_frame_queue_item(manager().m_next_frame.release_value()))
  396. return {};
  397. }
  398. // Now that we've presented the current frame, we can throw whatever error is next in queue.
  399. // This way, we always display a frame before the stream ends, and should also show any frames
  400. // we already had when a real error occurs.
  401. if (future_frame_item->is_error()) {
  402. manager().dispatch_decoder_error(future_frame_item.release_value().release_error());
  403. return {};
  404. }
  405. // The future frame item becomes the next one to present.
  406. manager().m_next_frame.emplace(future_frame_item.release_value());
  407. set_presentation_timer();
  408. return {};
  409. }
  410. Time m_last_present_in_real_time = Time::zero();
  411. };
  412. class PlaybackManager::PausedStateHandler : public PlaybackManager::PlaybackStateHandler {
  413. public:
  414. PausedStateHandler(PlaybackManager& manager)
  415. : PlaybackStateHandler(manager)
  416. {
  417. }
  418. ~PausedStateHandler() override = default;
  419. private:
  420. StringView name() override { return "Paused"sv; }
  421. ErrorOr<void> play() override
  422. {
  423. return replace_handler_and_delete_this<PlayingStateHandler>();
  424. }
  425. bool is_playing() const override { return false; };
  426. PlaybackState get_state() const override { return PlaybackState::Paused; }
  427. };
  428. class PlaybackManager::BufferingStateHandler : public PlaybackManager::ResumingStateHandler {
  429. using PlaybackManager::ResumingStateHandler::ResumingStateHandler;
  430. ErrorOr<void> on_enter() override
  431. {
  432. manager().m_decode_timer->start(0);
  433. return {};
  434. }
  435. StringView name() override { return "Buffering"sv; }
  436. ErrorOr<void> on_buffer_filled() override
  437. {
  438. return assume_next_state();
  439. }
  440. PlaybackState get_state() const override { return PlaybackState::Buffering; }
  441. };
  442. class PlaybackManager::SeekingStateHandler : public PlaybackManager::ResumingStateHandler {
  443. public:
  444. SeekingStateHandler(PlaybackManager& manager, bool playing, Time target_timestamp, SeekMode seek_mode)
  445. : ResumingStateHandler(manager, playing)
  446. , m_target_timestamp(target_timestamp)
  447. , m_seek_mode(seek_mode)
  448. {
  449. }
  450. ~SeekingStateHandler() override = default;
  451. private:
  452. ErrorOr<void> on_enter() override
  453. {
  454. auto earliest_available_sample = manager().m_last_present_in_media_time;
  455. if (manager().m_next_frame.has_value() && manager().m_next_frame->timestamp() != FrameQueueItem::no_timestamp) {
  456. earliest_available_sample = min(earliest_available_sample, manager().m_next_frame->timestamp());
  457. }
  458. auto keyframe_timestamp = manager().seek_demuxer_to_most_recent_keyframe(m_target_timestamp, earliest_available_sample);
  459. #if PLAYBACK_MANAGER_DEBUG
  460. auto seek_mode_name = m_seek_mode == SeekMode::Accurate ? "Accurate"sv : "Fast"sv;
  461. if (keyframe_timestamp.has_value()) {
  462. dbgln("{} seeking to timestamp target {}ms, selected keyframe at {}ms", seek_mode_name, m_target_timestamp.to_milliseconds(), keyframe_timestamp->to_milliseconds());
  463. } else {
  464. dbgln("{} seeking to timestamp target {}ms, demuxer kept its iterator position after {}ms", seek_mode_name, m_target_timestamp.to_milliseconds(), earliest_available_sample.to_milliseconds());
  465. }
  466. #endif
  467. if (m_seek_mode == SeekMode::Fast) {
  468. m_target_timestamp = keyframe_timestamp.value_or(manager().m_last_present_in_media_time);
  469. }
  470. if (keyframe_timestamp.has_value()) {
  471. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Keyframe is nearer to the target than the current frames, clearing queue");
  472. manager().m_frame_queue->clear();
  473. manager().m_next_frame.clear();
  474. manager().m_last_present_in_media_time = keyframe_timestamp.value();
  475. } else if (m_target_timestamp >= manager().m_last_present_in_media_time && manager().m_next_frame.has_value() && manager().m_next_frame.value().timestamp() > m_target_timestamp) {
  476. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Target timestamp is between the last presented frame and the next frame, exiting seek at {}ms", m_target_timestamp.to_milliseconds());
  477. manager().m_last_present_in_media_time = m_target_timestamp;
  478. return assume_next_state();
  479. }
  480. return skip_samples_until_timestamp();
  481. }
  482. ErrorOr<void> skip_samples_until_timestamp()
  483. {
  484. while (!manager().m_frame_queue->is_empty()) {
  485. auto item = manager().m_frame_queue->dequeue();
  486. manager().m_decode_timer->start(0);
  487. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Dequeuing frame at {}ms and comparing to seek target {}ms", item.timestamp().to_milliseconds(), m_target_timestamp.to_milliseconds());
  488. if (manager().m_next_frame.has_value() && (item.timestamp() > m_target_timestamp || item.timestamp() == FrameQueueItem::no_timestamp)) {
  489. // If the frame we're presenting is later than the target timestamp, skip the timestamp forward to it.
  490. if (manager().m_next_frame->timestamp() > m_target_timestamp) {
  491. manager().m_last_present_in_media_time = manager().m_next_frame->timestamp();
  492. } else {
  493. manager().m_last_present_in_media_time = m_target_timestamp;
  494. }
  495. if (manager().dispatch_frame_queue_item(manager().m_next_frame.release_value()))
  496. return {};
  497. manager().m_next_frame.emplace(item);
  498. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Exiting seek to {} state at {}ms", m_playing ? "Playing" : "Paused", manager().m_last_present_in_media_time.to_milliseconds());
  499. return assume_next_state();
  500. }
  501. manager().m_next_frame.emplace(item);
  502. }
  503. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Frame queue is empty while seeking, waiting for buffer fill.");
  504. manager().m_decode_timer->start(0);
  505. return {};
  506. }
  507. StringView name() override { return "Seeking"sv; }
  508. ErrorOr<void> seek(Time target_timestamp, SeekMode seek_mode) override
  509. {
  510. m_target_timestamp = target_timestamp;
  511. m_seek_mode = seek_mode;
  512. return on_enter();
  513. }
  514. Time current_time() const override
  515. {
  516. return m_target_timestamp;
  517. }
  518. // We won't need this override when threaded, the queue can pause us in on_enter().
  519. ErrorOr<void> on_buffer_filled() override
  520. {
  521. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Buffer filled while seeking, dequeuing until timestamp.");
  522. return skip_samples_until_timestamp();
  523. }
  524. PlaybackState get_state() const override { return PlaybackState::Seeking; }
  525. Time m_target_timestamp { Time::zero() };
  526. SeekMode m_seek_mode { SeekMode::Accurate };
  527. };
  528. class PlaybackManager::StoppedStateHandler : public PlaybackManager::PlaybackStateHandler {
  529. public:
  530. StoppedStateHandler(PlaybackManager& manager)
  531. : PlaybackStateHandler(manager)
  532. {
  533. }
  534. ~StoppedStateHandler() override = default;
  535. private:
  536. ErrorOr<void> on_enter() override
  537. {
  538. return {};
  539. }
  540. StringView name() override { return "Stopped"sv; }
  541. ErrorOr<void> play() override
  542. {
  543. manager().m_next_frame.clear();
  544. manager().m_frame_queue->clear();
  545. auto start_timestamp = manager().seek_demuxer_to_most_recent_keyframe(Time::zero());
  546. VERIFY(start_timestamp.has_value());
  547. manager().m_last_present_in_media_time = start_timestamp.release_value();
  548. return replace_handler_and_delete_this<SeekingStateHandler>(true, Time::zero(), SeekMode::Fast);
  549. }
  550. bool is_playing() const override { return false; };
  551. PlaybackState get_state() const override { return PlaybackState::Stopped; }
  552. };
  553. }