diff --git a/CHANGELOG.md b/CHANGELOG.md index 03fae5e2..156a8c42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - kind box full-box header - stpp support when the optional fields do not even have a zero-termination byte +- mp4ff-wvttlister now lists all boxes in a sample ## [0.42.0] - 2024-01-26 diff --git a/cmd/mp4ff-wvttlister/main.go b/cmd/mp4ff-wvttlister/main.go index 968c7ec6..714c9320 100644 --- a/cmd/mp4ff-wvttlister/main.go +++ b/cmd/mp4ff-wvttlister/main.go @@ -212,9 +212,23 @@ func parseFragmentedMp4(f *mp4.File, w io.Writer, trackID uint32, maxNrSamples i func printWvttSample(w io.Writer, sample []byte, nr int, pts uint64, dur uint32) error { fmt.Fprintf(w, "Sample %d, pts=%d, dur=%d\n", nr, pts, dur) buf := bytes.NewBuffer(sample) - box, err := mp4.DecodeBox(0, buf) - if err != nil { - return err + pos := 0 + for { + box, err := mp4.DecodeBox(uint64(pos), buf) + if err != nil { + if err == io.EOF { + break + } + return err + } + err = box.Info(w, " ", "", " ") + if err != nil { + return err + } + pos += int(box.Size()) + if pos >= len(sample) { + break + } } - return box.Info(w, " ", "", " ") + return nil } diff --git a/cmd/mp4ff-wvttlister/main_test.go b/cmd/mp4ff-wvttlister/main_test.go index 5dce3bd5..7df407be 100644 --- a/cmd/mp4ff-wvttlister/main_test.go +++ b/cmd/mp4ff-wvttlister/main_test.go @@ -7,7 +7,7 @@ import ( "testing" ) -var wanted = `Track 1, timescale = 1000 +var wantedSampleShort = `Track 1, timescale = 1000 [vttC] size=14 - config: "WEBVTT" Sample 1, pts=0, dur=6640 @@ -54,28 +54,58 @@ Sample 8, pts=14680, dur=5320 - sourceID: 1833399447 ` +var wantedMultiVttc = `Sample 1, pts=291054710760, dur=2560 +[vttc] size=113 + [sttg] size=46 + - settings: align:middle line:61%,end position:49% + [payl] size=59 + - cueText: "dans \"mulot\". Bravo, Agathe !" +[vttc] size=117 + [sttg] size=46 + - settings: align:middle line:68%,end position:49% + [payl] size=63 + - cueText: "Ouais ! Belle gosse ! Voici 2 M !" +` + func TestWvttLister(t *testing.T) { - testFile := "testdata/sample_short.ismt" - ifh, err := os.Open(testFile) - if err != nil { - t.Error(err) - } - defer ifh.Close() - var w bytes.Buffer - err = run(ifh, &w, 0, -1) - if err != nil { - t.Error(err) + testCases := []struct { + testFile string + wanted string + }{ + { + testFile: "testdata/sample_short.ismt", + wanted: wantedSampleShort, + }, + { + testFile: "testdata/multi_vttc.mp4", + wanted: wantedMultiVttc, + }, } - got := w.String() - gotLines := strings.Split(got, "\n") - wantedLines := strings.Split(wanted, "\n") - if len(gotLines) != len(wantedLines) { - t.Errorf("got %d lines, wanted %d", len(gotLines), len(wantedLines)) - } - for i := range gotLines { - if gotLines[i] != wantedLines[i] { - t.Errorf("line %d: got: %q\n wanted %q", i, gotLines[i], wantedLines[i]) - } + + for _, tc := range testCases { + t.Run(tc.testFile, func(t *testing.T) { + ifh, err := os.Open(tc.testFile) + if err != nil { + t.Error(err) + } + defer ifh.Close() + var w bytes.Buffer + err = run(ifh, &w, 0, -1) + if err != nil { + t.Error(err) + } + got := w.String() + gotLines := strings.Split(got, "\n") + wantedLines := strings.Split(tc.wanted, "\n") + if len(gotLines) != len(wantedLines) { + t.Errorf("got %d lines, wanted %d", len(gotLines), len(wantedLines)) + } + for i := range gotLines { + if gotLines[i] != wantedLines[i] { + t.Errorf("line %d: got: %q\n wanted %q", i, gotLines[i], wantedLines[i]) + } + } + }) } } diff --git a/cmd/mp4ff-wvttlister/testdata/multi_vttc.mp4 b/cmd/mp4ff-wvttlister/testdata/multi_vttc.mp4 new file mode 100644 index 00000000..5ccdbb2b Binary files /dev/null and b/cmd/mp4ff-wvttlister/testdata/multi_vttc.mp4 differ