PlaybackManager.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  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. on_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 { error };
  76. m_event_handler.dispatch_event(event);
  77. }
  78. void PlaybackManager::on_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::timer_callback()
  93. {
  94. TRY_OR_FATAL_ERROR(m_playback_handler->on_timer_callback());
  95. }
  96. void PlaybackManager::seek_to_timestamp(Time target_timestamp, SeekMode seek_mode)
  97. {
  98. TRY_OR_FATAL_ERROR(m_playback_handler->seek(target_timestamp, seek_mode));
  99. }
  100. Optional<Time> PlaybackManager::seek_demuxer_to_most_recent_keyframe(Time timestamp, Optional<Time> earliest_available_sample)
  101. {
  102. // FIXME: When the demuxer is getting samples off the main thread in the future, this needs to
  103. // mutex so that seeking can't happen while that thread is getting a sample.
  104. auto result = m_demuxer->seek_to_most_recent_keyframe(m_selected_video_track, timestamp, move(earliest_available_sample));
  105. if (result.is_error())
  106. on_decoder_error(result.release_error());
  107. return result.release_value();
  108. }
  109. void PlaybackManager::restart_playback()
  110. {
  111. seek_to_timestamp(Time::zero());
  112. }
  113. void PlaybackManager::dispatch_decoder_error(DecoderError error)
  114. {
  115. m_main_loop.post_event(m_event_handler, make<DecoderErrorEvent>(error));
  116. }
  117. void PlaybackManager::dispatch_new_frame(RefPtr<Gfx::Bitmap> frame)
  118. {
  119. m_main_loop.post_event(m_event_handler, make<VideoFramePresentEvent>(frame));
  120. }
  121. void PlaybackManager::start_timer(int milliseconds)
  122. {
  123. m_present_timer->start(milliseconds);
  124. }
  125. bool PlaybackManager::decode_and_queue_one_sample()
  126. {
  127. if (m_frame_queue->size() >= FRAME_BUFFER_COUNT) {
  128. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Frame queue is full, stopping");
  129. return false;
  130. }
  131. #if PLAYBACK_MANAGER_DEBUG
  132. auto start_time = Time::now_monotonic();
  133. #endif
  134. #define TRY_OR_ENQUEUE_ERROR(expression) \
  135. ({ \
  136. auto _temporary_result = ((expression)); \
  137. if (_temporary_result.is_error()) { \
  138. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Enqueued decoder error: {}", _temporary_result.error().string_literal()); \
  139. m_frame_queue->enqueue(FrameQueueItem::error_marker(_temporary_result.release_error())); \
  140. return false; \
  141. } \
  142. static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_result.release_value())>, \
  143. "Do not return a reference from a fallible expression"); \
  144. _temporary_result.release_value(); \
  145. })
  146. auto frame_sample = TRY_OR_ENQUEUE_ERROR(m_demuxer->get_next_video_sample_for_track(m_selected_video_track));
  147. OwnPtr<VideoFrame> decoded_frame = nullptr;
  148. while (!decoded_frame) {
  149. TRY_OR_ENQUEUE_ERROR(m_decoder->receive_sample(frame_sample->data()));
  150. while (true) {
  151. auto frame_result = m_decoder->get_decoded_frame();
  152. if (frame_result.is_error()) {
  153. if (frame_result.error().category() == DecoderErrorCategory::NeedsMoreInput)
  154. break;
  155. dispatch_decoder_error(frame_result.release_error());
  156. return false;
  157. }
  158. decoded_frame = frame_result.release_value();
  159. VERIFY(decoded_frame);
  160. }
  161. }
  162. auto& cicp = decoded_frame->cicp();
  163. cicp.adopt_specified_values(frame_sample->container_cicp());
  164. cicp.default_code_points_if_unspecified({ ColorPrimaries::BT709, TransferCharacteristics::BT709, MatrixCoefficients::BT709, ColorRange::Studio });
  165. // BT.601, BT.709 and BT.2020 have a similar transfer function to sRGB, so other applications
  166. // (Chromium, VLC) forgo transfer characteristics conversion. We will emulate that behavior by
  167. // handling those as sRGB instead, which causes no transfer function change in the output,
  168. // unless display color management is later implemented.
  169. switch (cicp.transfer_characteristics()) {
  170. case TransferCharacteristics::BT601:
  171. case TransferCharacteristics::BT709:
  172. case TransferCharacteristics::BT2020BitDepth10:
  173. case TransferCharacteristics::BT2020BitDepth12:
  174. cicp.set_transfer_characteristics(TransferCharacteristics::SRGB);
  175. break;
  176. default:
  177. break;
  178. }
  179. auto bitmap = TRY_OR_ENQUEUE_ERROR(decoded_frame->to_bitmap());
  180. m_frame_queue->enqueue(FrameQueueItem::frame(bitmap, frame_sample->timestamp()));
  181. #if PLAYBACK_MANAGER_DEBUG
  182. auto end_time = Time::now_monotonic();
  183. 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());
  184. #endif
  185. return true;
  186. }
  187. void PlaybackManager::on_decode_timer()
  188. {
  189. if (!decode_and_queue_one_sample()) {
  190. // Note: When threading is implemented, this must be dispatched via an event loop.
  191. TRY_OR_FATAL_ERROR(m_playback_handler->on_buffer_filled());
  192. return;
  193. }
  194. // Continually decode until buffering is complete
  195. m_decode_timer->start(0);
  196. }
  197. Time PlaybackManager::PlaybackStateHandler::current_time() const
  198. {
  199. return m_manager.m_last_present_in_media_time;
  200. }
  201. ErrorOr<void> PlaybackManager::PlaybackStateHandler::seek(Time target_timestamp, SeekMode seek_mode)
  202. {
  203. return replace_handler_and_delete_this<SeekingStateHandler>(is_playing(), target_timestamp, seek_mode);
  204. }
  205. ErrorOr<void> PlaybackManager::PlaybackStateHandler::stop()
  206. {
  207. return replace_handler_and_delete_this<StoppedStateHandler>();
  208. }
  209. template<class T, class... Args>
  210. ErrorOr<void> PlaybackManager::PlaybackStateHandler::replace_handler_and_delete_this(Args... args)
  211. {
  212. auto temp_handler = TRY(adopt_nonnull_own_or_enomem<PlaybackStateHandler>(new (nothrow) T(m_manager, args...)));
  213. m_manager.m_playback_handler.swap(temp_handler);
  214. #if PLAYBACK_MANAGER_DEBUG
  215. m_has_exited = true;
  216. dbgln("Changing state from {} to {}", temp_handler->name(), m_manager.m_playback_handler->name());
  217. #endif
  218. TRY(m_manager.m_playback_handler->on_enter());
  219. return {};
  220. }
  221. PlaybackManager& PlaybackManager::PlaybackStateHandler::manager() const
  222. {
  223. #if PLAYBACK_MANAGER_DEBUG
  224. VERIFY(!m_has_exited);
  225. #endif
  226. return m_manager;
  227. }
  228. class PlaybackManager::PlayingStateHandler : public PlaybackManager::PlaybackStateHandler {
  229. public:
  230. PlayingStateHandler(PlaybackManager& manager)
  231. : PlaybackStateHandler(manager)
  232. {
  233. }
  234. ~PlayingStateHandler() override = default;
  235. private:
  236. ErrorOr<void> on_enter() override
  237. {
  238. m_last_present_in_real_time = Time::now_monotonic();
  239. return on_timer_callback();
  240. }
  241. StringView name() override { return "Playing"sv; }
  242. bool is_playing() override { return true; };
  243. ErrorOr<void> pause() override
  244. {
  245. manager().m_last_present_in_media_time = current_time();
  246. return replace_handler_and_delete_this<PausedStateHandler>();
  247. }
  248. ErrorOr<void> buffer() override
  249. {
  250. manager().m_last_present_in_media_time = current_time();
  251. return replace_handler_and_delete_this<BufferingStateHandler>(true);
  252. }
  253. Time current_time() const override
  254. {
  255. return manager().m_last_present_in_media_time + (Time::now_monotonic() - m_last_present_in_real_time);
  256. }
  257. ErrorOr<void> on_timer_callback() override
  258. {
  259. Optional<FrameQueueItem> future_frame_item;
  260. bool should_present_frame = false;
  261. // Skip frames until we find a frame past the current playback time, and keep the one that precedes it to display.
  262. while (!manager().m_frame_queue->is_empty()) {
  263. future_frame_item.emplace(manager().m_frame_queue->dequeue());
  264. manager().m_decode_timer->start(0);
  265. if (future_frame_item->is_error() || future_frame_item->timestamp() >= current_time()) {
  266. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Should present frame, future {} is error or after {}ms", future_frame_item->debug_string(), current_time().to_milliseconds());
  267. should_present_frame = true;
  268. break;
  269. }
  270. if (manager().m_next_frame.has_value()) {
  271. 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());
  272. manager().m_skipped_frames++;
  273. }
  274. manager().m_next_frame.emplace(future_frame_item.release_value());
  275. }
  276. // If we don't have both of these items, we can't present, since we need to set a timer for
  277. // the next frame. Check if we need to buffer based on the current state.
  278. if (!manager().m_next_frame.has_value() || !future_frame_item.has_value()) {
  279. #if PLAYBACK_MANAGER_DEBUG
  280. StringBuilder debug_string_builder;
  281. debug_string_builder.append("We don't have "sv);
  282. if (!manager().m_next_frame.has_value()) {
  283. debug_string_builder.append("a frame to present"sv);
  284. if (!future_frame_item.has_value())
  285. debug_string_builder.append(" or a future frame"sv);
  286. } else {
  287. debug_string_builder.append("a future frame"sv);
  288. }
  289. debug_string_builder.append(", checking for error and buffering"sv);
  290. dbgln_if(PLAYBACK_MANAGER_DEBUG, debug_string_builder.to_deprecated_string());
  291. #endif
  292. if (future_frame_item.has_value()) {
  293. if (future_frame_item->is_error()) {
  294. manager().on_decoder_error(future_frame_item.release_value().release_error());
  295. return {};
  296. }
  297. manager().m_next_frame.emplace(future_frame_item.release_value());
  298. }
  299. TRY(buffer());
  300. return {};
  301. }
  302. // If we have a frame, send it for presentation.
  303. if (should_present_frame) {
  304. auto now = Time::now_monotonic();
  305. manager().m_last_present_in_media_time += now - m_last_present_in_real_time;
  306. m_last_present_in_real_time = now;
  307. manager().dispatch_new_frame(manager().m_next_frame.value().bitmap());
  308. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Sent frame for presentation");
  309. }
  310. // Now that we've presented the current frame, we can throw whatever error is next in queue.
  311. // This way, we always display a frame before the stream ends, and should also show any frames
  312. // we already had when a real error occurs.
  313. if (future_frame_item->is_error()) {
  314. manager().on_decoder_error(future_frame_item.release_value().release_error());
  315. return {};
  316. }
  317. // The future frame item becomes the next one to present.
  318. manager().m_next_frame.emplace(future_frame_item.release_value());
  319. auto frame_time_ms = (manager().m_next_frame->timestamp() - current_time()).to_milliseconds();
  320. VERIFY(frame_time_ms <= NumericLimits<int>::max());
  321. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Time until next frame is {}ms", frame_time_ms);
  322. manager().start_timer(max(static_cast<int>(frame_time_ms), 0));
  323. return {};
  324. }
  325. Time m_last_present_in_real_time = Time::zero();
  326. };
  327. class PlaybackManager::PausedStateHandler : public PlaybackManager::PlaybackStateHandler {
  328. public:
  329. PausedStateHandler(PlaybackManager& manager)
  330. : PlaybackStateHandler(manager)
  331. {
  332. }
  333. ~PausedStateHandler() override = default;
  334. private:
  335. StringView name() override { return "Paused"sv; }
  336. ErrorOr<void> play() override
  337. {
  338. return replace_handler_and_delete_this<PlayingStateHandler>();
  339. }
  340. bool is_playing() override { return false; };
  341. };
  342. class PlaybackManager::BufferingStateHandler : public PlaybackManager::PlaybackStateHandler {
  343. public:
  344. BufferingStateHandler(PlaybackManager& manager, bool playing)
  345. : PlaybackStateHandler(manager)
  346. , m_playing(playing)
  347. {
  348. }
  349. ~BufferingStateHandler() override = default;
  350. private:
  351. ErrorOr<void> on_enter() override
  352. {
  353. manager().m_decode_timer->start(0);
  354. return {};
  355. }
  356. StringView name() override { return "Buffering"sv; }
  357. ErrorOr<void> play() override
  358. {
  359. m_playing = true;
  360. return {};
  361. }
  362. bool is_playing() override { return m_playing; };
  363. ErrorOr<void> pause() override
  364. {
  365. m_playing = false;
  366. return {};
  367. }
  368. ErrorOr<void> on_buffer_filled() override
  369. {
  370. if (m_playing)
  371. return replace_handler_and_delete_this<PlayingStateHandler>();
  372. return replace_handler_and_delete_this<PausedStateHandler>();
  373. }
  374. bool m_playing { false };
  375. };
  376. class PlaybackManager::SeekingStateHandler : public PlaybackManager::PlaybackStateHandler {
  377. public:
  378. SeekingStateHandler(PlaybackManager& manager, bool playing, Time target_timestamp, SeekMode seek_mode)
  379. : PlaybackStateHandler(manager)
  380. , m_playing(playing)
  381. , m_target_timestamp(target_timestamp)
  382. , m_seek_mode(seek_mode)
  383. {
  384. }
  385. ~SeekingStateHandler() override = default;
  386. private:
  387. ErrorOr<void> exit_seek()
  388. {
  389. if (m_playing)
  390. return replace_handler_and_delete_this<PlayingStateHandler>();
  391. return replace_handler_and_delete_this<PausedStateHandler>();
  392. }
  393. ErrorOr<void> on_enter() override
  394. {
  395. auto earliest_available_sample = manager().m_last_present_in_media_time;
  396. if (manager().m_next_frame.has_value() && manager().m_next_frame->is_frame()) {
  397. earliest_available_sample = min(earliest_available_sample, manager().m_next_frame->timestamp());
  398. }
  399. auto keyframe_timestamp = manager().seek_demuxer_to_most_recent_keyframe(m_target_timestamp, earliest_available_sample);
  400. #if PLAYBACK_MANAGER_DEBUG
  401. auto seek_mode_name = m_seek_mode == SeekMode::Accurate ? "Accurate"sv : "Fast"sv;
  402. if (keyframe_timestamp.has_value()) {
  403. dbgln("{} seeking to timestamp target {}ms, selected keyframe at {}ms", seek_mode_name, m_target_timestamp.to_milliseconds(), keyframe_timestamp->to_milliseconds());
  404. } else {
  405. dbgln("{} seeking to timestamp target {}ms, demuxer kept its iterator position", seek_mode_name, m_target_timestamp.to_milliseconds());
  406. }
  407. #endif
  408. if (m_seek_mode == SeekMode::Fast) {
  409. m_target_timestamp = keyframe_timestamp.value_or(earliest_available_sample);
  410. }
  411. if (keyframe_timestamp.has_value()) {
  412. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Timestamp is earlier than current media time, clearing queue");
  413. manager().m_frame_queue->clear();
  414. manager().m_next_frame.clear();
  415. } 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) {
  416. manager().m_last_present_in_media_time = m_target_timestamp;
  417. return exit_seek();
  418. }
  419. return skip_samples_until_timestamp();
  420. }
  421. ErrorOr<void> skip_samples_until_timestamp()
  422. {
  423. while (!manager().m_frame_queue->is_empty()) {
  424. auto item = manager().m_frame_queue->dequeue();
  425. manager().m_decode_timer->start(0);
  426. if (item.is_error()) {
  427. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Encountered error while seeking: {}", item.error().description());
  428. manager().on_decoder_error(item.release_error());
  429. return {};
  430. }
  431. if (item.is_frame()) {
  432. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Dequeuing frame at {}ms and comparing to seek target {}ms", item.timestamp().to_milliseconds(), m_target_timestamp.to_milliseconds());
  433. if (item.timestamp() > m_target_timestamp) {
  434. // Fast seeking will result in an equal timestamp, so we can exit as soon as we see the next frame.
  435. if (manager().m_next_frame.has_value()) {
  436. manager().dispatch_new_frame(manager().m_next_frame.release_value().bitmap());
  437. manager().m_last_present_in_media_time = m_target_timestamp;
  438. }
  439. manager().m_next_frame.emplace(item);
  440. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Exiting seek to {} state at {}ms", m_playing ? "Playing" : "Paused", manager().m_last_present_in_media_time.to_milliseconds());
  441. return exit_seek();
  442. }
  443. manager().m_next_frame.emplace(item);
  444. continue;
  445. }
  446. VERIFY_NOT_REACHED();
  447. }
  448. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Frame queue is empty while seeking, waiting for buffer fill.");
  449. manager().m_decode_timer->start(0);
  450. return {};
  451. }
  452. StringView name() override { return "Seeking"sv; }
  453. ErrorOr<void> play() override
  454. {
  455. m_playing = true;
  456. return {};
  457. }
  458. bool is_playing() override { return m_playing; };
  459. ErrorOr<void> pause() override
  460. {
  461. m_playing = false;
  462. return {};
  463. }
  464. ErrorOr<void> seek(Time target_timestamp, SeekMode seek_mode) override
  465. {
  466. m_target_timestamp = target_timestamp;
  467. m_seek_mode = seek_mode;
  468. return on_enter();
  469. }
  470. Time current_time() const override
  471. {
  472. return m_target_timestamp;
  473. }
  474. // We won't need this override when threaded, the queue can pause us in on_enter().
  475. ErrorOr<void> on_buffer_filled() override
  476. {
  477. dbgln_if(PLAYBACK_MANAGER_DEBUG, "Buffer filled while seeking, dequeuing until timestamp.");
  478. return skip_samples_until_timestamp();
  479. }
  480. bool m_playing { false };
  481. Time m_target_timestamp { Time::zero() };
  482. SeekMode m_seek_mode { SeekMode::Accurate };
  483. };
  484. class PlaybackManager::StoppedStateHandler : public PlaybackManager::PlaybackStateHandler {
  485. public:
  486. StoppedStateHandler(PlaybackManager& manager)
  487. : PlaybackStateHandler(manager)
  488. {
  489. }
  490. ~StoppedStateHandler() override = default;
  491. private:
  492. ErrorOr<void> on_enter() override
  493. {
  494. return {};
  495. }
  496. StringView name() override { return "Stopped"sv; }
  497. ErrorOr<void> play() override
  498. {
  499. manager().m_next_frame.clear();
  500. manager().m_frame_queue->clear();
  501. auto start_timestamp = manager().seek_demuxer_to_most_recent_keyframe(Time::zero());
  502. VERIFY(start_timestamp.has_value());
  503. manager().m_last_present_in_media_time = start_timestamp.release_value();
  504. return replace_handler_and_delete_this<PlayingStateHandler>();
  505. }
  506. bool is_playing() override { return false; };
  507. };
  508. }