package record import ( "io" "os" "path/filepath" "time" "github.com/bluenviron/mediacommon/pkg/formats/fmp4" "github.com/bluenviron/mediacommon/pkg/formats/fmp4/seekablebuffer" "github.com/bluenviron/mediamtx/internal/logger" ) func writePart( f io.Writer, sequenceNumber uint32, partTracks map[*formatFMP4Track]*fmp4.PartTrack, ) error { fmp4PartTracks := make([]*fmp4.PartTrack, len(partTracks)) i := 0 for _, partTrack := range partTracks { fmp4PartTracks[i] = partTrack i++ } part := &fmp4.Part{ SequenceNumber: sequenceNumber, Tracks: fmp4PartTracks, } var buf seekablebuffer.Buffer err := part.Marshal(&buf) if err != nil { return err } _, err = f.Write(buf.Bytes()) return err } type formatFMP4Part struct { s *formatFMP4Segment sequenceNumber uint32 startDTS time.Duration partTracks map[*formatFMP4Track]*fmp4.PartTrack endDTS time.Duration } func (p *formatFMP4Part) initialize() { p.partTracks = make(map[*formatFMP4Track]*fmp4.PartTrack) } func (p *formatFMP4Part) close() error { if p.s.fi == nil { p.s.path = Path(p.s.startNTP).Encode(p.s.f.a.pathFormat) p.s.f.a.agent.Log(logger.Debug, "creating segment %s", p.s.path) err := os.MkdirAll(filepath.Dir(p.s.path), 0o755) if err != nil { return err } fi, err := os.Create(p.s.path) if err != nil { return err } p.s.f.a.agent.OnSegmentCreate(p.s.path) err = writeInit(fi, p.s.f.tracks) if err != nil { fi.Close() return err } p.s.fi = fi } return writePart(p.s.fi, p.sequenceNumber, p.partTracks) } func (p *formatFMP4Part) record(track *formatFMP4Track, sample *sample) error { partTrack, ok := p.partTracks[track] if !ok { partTrack = &fmp4.PartTrack{ ID: track.initTrack.ID, BaseTime: durationGoToMp4(sample.dts-p.s.startDTS, track.initTrack.TimeScale), } p.partTracks[track] = partTrack } partTrack.Samples = append(partTrack.Samples, sample.PartSample) p.endDTS = sample.dts return nil } func (p *formatFMP4Part) duration() time.Duration { return p.endDTS - p.startDTS }