// Copyright 2026 Leo Cheng
// SPDX-License-Identifier: Apache-2.0
///|
/// A fragment with two samples, written out, read back, and walked.
///
/// moon run src/examples/02-boxes
#coverage.skip
fn main raise {
let samples : Array[@mp4.SampleData] = [
{
data: Bytes::from_array([b'\x00', b'\x00', b'\x00', b'\x01', b'\x67']),
duration: 1024L,
composition_offset: 0L,
sync: true,
},
{
data: Bytes::from_array([b'\x00', b'\x00', b'\x00', b'\x01', b'\x41']),
duration: 1024L,
composition_offset: 512L,
sync: false,
},
]
let fragment = @mp4.MovieFragment::new(1, [
{ track_id: 1, base_decode_time: 0L, samples, },
])
let data = fragment.encode()
println("fragment: " + data.length().to_string() + " bytes")
let file = @mp4.Mp4::parse(data[:])
println("boxes at the top")
for box in file.boxes {
println(" " + box.type_ + " (" + box.byte_length().to_string() + " bytes)")
for child in box.boxes() {
println(
" " +
child.type_ +
" (" +
child.byte_length().to_string() +
" bytes)",
)
}
}
let read = file.fragments()[0]
println(
"fragment " +
read.sequence.to_string() +
", media from " +
read.start.to_string() +
" to " +
read.end.to_string(),
)
for run in read.runs {
println(
" track " +
run.track_id.to_string() +
", decode time " +
run.base_decode_time.to_string(),
)
for sample in run.samples {
println(
" " +
sample.size.to_string() +
" bytes at " +
sample.offset.to_string() +
", " +
sample.duration.to_string() +
" ticks, key frame: " +
sample.sync.to_string(),
)
}
}
// Reading and writing again gives the same bytes: a box this package has no
// name for is kept as it was, and so is everything else.
println("round trip: " + (file.encode() == data).to_string())
// The bytes a sample points at are the bytes that went in.
let first = read.runs[0].samples[0]
println(
"first sample: " +
@utf8.decode_lossy(data[first.offset:first.offset + first.size]).to_string(),
)
}