/* * Copyright (c) 2021, Hunter Salyer * Copyright (c) 2022, Gregory Bertilson * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include "Document.h" namespace Video::Matroska { class SampleIterator; class Streamer; class Reader { public: typedef Function(TrackEntry const&)> TrackEntryCallback; static DecoderErrorOr from_file(StringView path); static DecoderErrorOr from_data(ReadonlyBytes data); EBMLHeader const& header() const { return m_header.value(); } DecoderErrorOr segment_information(); DecoderErrorOr for_each_track(TrackEntryCallback); DecoderErrorOr for_each_track_of_type(TrackEntry::TrackType, TrackEntryCallback); DecoderErrorOr track_for_track_number(u64); DecoderErrorOr track_count(); DecoderErrorOr create_sample_iterator(u64 track_number); DecoderErrorOr seek_to_random_access_point(SampleIterator, Time); DecoderErrorOr const&>> cue_points_for_track(u64 track_number); DecoderErrorOr has_cues_for_track(u64 track_number); private: Reader(ReadonlyBytes data) : m_data(data) { } DecoderErrorOr parse_initial_data(); DecoderErrorOr> find_first_top_level_element_with_id([[maybe_unused]] StringView element_name, u32 element_id); DecoderErrorOr ensure_tracks_are_parsed(); DecoderErrorOr parse_tracks(Streamer&); DecoderErrorOr parse_cues(Streamer&); DecoderErrorOr ensure_cues_are_parsed(); DecoderErrorOr seek_to_cue_for_timestamp(SampleIterator&, Time const&); RefPtr m_mapped_file; ReadonlyBytes m_data; Optional m_header; size_t m_segment_contents_position { 0 }; size_t m_segment_contents_size { 0 }; HashMap m_seek_entries; size_t m_last_top_level_element_position { 0 }; Optional m_segment_information; OrderedHashMap m_tracks; // The vectors must be sorted by timestamp at all times. HashMap> m_cues; bool m_cues_have_been_parsed { false }; }; class SampleIterator { public: DecoderErrorOr next_block(); Cluster const& current_cluster() { return *m_current_cluster; } Optional