PlaybackManager.cpp 25 KB

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