MatroskaDemuxer.cpp 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /*
  2. * Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "MatroskaDemuxer.h"
  7. namespace Video::Matroska {
  8. DecoderErrorOr<NonnullOwnPtr<MatroskaDemuxer>> MatroskaDemuxer::from_file(StringView filename)
  9. {
  10. return make<MatroskaDemuxer>(TRY(Reader::from_file(filename)));
  11. }
  12. DecoderErrorOr<NonnullOwnPtr<MatroskaDemuxer>> MatroskaDemuxer::from_data(ReadonlyBytes data)
  13. {
  14. return make<MatroskaDemuxer>(TRY(Reader::from_data(data)));
  15. }
  16. DecoderErrorOr<Vector<Track>> MatroskaDemuxer::get_tracks_for_type(TrackType type)
  17. {
  18. TrackEntry::TrackType matroska_track_type;
  19. switch (type) {
  20. case TrackType::Video:
  21. matroska_track_type = TrackEntry::TrackType::Video;
  22. break;
  23. case TrackType::Audio:
  24. matroska_track_type = TrackEntry::TrackType::Audio;
  25. break;
  26. case TrackType::Subtitles:
  27. matroska_track_type = TrackEntry::TrackType::Subtitle;
  28. break;
  29. }
  30. Vector<Track> tracks;
  31. TRY(m_reader.for_each_track_of_type(matroska_track_type, [&](TrackEntry const& track_entry) -> DecoderErrorOr<IterationDecision> {
  32. VERIFY(track_entry.track_type() == matroska_track_type);
  33. DECODER_TRY_ALLOC(tracks.try_append(Track(type, track_entry.track_number())));
  34. return IterationDecision::Continue;
  35. }));
  36. return tracks;
  37. }
  38. DecoderErrorOr<MatroskaDemuxer::TrackStatus*> MatroskaDemuxer::get_track_status(Track track)
  39. {
  40. if (!m_track_statuses.contains(track)) {
  41. auto iterator = TRY(m_reader.create_sample_iterator(track.identifier()));
  42. DECODER_TRY_ALLOC(m_track_statuses.try_set(track, { iterator }));
  43. }
  44. return &m_track_statuses.get(track).release_value();
  45. }
  46. DecoderErrorOr<void> MatroskaDemuxer::seek_to_most_recent_keyframe(Track track, size_t timestamp)
  47. {
  48. if (timestamp == 0) {
  49. // Removing the track status will cause us to start from the beginning.
  50. m_track_statuses.remove(track);
  51. return {};
  52. }
  53. return DecoderError::not_implemented();
  54. }
  55. DecoderErrorOr<NonnullOwnPtr<Sample>> MatroskaDemuxer::get_next_sample_for_track(Track track)
  56. {
  57. // FIXME: This makes a copy of the sample, which shouldn't be necessary.
  58. // Matroska should make a RefPtr<ByteBuffer>, probably.
  59. auto& status = *TRY(get_track_status(track));
  60. if (!status.block.has_value() || status.frame_index >= status.block->frame_count()) {
  61. status.block = TRY(status.iterator.next_block());
  62. status.frame_index = 0;
  63. }
  64. auto const& cluster = status.iterator.current_cluster();
  65. Time timestamp = Time::from_nanoseconds((cluster.timestamp() + status.block->timestamp()) * TRY(m_reader.segment_information()).timestamp_scale());
  66. auto cicp = TRY(m_reader.track_for_track_number(track.identifier())).video_track()->color_format.to_cicp();
  67. return make<VideoSample>(status.block->frame(status.frame_index++), cicp, timestamp);
  68. }
  69. DecoderErrorOr<Time> MatroskaDemuxer::duration()
  70. {
  71. auto segment_information = TRY(m_reader.segment_information());
  72. if (!segment_information.duration().has_value())
  73. return Time::zero();
  74. return Time::from_nanoseconds(static_cast<i64>(segment_information.duration().value() * segment_information.timestamp_scale()));
  75. }
  76. }