PlaybackManager.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /*
  2. * Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Atomic.h>
  8. #include <AK/Function.h>
  9. #include <AK/NonnullOwnPtr.h>
  10. #include <AK/Queue.h>
  11. #include <AK/Time.h>
  12. #include <LibCore/SharedCircularQueue.h>
  13. #include <LibGfx/Bitmap.h>
  14. #include <LibThreading/ConditionVariable.h>
  15. #include <LibThreading/Mutex.h>
  16. #include <LibThreading/Thread.h>
  17. #include <LibVideo/Containers/Demuxer.h>
  18. #include <LibVideo/Containers/Matroska/Document.h>
  19. #include "VideoDecoder.h"
  20. namespace Video {
  21. class FrameQueueItem {
  22. public:
  23. FrameQueueItem()
  24. : m_data(Empty())
  25. , m_timestamp(Duration::zero())
  26. {
  27. }
  28. static constexpr Duration no_timestamp = Duration::min();
  29. enum class Type {
  30. Frame,
  31. Error,
  32. };
  33. static FrameQueueItem frame(RefPtr<Gfx::Bitmap> bitmap, Duration timestamp)
  34. {
  35. return FrameQueueItem(move(bitmap), timestamp);
  36. }
  37. static FrameQueueItem error_marker(DecoderError&& error, Duration timestamp)
  38. {
  39. return FrameQueueItem(move(error), timestamp);
  40. }
  41. bool is_frame() const { return m_data.has<RefPtr<Gfx::Bitmap>>(); }
  42. RefPtr<Gfx::Bitmap> bitmap() const { return m_data.get<RefPtr<Gfx::Bitmap>>(); }
  43. Duration timestamp() const { return m_timestamp; }
  44. bool is_error() const { return m_data.has<DecoderError>(); }
  45. DecoderError const& error() const { return m_data.get<DecoderError>(); }
  46. DecoderError release_error()
  47. {
  48. auto error = move(m_data.get<DecoderError>());
  49. m_data.set(Empty());
  50. return error;
  51. }
  52. bool is_empty() const { return m_data.has<Empty>(); }
  53. ByteString debug_string() const
  54. {
  55. if (is_error())
  56. return ByteString::formatted("{} at {}ms", error().string_literal(), timestamp().to_milliseconds());
  57. return ByteString::formatted("frame at {}ms", timestamp().to_milliseconds());
  58. }
  59. private:
  60. FrameQueueItem(RefPtr<Gfx::Bitmap> bitmap, Duration timestamp)
  61. : m_data(move(bitmap))
  62. , m_timestamp(timestamp)
  63. {
  64. VERIFY(m_timestamp != no_timestamp);
  65. }
  66. FrameQueueItem(DecoderError&& error, Duration timestamp)
  67. : m_data(move(error))
  68. , m_timestamp(timestamp)
  69. {
  70. }
  71. Variant<Empty, RefPtr<Gfx::Bitmap>, DecoderError> m_data { Empty() };
  72. Duration m_timestamp { no_timestamp };
  73. };
  74. static constexpr size_t frame_buffer_count = 4;
  75. using VideoFrameQueue = Core::SharedSingleProducerCircularQueue<FrameQueueItem, frame_buffer_count>;
  76. enum class PlaybackState {
  77. Playing,
  78. Paused,
  79. Buffering,
  80. Seeking,
  81. Stopped,
  82. };
  83. class PlaybackManager {
  84. AK_MAKE_NONCOPYABLE(PlaybackManager);
  85. AK_MAKE_NONMOVABLE(PlaybackManager);
  86. public:
  87. enum class SeekMode {
  88. Accurate,
  89. Fast,
  90. };
  91. static constexpr SeekMode DEFAULT_SEEK_MODE = SeekMode::Accurate;
  92. static DecoderErrorOr<NonnullOwnPtr<PlaybackManager>> from_file(StringView file);
  93. static DecoderErrorOr<NonnullOwnPtr<PlaybackManager>> from_mapped_file(NonnullOwnPtr<Core::MappedFile> file);
  94. static DecoderErrorOr<NonnullOwnPtr<PlaybackManager>> from_data(ReadonlyBytes data);
  95. PlaybackManager(NonnullOwnPtr<Demuxer>& demuxer, Track video_track, NonnullOwnPtr<VideoDecoder>&& decoder, VideoFrameQueue&& frame_queue);
  96. ~PlaybackManager();
  97. void resume_playback();
  98. void pause_playback();
  99. void restart_playback();
  100. void seek_to_timestamp(Duration, SeekMode = DEFAULT_SEEK_MODE);
  101. bool is_playing() const
  102. {
  103. return m_playback_handler->is_playing();
  104. }
  105. PlaybackState get_state() const
  106. {
  107. return m_playback_handler->get_state();
  108. }
  109. u64 number_of_skipped_frames() const { return m_skipped_frames; }
  110. Duration current_playback_time();
  111. Duration duration();
  112. Function<void(RefPtr<Gfx::Bitmap>)> on_video_frame;
  113. Function<void()> on_playback_state_change;
  114. Function<void(DecoderError)> on_decoder_error;
  115. Function<void(Error)> on_fatal_playback_error;
  116. Track const& selected_video_track() const { return m_selected_video_track; }
  117. private:
  118. class PlaybackStateHandler;
  119. // Abstract class to allow resuming play/pause after the state is completed.
  120. class ResumingStateHandler;
  121. class PlayingStateHandler;
  122. class PausedStateHandler;
  123. class BufferingStateHandler;
  124. class SeekingStateHandler;
  125. class StoppedStateHandler;
  126. static DecoderErrorOr<NonnullOwnPtr<PlaybackManager>> create(NonnullOwnPtr<Demuxer> demuxer);
  127. void timer_callback();
  128. // This must be called with m_demuxer_mutex locked!
  129. DecoderErrorOr<Optional<Duration>> seek_demuxer_to_most_recent_keyframe(Duration timestamp, Optional<Duration> earliest_available_sample = OptionalNone());
  130. Optional<FrameQueueItem> dequeue_one_frame();
  131. void set_state_update_timer(int delay_ms);
  132. void decode_and_queue_one_sample();
  133. void dispatch_decoder_error(DecoderError error);
  134. void dispatch_new_frame(RefPtr<Gfx::Bitmap> frame);
  135. // Returns whether we changed playback states. If so, any PlaybackStateHandler processing must cease.
  136. [[nodiscard]] bool dispatch_frame_queue_item(FrameQueueItem&&);
  137. void dispatch_state_change();
  138. void dispatch_fatal_error(Error);
  139. Duration m_last_present_in_media_time = Duration::zero();
  140. NonnullOwnPtr<Demuxer> m_demuxer;
  141. Threading::Mutex m_demuxer_mutex;
  142. Track m_selected_video_track;
  143. VideoFrameQueue m_frame_queue;
  144. RefPtr<Core::Timer> m_state_update_timer;
  145. unsigned m_decoding_buffer_time_ms = 16;
  146. RefPtr<Threading::Thread> m_decode_thread;
  147. NonnullOwnPtr<VideoDecoder> m_decoder;
  148. Atomic<bool> m_stop_decoding { false };
  149. Threading::Mutex m_decode_wait_mutex;
  150. Threading::ConditionVariable m_decode_wait_condition;
  151. Atomic<bool> m_buffer_is_full { false };
  152. OwnPtr<PlaybackStateHandler> m_playback_handler;
  153. Optional<FrameQueueItem> m_next_frame;
  154. u64 m_skipped_frames { 0 };
  155. // This is a nested class to allow private access.
  156. class PlaybackStateHandler {
  157. public:
  158. PlaybackStateHandler(PlaybackManager& manager)
  159. : m_manager(manager)
  160. {
  161. }
  162. virtual ~PlaybackStateHandler() = default;
  163. virtual StringView name() = 0;
  164. virtual ErrorOr<void> on_enter() { return {}; }
  165. virtual ErrorOr<void> play() { return {}; }
  166. virtual bool is_playing() const = 0;
  167. virtual PlaybackState get_state() const = 0;
  168. virtual ErrorOr<void> pause() { return {}; }
  169. virtual ErrorOr<void> buffer() { return {}; }
  170. virtual ErrorOr<void> seek(Duration target_timestamp, SeekMode);
  171. virtual ErrorOr<void> stop();
  172. virtual Duration current_time() const;
  173. virtual ErrorOr<void> do_timed_state_update() { return {}; }
  174. protected:
  175. template<class T, class... Args>
  176. ErrorOr<void> replace_handler_and_delete_this(Args... args);
  177. PlaybackManager& manager() const;
  178. PlaybackManager& manager()
  179. {
  180. return const_cast<PlaybackManager&>(const_cast<PlaybackStateHandler const*>(this)->manager());
  181. }
  182. private:
  183. PlaybackManager& m_manager;
  184. #if PLAYBACK_MANAGER_DEBUG
  185. bool m_has_exited { false };
  186. #endif
  187. };
  188. };
  189. }