diff --git a/internal/playback/fmp4.go b/internal/playback/fmp4.go index c7819749..dcfbd847 100644 --- a/internal/playback/fmp4.go +++ b/internal/playback/fmp4.go @@ -95,7 +95,7 @@ func fmp4ReadInit(r io.ReadSeeker) ([]byte, error) { return buf, nil } -func fmp4ReadDuration(r io.ReadSeeker) (time.Duration, error) { +func fmp4ReadMaxDuration(r io.ReadSeeker) (time.Duration, error) { // find and skip ftyp buf := make([]byte, 8) @@ -321,7 +321,7 @@ func fmp4SeekAndMuxParts( var outPart *fmp4.Part var outTrack *fmp4.PartTrack var outBuf seekablebuffer.Buffer - elapsed := uint64(0) + maxElapsed := uint64(0) initWritten := false firstSampleWritten := make(map[uint32]struct{}) gop := make(map[uint32][]*fmp4.PartSample) @@ -370,7 +370,7 @@ func fmp4SeekAndMuxParts( return nil, err } - elapsed = tfdt.BaseMediaDecodeTimeV1 + elapsed := tfdt.BaseMediaDecodeTimeV1 baseTimeSet := false for _, e := range trun.Entries { @@ -426,6 +426,10 @@ func fmp4SeekAndMuxParts( elapsed += uint64(e.SampleDuration) } + if elapsed > maxElapsed { + maxElapsed = elapsed + } + if outTrack.Samples != nil { outPart.Tracks = append(outPart.Tracks, outTrack) } @@ -467,9 +471,9 @@ func fmp4SeekAndMuxParts( return 0, errNoSegmentsFound } - elapsed -= minTimeMP4 + maxElapsed -= minTimeMP4 - return durationMp4ToGo(elapsed, fmp4Timescale), nil + return durationMp4ToGo(maxElapsed, fmp4Timescale), nil } func fmp4MuxParts( @@ -485,7 +489,7 @@ func fmp4MuxParts( var outPart *fmp4.Part var outTrack *fmp4.PartTrack var outBuf seekablebuffer.Buffer - elapsed := uint64(0) + maxElapsed := uint64(0) _, err := mp4.ReadBoxStructure(r, func(h *mp4.ReadHandle) (interface{}, error) { switch h.BoxInfo.Type.String() { @@ -534,7 +538,7 @@ func fmp4MuxParts( return nil, err } - elapsed = tfdt.BaseMediaDecodeTimeV1 + elapsed := tfdt.BaseMediaDecodeTimeV1 for _, e := range trun.Entries { payload := make([]byte, e.SampleSize) @@ -561,6 +565,10 @@ func fmp4MuxParts( elapsed += uint64(e.SampleDuration) } + if elapsed > maxElapsed { + maxElapsed = elapsed + } + if outTrack.Samples != nil { outPart.Tracks = append(outPart.Tracks, outTrack) } @@ -590,5 +598,5 @@ func fmp4MuxParts( return 0, err } - return durationMp4ToGo(elapsed, fmp4Timescale), nil + return durationMp4ToGo(maxElapsed, fmp4Timescale), nil } diff --git a/internal/playback/on_get.go b/internal/playback/on_get.go index 4cea1839..e610260b 100644 --- a/internal/playback/on_get.go +++ b/internal/playback/on_get.go @@ -38,7 +38,7 @@ func seekAndMux( minTime := start.Sub(segments[0].Start) maxTime := minTime + duration var init []byte - var elapsed time.Duration + var maxElapsed time.Duration err := func() error { f, err := os.Open(segments[0].Fpath) @@ -52,7 +52,7 @@ func seekAndMux( return err } - elapsed, err = fmp4SeekAndMuxParts(f, init, minTime, maxTime, w) + maxElapsed, err = fmp4SeekAndMuxParts(f, init, minTime, maxTime, w) if err != nil { return err } @@ -63,10 +63,10 @@ func seekAndMux( return err } + duration -= maxElapsed + overallElapsed := maxElapsed prevInit := init - prevEnd := start.Add(elapsed) - duration -= elapsed - overallElapsed := elapsed + prevEnd := start.Add(maxElapsed) for _, seg := range segments[1:] { err := func() error { @@ -85,7 +85,7 @@ func seekAndMux( return errStopIteration } - elapsed, err = fmp4MuxParts(f, overallElapsed, duration, w) + maxElapsed, err = fmp4MuxParts(f, overallElapsed, duration, w) if err != nil { return err } @@ -100,9 +100,9 @@ func seekAndMux( return err } - prevEnd = seg.Start.Add(elapsed) - duration -= elapsed - overallElapsed += elapsed + duration -= maxElapsed + overallElapsed += maxElapsed + prevEnd = seg.Start.Add(maxElapsed) } return nil diff --git a/internal/playback/on_get_test.go b/internal/playback/on_get_test.go index 266a1588..b4b97d24 100644 --- a/internal/playback/on_get_test.go +++ b/internal/playback/on_get_test.go @@ -59,27 +59,40 @@ func writeSegment1(t *testing.T, fpath string) { }, { SequenceNumber: 1, - Tracks: []*fmp4.PartTrack{{ - ID: 1, - BaseTime: 30 * 90000, - Samples: []*fmp4.PartSample{ - { - Duration: 30 * 90000, - IsNonSyncSample: false, - Payload: []byte{1, 2}, - }, - { - Duration: 1 * 90000, - IsNonSyncSample: false, - Payload: []byte{3, 4}, - }, - { - Duration: 1 * 90000, - IsNonSyncSample: true, - Payload: []byte{5, 6}, + Tracks: []*fmp4.PartTrack{ + { + ID: 1, + BaseTime: 30 * 90000, + Samples: []*fmp4.PartSample{ + { + Duration: 30 * 90000, + IsNonSyncSample: false, + Payload: []byte{1, 2}, + }, + { + Duration: 1 * 90000, + IsNonSyncSample: false, + Payload: []byte{3, 4}, + }, + { + Duration: 1 * 90000, + IsNonSyncSample: true, + Payload: []byte{5, 6}, + }, }, }, - }}, + { + ID: 2, + BaseTime: 29 * 90000, + Samples: []*fmp4.PartSample{ + { + Duration: 30 * 90000, + IsNonSyncSample: false, + Payload: []byte{1, 2}, + }, + }, + }, + }, }, } err = parts.Marshal(&buf2) diff --git a/internal/playback/on_list.go b/internal/playback/on_list.go index 57c14355..d44e2ced 100644 --- a/internal/playback/on_list.go +++ b/internal/playback/on_list.go @@ -47,7 +47,7 @@ func computeDurationAndConcatenate(recordFormat conf.RecordFormat, segments []*S return err } - duration, err := fmp4ReadDuration(f) + maxDuration, err := fmp4ReadMaxDuration(f) if err != nil { return err } @@ -58,12 +58,12 @@ func computeDurationAndConcatenate(recordFormat conf.RecordFormat, segments []*S init, seg.Start) { prevStart := out[len(out)-1].Start - curEnd := seg.Start.Add(duration) + curEnd := seg.Start.Add(maxDuration) out[len(out)-1].Duration = listEntryDuration(curEnd.Sub(prevStart)) } else { out = append(out, listEntry{ Start: seg.Start, - Duration: listEntryDuration(duration), + Duration: listEntryDuration(maxDuration), }) }