Document.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  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/ByteString.h>
  9. #include <AK/FlyString.h>
  10. #include <AK/HashMap.h>
  11. #include <AK/OwnPtr.h>
  12. #include <AK/Time.h>
  13. #include <AK/Utf8View.h>
  14. #include <LibVideo/Color/CodingIndependentCodePoints.h>
  15. namespace Video::Matroska {
  16. struct EBMLHeader {
  17. ByteString doc_type;
  18. u32 doc_type_version;
  19. };
  20. class SegmentInformation {
  21. public:
  22. u64 timestamp_scale() const { return m_timestamp_scale; }
  23. void set_timestamp_scale(u64 timestamp_scale) { m_timestamp_scale = timestamp_scale; }
  24. Utf8View muxing_app() const { return Utf8View(m_muxing_app); }
  25. void set_muxing_app(ByteString muxing_app) { m_muxing_app = move(muxing_app); }
  26. Utf8View writing_app() const { return Utf8View(m_writing_app); }
  27. void set_writing_app(ByteString writing_app) { m_writing_app = move(writing_app); }
  28. Optional<double> duration_unscaled() const { return m_duration_unscaled; }
  29. void set_duration_unscaled(double duration) { m_duration_unscaled.emplace(duration); }
  30. Optional<Duration> duration() const
  31. {
  32. if (!duration_unscaled().has_value())
  33. return {};
  34. return Duration::from_nanoseconds(static_cast<i64>(static_cast<double>(timestamp_scale()) * duration_unscaled().value()));
  35. }
  36. private:
  37. u64 m_timestamp_scale { 1'000'000 };
  38. ByteString m_muxing_app;
  39. ByteString m_writing_app;
  40. Optional<double> m_duration_unscaled;
  41. };
  42. class TrackEntry {
  43. public:
  44. enum TrackType : u8 {
  45. Invalid = 0,
  46. Video = 1,
  47. Audio = 2,
  48. Complex = 3,
  49. Logo = 16,
  50. Subtitle = 17,
  51. Buttons = 18,
  52. Control = 32,
  53. Metadata = 33,
  54. };
  55. enum class ColorRange : u8 {
  56. Unspecified = 0,
  57. Broadcast = 1,
  58. Full = 2,
  59. UseCICP = 3, // defined by MatrixCoefficients / TransferCharacteristics
  60. };
  61. struct ColorFormat {
  62. ColorPrimaries color_primaries = ColorPrimaries::Unspecified;
  63. TransferCharacteristics transfer_characteristics = TransferCharacteristics::Unspecified;
  64. MatrixCoefficients matrix_coefficients = MatrixCoefficients::Unspecified;
  65. u64 bits_per_channel = 0;
  66. ColorRange range = ColorRange::Unspecified;
  67. CodingIndependentCodePoints to_cicp() const
  68. {
  69. Video::VideoFullRangeFlag video_full_range_flag;
  70. switch (range) {
  71. case ColorRange::Full:
  72. video_full_range_flag = Video::VideoFullRangeFlag::Full;
  73. break;
  74. case ColorRange::Broadcast:
  75. video_full_range_flag = Video::VideoFullRangeFlag::Studio;
  76. break;
  77. case ColorRange::Unspecified:
  78. case ColorRange::UseCICP:
  79. // FIXME: Figure out what UseCICP should do here. Matroska specification did not
  80. // seem to explain in the 'colour' section. When this is fixed, change
  81. // replace_code_points_if_specified to match.
  82. video_full_range_flag = Video::VideoFullRangeFlag::Unspecified;
  83. break;
  84. }
  85. return { color_primaries, transfer_characteristics, matrix_coefficients, video_full_range_flag };
  86. }
  87. };
  88. struct VideoTrack {
  89. u64 pixel_width;
  90. u64 pixel_height;
  91. ColorFormat color_format;
  92. };
  93. struct AudioTrack {
  94. u64 channels;
  95. u64 bit_depth;
  96. };
  97. u64 track_number() const { return m_track_number; }
  98. void set_track_number(u64 track_number) { m_track_number = track_number; }
  99. u64 track_uid() const { return m_track_uid; }
  100. void set_track_uid(u64 track_uid) { m_track_uid = track_uid; }
  101. TrackType track_type() const { return m_track_type; }
  102. void set_track_type(TrackType track_type) { m_track_type = track_type; }
  103. FlyString language() const { return m_language; }
  104. void set_language(FlyString const& language) { m_language = language; }
  105. FlyString codec_id() const { return m_codec_id; }
  106. void set_codec_id(FlyString const& codec_id) { m_codec_id = codec_id; }
  107. double timestamp_scale() const { return m_timestamp_scale; }
  108. void set_timestamp_scale(double timestamp_scale) { m_timestamp_scale = timestamp_scale; }
  109. u64 codec_delay() const { return m_codec_delay; }
  110. void set_codec_delay(u64 codec_delay) { m_codec_delay = codec_delay; }
  111. u64 timestamp_offset() const { return m_timestamp_offset; }
  112. void set_timestamp_offset(u64 timestamp_offset) { m_timestamp_offset = timestamp_offset; }
  113. Optional<VideoTrack> video_track() const
  114. {
  115. if (track_type() != Video)
  116. return {};
  117. return m_video_track;
  118. }
  119. void set_video_track(VideoTrack video_track) { m_video_track = video_track; }
  120. Optional<AudioTrack> audio_track() const
  121. {
  122. if (track_type() != Audio)
  123. return {};
  124. return m_audio_track;
  125. }
  126. void set_audio_track(AudioTrack audio_track) { m_audio_track = audio_track; }
  127. private:
  128. u64 m_track_number { 0 };
  129. u64 m_track_uid { 0 };
  130. TrackType m_track_type { Invalid };
  131. FlyString m_language = "eng"_fly_string;
  132. FlyString m_codec_id;
  133. double m_timestamp_scale { 1 };
  134. u64 m_codec_delay { 0 };
  135. u64 m_timestamp_offset { 0 };
  136. union {
  137. VideoTrack m_video_track {};
  138. AudioTrack m_audio_track;
  139. };
  140. };
  141. class Block {
  142. public:
  143. enum Lacing : u8 {
  144. None = 0b00,
  145. XIPH = 0b01,
  146. FixedSize = 0b10,
  147. EBML = 0b11,
  148. };
  149. u64 track_number() const { return m_track_number; }
  150. void set_track_number(u64 track_number) { m_track_number = track_number; }
  151. Duration timestamp() const { return m_timestamp; }
  152. void set_timestamp(Duration timestamp) { m_timestamp = timestamp; }
  153. bool only_keyframes() const { return m_only_keyframes; }
  154. void set_only_keyframes(bool only_keyframes) { m_only_keyframes = only_keyframes; }
  155. bool invisible() const { return m_invisible; }
  156. void set_invisible(bool invisible) { m_invisible = invisible; }
  157. Lacing lacing() const { return m_lacing; }
  158. void set_lacing(Lacing lacing) { m_lacing = lacing; }
  159. bool discardable() const { return m_discardable; }
  160. void set_discardable(bool discardable) { m_discardable = discardable; }
  161. void set_frames(Vector<ReadonlyBytes>&& frames) { m_frames = move(frames); }
  162. ReadonlyBytes const& frame(size_t index) const { return frames()[index]; }
  163. u64 frame_count() const { return m_frames.size(); }
  164. Vector<ReadonlyBytes> const& frames() const { return m_frames; }
  165. private:
  166. u64 m_track_number { 0 };
  167. Duration m_timestamp { Duration::zero() };
  168. bool m_only_keyframes { false };
  169. bool m_invisible { false };
  170. Lacing m_lacing { None };
  171. bool m_discardable { true };
  172. Vector<ReadonlyBytes> m_frames;
  173. };
  174. class Cluster {
  175. public:
  176. Duration timestamp() const { return m_timestamp; }
  177. void set_timestamp(Duration timestamp) { m_timestamp = timestamp; }
  178. private:
  179. Duration m_timestamp { Duration::zero() };
  180. };
  181. class CueTrackPosition {
  182. public:
  183. u64 track_number() const { return m_track_number; }
  184. void set_track_number(u64 track_number) { m_track_number = track_number; }
  185. size_t cluster_position() const { return m_cluster_position; }
  186. void set_cluster_position(size_t cluster_position) { m_cluster_position = cluster_position; }
  187. size_t block_offset() const { return m_block_offset; }
  188. void set_block_offset(size_t block_offset) { m_block_offset = block_offset; }
  189. private:
  190. u64 m_track_number { 0 };
  191. size_t m_cluster_position { 0 };
  192. size_t m_block_offset { 0 };
  193. };
  194. class CuePoint {
  195. public:
  196. Duration timestamp() const { return m_timestamp; }
  197. void set_timestamp(Duration timestamp) { m_timestamp = timestamp; }
  198. OrderedHashMap<u64, CueTrackPosition>& track_positions() { return m_track_positions; }
  199. OrderedHashMap<u64, CueTrackPosition> const& track_positions() const { return m_track_positions; }
  200. Optional<CueTrackPosition const&> position_for_track(u64 track_number) const { return m_track_positions.get(track_number); }
  201. private:
  202. Duration m_timestamp = Duration::min();
  203. OrderedHashMap<u64, CueTrackPosition> m_track_positions;
  204. };
  205. }