moonbitstack/moonmedia/mp4 does not have a README file

    Mp4Error

    pub(all) suberror Mp4Error {
    Malformed(at~ : Int, want~ : String, got~ : String)
    }

    Why a file could not be read.

    at is the offset in the file the reader had reached, want what the format requires there and got what was actually there.
    impl Show for Mp4Error

    Mp4Error::output

    fn Mp4Error::output(self : Mp4Error, logger : &Logger) -> Unit

    The account of a failure.

    Mp4Error::to_string

    fn Mp4Error::to_string(self : Mp4Error) -> String

    The account of a failure.

    Box

    pub(all) struct Box {
    type_ : String
    usertype : Bytes?
    large : Bool
    content : Content
    } derive(Eq,
    Debug
    )

    One box: a type, a size and its content.

    large remembers that the size was written as a 64-bit field rather than the usual 32-bit one, because writing it back the other way would change the file even though it would still be readable.

    Box::boxes

    fn Box::boxes(self : Box) -> Array[Box]

    The child boxes, or an empty array for a box that holds bytes.

    Box::byte_length

    fn Box::byte_length(self : Box) -> Int

    How many bytes this box occupies, header included.

    Box::bytes

    fn Box::bytes(type_ : StringView, raw : Bytes) -> Box

    A box of type_ holding bytes.

    Box::child

    fn Box::child(self : Box, type_ : StringView) -> Box?

    The first child of this box with the given type.

    Box::children

    fn Box::children(type_ : StringView, boxes : Array[Box]) -> Box

    A box of type_ holding smaller boxes.

    Box::children_of

    fn Box::children_of(self : Box, type_ : StringView) -> Array[Box]

    Every child of this box with the given type, in order.

    Box::encode

    fn Box::encode(self : Box) -> Bytes

    Write one box.

    Box::equal

    fn Box::equal(Box, Box) -> Bool

    Box::fourcc

    fn Box::fourcc(self : Box) -> StringView

    The four character code as a view.

    Box::is_type

    fn Box::is_type(self : Box, type_ : StringView) -> Bool

    Whether this box is of the given type.

    Box::not_equal

    fn Box::not_equal(x : Box, y : Box) -> Bool

    Box::raw

    fn Box::raw(self : Box) -> Bytes

    The bytes this box holds itself, without its children.

    Box::to_repr

    Content

    pub(all) enum Content {
    Children(prefix~ : Bytes, boxes~ : Array[Box])
    Bytes(raw~ : Bytes)
    } derive(Eq,
    Debug
    )

    What a box holds.

    A box either contains smaller boxes or a run of bytes. The boxes that hold both — a sample description entry is a fixed header followed by child boxes — keep the fixed part in prefix and the children after it, so the tree stays generic without losing a byte.

    Content::equal

    fn Content::equal(Content, Content) -> Bool

    Content::not_equal

    fn Content::not_equal(x : Content, y : Content) -> Bool

    Content::to_repr

    FileType

    pub(all) struct FileType {
    major : String
    minor : Int
    compatible : Array[String]
    } derive(Eq,
    Debug
    )

    The brands a file declares in ftyp.

    FileType::encode

    fn FileType::encode(self : FileType) -> Bytes

    Write a file type box.

    FileType::equal

    fn FileType::equal(FileType, FileType) -> Bool

    FileType::not_equal

    fn FileType::not_equal(x : FileType, y : FileType) -> Bool

    FileType::of

    fn FileType::of(raw : Bytes) -> FileType raise Mp4Error

    Read a file type box.

    FileType::to_repr

    Fragment

    pub(all) struct Fragment {
    sequence : Int
    start : Int
    end : Int
    runs : Array[Run]
    } derive(Eq,
    Debug
    )

    One movie fragment: the moof that describes it and the media data that follows, up to the next fragment.

    Fragment::equal

    fn Fragment::equal(Fragment, Fragment) -> Bool

    Fragment::not_equal

    fn Fragment::not_equal(x : Fragment, y : Fragment) -> Bool

    Fragment::to_repr

    FragmentTrack

    pub(all) struct FragmentTrack {
    track_id : Int
    base_decode_time : Int64
    samples : Array[SampleData]
    } derive(Eq,
    Debug
    )

    One track's contribution to a fragment.

    FragmentTrack::equal

    FragmentTrack::not_equal

    fn FragmentTrack::not_equal(x : FragmentTrack, y : FragmentTrack) -> Bool

    IndexReference

    pub(all) struct IndexReference {
    reference_type : Bool
    referenced_size : Int64
    subsegment_duration : Int64
    starts_with_sap : Bool
    sap_type : Int
    sap_delta_time : Int64
    } derive(Eq,
    Debug
    )

    One piece of a segment index: how big the next piece is and how long it plays, or a pointer to another index.

    IndexReference::equal

    IndexReference::not_equal

    fn IndexReference::not_equal(x : IndexReference, y : IndexReference) -> Bool

    MovieFragment

    pub(all) struct MovieFragment {
    sequence : Int
    tracks : Array[FragmentTrack]
    } derive(Eq,
    Debug
    )

    A movie fragment ready to be written: moof and the mdat it points at.

    MovieFragment::duration

    fn MovieFragment::duration(self : MovieFragment, timescale : Int64) -> Double

    How long the fragment plays, in the timescale of its longest track.

    MovieFragment::encode

    fn MovieFragment::encode(self : MovieFragment) -> Bytes

    The fragment as bytes: the moof and then the mdat, which is the order a player needs them in when both arrive in one request.

    MovieFragment::equal

    MovieFragment::new

    fn MovieFragment::new(sequence : Int, tracks : Array[FragmentTrack]) -> MovieFragment

    A fragment of tracks carrying fragment number sequence.

    MovieFragment::not_equal

    fn MovieFragment::not_equal(x : MovieFragment, y : MovieFragment) -> Bool

    MovieFragment::sample_bytes

    fn MovieFragment::sample_bytes(self : MovieFragment) -> Bytes

    The sample bytes of every track, in track order, which is the order the data offsets describe.

    MovieHeader

    pub(all) struct MovieHeader {
    timescale : Int64
    duration : Int64
    } derive(Eq,
    Debug
    )

    A track's timescale: how many units make a second.

    MovieHeader::equal

    fn MovieHeader::equal(MovieHeader, MovieHeader) -> Bool

    MovieHeader::not_equal

    fn MovieHeader::not_equal(x : MovieHeader, y : MovieHeader) -> Bool

    Mp4

    pub(all) struct Mp4 {
    data : Bytes
    boxes : Array[Box]
    }

    A file and the boxes it was read into.

    The bytes are kept because sample data is described by offsets into them: a sample is a view, not a copy, so a track of a hundred thousand frames costs nothing to list.

    Mp4::box

    fn Mp4::box(self : Mp4, type_ : StringView) -> Box?

    The first box of a type at the top level.

    Mp4::encode

    fn Mp4::encode(self : Mp4) -> Bytes

    Write the file back. A file read and written again is the same bytes.

    Mp4::file_type

    fn Mp4::file_type(self : Mp4) -> FileType? raise Mp4Error

    The brand a file declares, ftyp.

    Mp4::fragments

    fn Mp4::fragments(self : Mp4) -> Array[Fragment] raise Mp4Error

    The fragments of a fragmented file, in order.

    A fragment runs from its moof to the next one, so a segment cut on a fragment boundary is a run of whole boxes.

    Mp4::init_section

    fn Mp4::init_section(self : Mp4) -> Bytes raise Mp4Error

    The boxes a player needs before the first fragment: a file type, and a movie header whose sample tables are empty and whose mvex describes what is to come.

    The durations in the header are set to zero, because a live stream does not know how long it is; a fragment says when it starts, and that is what a player uses.

    Mp4::is_fragmented

    fn Mp4::is_fragmented(self : Mp4) -> Bool

    Whether the file describes its media in fragments rather than in a sample table, which is what a stream cut into segments looks like.

    Mp4::movie

    fn Mp4::movie(self : Mp4) -> Box?

    The movie header, moov.

    Mp4::parse

    fn Mp4::parse(data : BytesView) -> Mp4 raise Mp4Error

    Read a file.

    Mp4::tracks

    fn Mp4::tracks(self : Mp4) -> Array[Track] raise Mp4Error

    The samples of every track, in the order the tracks appear.

    Run

    pub(all) struct Run {
    track_id : Int
    base_decode_time : Int64
    samples : Array[Sample]
    } derive(Eq,
    Debug
    )

    The samples one track contributes to a fragment.

    Run::equal

    fn Run::equal(Run, Run) -> Bool

    Run::not_equal

    fn Run::not_equal(x : Run, y : Run) -> Bool

    Run::to_repr

    Sample

    pub(all) struct Sample {
    offset : Int
    size : Int
    dts : Int64
    duration : Int64
    composition_offset : Int64
    sync : Bool
    } derive(Eq,
    Debug
    )

    One sample: where its bytes are, when it plays, and whether a player may start here.

    Sample::equal

    fn Sample::equal(Sample, Sample) -> Bool

    Sample::not_equal

    fn Sample::not_equal(x : Sample, y : Sample) -> Bool

    Sample::pts

    fn Sample::pts(self : Sample) -> Int64

    When the sample is shown, in the track's timescale.

    Sample::seconds

    fn Sample::seconds(self : Sample, timescale : Int64) -> Double

    How long the sample is in seconds.

    Sample::to_repr

    SampleData

    pub(all) struct SampleData {
    data : Bytes
    duration : Int64
    composition_offset : Int64
    sync : Bool
    } derive(Eq,
    Debug
    )

    A sample as it is written into a fragment: its bytes and what the fragment has to say about it.

    SampleData::equal

    fn SampleData::equal(SampleData, SampleData) -> Bool

    SampleData::not_equal

    fn SampleData::not_equal(x : SampleData, y : SampleData) -> Bool

    SegmentIndex

    pub(all) struct SegmentIndex {
    reference_id : Int
    timescale : Int64
    earliest_presentation_time : Int64
    first_offset : Int64
    references : Array[IndexReference]
    } derive(Eq,
    Debug
    )

    A segment index, sidx (ISO/IEC 14496-12 §8.16.3).

    It says where the pieces of a fragmented stream are, in a form a player can read without downloading them, which is how a DASH client knows what to fetch next.

    SegmentIndex::encode

    fn SegmentIndex::encode(self : SegmentIndex) -> Bytes

    Write a segment index back as a sidx box.

    The version is chosen from the values: a presentation time or an offset past what 32 bits hold needs the wide form, and a reader that assumed the narrow one would run into the next field.

    SegmentIndex::equal

    SegmentIndex::not_equal

    fn SegmentIndex::not_equal(x : SegmentIndex, y : SegmentIndex) -> Bool

    Track

    pub(all) struct Track {
    id : Int
    kind : TrackKind
    timescale : Int64
    duration : Int64
    language : String
    codec : String
    width : Int
    height : Int
    sample_rate : Int
    channels : Int
    samples : Array[Sample]
    } derive(Eq,
    Debug
    )

    A track and the samples it holds, read from the sample table or from the fragments.

    Track::equal

    fn Track::equal(Track, Track) -> Bool

    Track::not_equal

    fn Track::not_equal(x : Track, y : Track) -> Bool

    Track::to_repr

    TrackKind

    pub(all) enum TrackKind {
    Video
    Audio
    Subtitle
    Hint
    Other(String)
    } derive(Eq,
    Debug
    )

    What a track carries, from the handler hdlr names.

    TrackKind::equal

    fn TrackKind::equal(TrackKind, TrackKind) -> Bool

    TrackKind::not_equal

    fn TrackKind::not_equal(x : TrackKind, y : TrackKind) -> Bool

    encode

    fn encode(boxes : Array[Box]) -> Bytes

    Write boxes back out.

    ftyp

    fn ftyp(major : StringView, compatible : Array[String]) -> Box

    A file type box.

    mdat

    fn mdat(data : Bytes) -> Box

    A media data box holding data.

    mfhd

    fn mfhd(sequence : Int) -> Box

    A fragment header: the fragment's number.

    movie_header

    fn movie_header(moov : Box) -> MovieHeader raise Mp4Error

    Read a mvhd.

    parse

    fn parse(data : BytesView) -> Array[Box] raise Mp4Error

    Read the boxes at the start of data.

    Reading stops at the first byte that is not a box; a file whose last box was cut short is refused rather than half-read.

    segment_index

    fn segment_index(box : Box) -> SegmentIndex raise Mp4Error

    Read a sidx box.

    tfdt

    fn tfdt(base_decode_time : Int64) -> Box

    The decode time the fragment starts at, so a player can place it without having seen the ones before it.

    tfhd

    fn tfhd(track_id : Int) -> Box

    A track fragment header that says where this track's data is: in this fragment, which is what default-base-is-moof means.

    trun

    fn trun(samples : Array[SampleData], data_offset : Int) -> Box

    A track run: every sample, with its duration, size, flags and composition offset written out rather than defaulted, so the fragment needs nothing from the header to be read.