MatroskaDocument.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /*
  2. * Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/ByteBuffer.h>
  8. #include <AK/FlyString.h>
  9. #include <AK/HashMap.h>
  10. #include <AK/NonnullOwnPtrVector.h>
  11. #include <AK/OwnPtr.h>
  12. #include <AK/String.h>
  13. #include <AK/Utf8View.h>
  14. namespace Video {
  15. struct EBMLHeader {
  16. String doc_type;
  17. u32 doc_type_version;
  18. };
  19. class SegmentInformation {
  20. public:
  21. u64 timestamp_scale() const { return m_timestamp_scale; }
  22. void set_timestamp_scale(u64 timestamp_scale) { m_timestamp_scale = timestamp_scale; }
  23. Utf8View muxing_app() const { return Utf8View(m_muxing_app); }
  24. void set_muxing_app(String muxing_app) { m_muxing_app = move(muxing_app); }
  25. Utf8View writing_app() const { return Utf8View(m_writing_app); }
  26. void set_writing_app(String writing_app) { m_writing_app = move(writing_app); }
  27. private:
  28. u64 m_timestamp_scale { 1'000'000 };
  29. String m_muxing_app;
  30. String m_writing_app;
  31. };
  32. class TrackEntry {
  33. public:
  34. enum TrackType : u8 {
  35. Invalid = 0,
  36. Video = 1,
  37. Audio = 2,
  38. Complex = 3,
  39. Logo = 16,
  40. Subtitle = 17,
  41. Buttons = 18,
  42. Control = 32,
  43. Metadata = 33,
  44. };
  45. struct VideoTrack {
  46. u64 pixel_width;
  47. u64 pixel_height;
  48. };
  49. struct AudioTrack {
  50. u64 channels;
  51. u64 bit_depth;
  52. };
  53. u64 track_number() const { return m_track_number; }
  54. void set_track_number(u64 track_number) { m_track_number = track_number; }
  55. u64 track_uid() const { return m_track_uid; }
  56. void set_track_uid(u64 track_uid) { m_track_uid = track_uid; }
  57. TrackType track_type() const { return m_track_type; }
  58. void set_track_type(TrackType track_type) { m_track_type = track_type; }
  59. FlyString language() const { return m_language; }
  60. void set_language(FlyString const& language) { m_language = language; }
  61. FlyString codec_id() const { return m_codec_id; }
  62. void set_codec_id(FlyString const& codec_id) { m_codec_id = codec_id; }
  63. Optional<VideoTrack> video_track() const
  64. {
  65. if (track_type() != Video)
  66. return {};
  67. return m_video_track;
  68. }
  69. void set_video_track(VideoTrack video_track) { m_video_track = video_track; }
  70. Optional<AudioTrack> audio_track() const
  71. {
  72. if (track_type() != Audio)
  73. return {};
  74. return m_audio_track;
  75. }
  76. void set_audio_track(AudioTrack audio_track) { m_audio_track = audio_track; }
  77. private:
  78. u64 m_track_number { 0 };
  79. u64 m_track_uid { 0 };
  80. TrackType m_track_type { Invalid };
  81. FlyString m_language = "eng";
  82. FlyString m_codec_id;
  83. union {
  84. VideoTrack m_video_track;
  85. AudioTrack m_audio_track;
  86. };
  87. };
  88. class Block {
  89. public:
  90. enum Lacing : u8 {
  91. None = 0b00,
  92. XIPH = 0b01,
  93. FixedSize = 0b10,
  94. EBML = 0b11,
  95. };
  96. Block() = default;
  97. u64 track_number() const { return m_track_number; }
  98. void set_track_number(u64 track_number) { m_track_number = track_number; }
  99. i16 timestamp() const { return m_timestamp; }
  100. void set_timestamp(i16 timestamp) { m_timestamp = timestamp; }
  101. bool only_keyframes() const { return m_only_keyframes; }
  102. void set_only_keyframes(bool only_keyframes) { m_only_keyframes = only_keyframes; }
  103. bool invisible() const { return m_invisible; }
  104. void set_invisible(bool invisible) { m_invisible = invisible; }
  105. Lacing lacing() const { return m_lacing; }
  106. void set_lacing(Lacing lacing) { m_lacing = lacing; }
  107. bool discardable() const { return m_discardable; }
  108. void set_discardable(bool discardable) { m_discardable = discardable; }
  109. u64 frame_count() const { return m_frames.size(); }
  110. ByteBuffer const& frame(size_t index) const { return m_frames.at(index); }
  111. void add_frame(ByteBuffer frame) { m_frames.append(move(frame)); }
  112. private:
  113. u64 m_track_number { 0 };
  114. i16 m_timestamp { 0 };
  115. bool m_only_keyframes { false };
  116. bool m_invisible { false };
  117. Lacing m_lacing { None };
  118. bool m_discardable { true };
  119. Vector<ByteBuffer> m_frames;
  120. };
  121. class Cluster {
  122. public:
  123. u64 timestamp() const { return m_timestamp; }
  124. void set_timestamp(u64 timestamp) { m_timestamp = timestamp; }
  125. NonnullOwnPtrVector<Block>& blocks() { return m_blocks; }
  126. NonnullOwnPtrVector<Block> const& blocks() const { return m_blocks; }
  127. private:
  128. u64 m_timestamp { 0 };
  129. NonnullOwnPtrVector<Block> m_blocks;
  130. };
  131. class MatroskaDocument {
  132. public:
  133. explicit MatroskaDocument(EBMLHeader m_header)
  134. : m_header(move(m_header))
  135. {
  136. }
  137. EBMLHeader const& header() const { return m_header; }
  138. Optional<SegmentInformation> segment_information() const
  139. {
  140. if (!m_segment_information)
  141. return {};
  142. return *m_segment_information;
  143. }
  144. void set_segment_information(OwnPtr<SegmentInformation> segment_information) { m_segment_information = move(segment_information); }
  145. HashMap<u64, NonnullOwnPtr<TrackEntry>> const& tracks() const { return m_tracks; }
  146. Optional<TrackEntry> track_for_track_number(u64 track_number) const
  147. {
  148. auto track = m_tracks.get(track_number);
  149. if (!track.has_value())
  150. return {};
  151. return *track.value();
  152. }
  153. Optional<TrackEntry> track_for_track_type(TrackEntry::TrackType type) const
  154. {
  155. for (auto& track_entry : m_tracks) {
  156. if (track_entry.value->track_type() == type)
  157. return *track_entry.value;
  158. }
  159. return {};
  160. }
  161. void add_track(u64 track_number, NonnullOwnPtr<TrackEntry> track)
  162. {
  163. m_tracks.set(track_number, move(track));
  164. }
  165. NonnullOwnPtrVector<Cluster>& clusters() { return m_clusters; }
  166. private:
  167. EBMLHeader m_header;
  168. OwnPtr<SegmentInformation> m_segment_information;
  169. HashMap<u64, NonnullOwnPtr<TrackEntry>> m_tracks;
  170. NonnullOwnPtrVector<Cluster> m_clusters;
  171. };
  172. }