github.com/bluenviron/mediacommon@v1.9.3/pkg/formats/fmp4/part_track.go (about) 1 package fmp4 2 3 import ( 4 "github.com/abema/go-mp4" 5 ) 6 7 // PartTrack is a track of Part. 8 type PartTrack struct { 9 ID int 10 BaseTime uint64 11 Samples []*PartSample 12 } 13 14 func (pt *PartTrack) marshal(w *mp4Writer) (*mp4.Trun, int, error) { 15 /* 16 |traf| 17 | |tfhd| 18 | |tfdt| 19 | |trun| 20 */ 21 22 _, err := w.writeBoxStart(&mp4.Traf{}) // <traf> 23 if err != nil { 24 return nil, 0, err 25 } 26 27 flags := 0 28 29 _, err = w.writeBox(&mp4.Tfhd{ // <tfhd/> 30 FullBox: mp4.FullBox{ 31 Flags: [3]byte{2, byte(flags >> 8), byte(flags)}, 32 }, 33 TrackID: uint32(pt.ID), 34 }) 35 if err != nil { 36 return nil, 0, err 37 } 38 39 _, err = w.writeBox(&mp4.Tfdt{ // <tfdt/> 40 FullBox: mp4.FullBox{ 41 Version: 1, 42 }, 43 // sum of decode durations of all earlier samples 44 BaseMediaDecodeTimeV1: pt.BaseTime, 45 }) 46 if err != nil { 47 return nil, 0, err 48 } 49 50 flags = trunFlagDataOffsetPreset | 51 trunFlagSampleDurationPresent | 52 trunFlagSampleSizePresent 53 54 for _, sample := range pt.Samples { 55 if sample.IsNonSyncSample { 56 flags |= trunFlagSampleFlagsPresent 57 } 58 if sample.PTSOffset != 0 { 59 flags |= trunFlagSampleCompositionTimeOffsetPresentOrV1 60 } 61 } 62 63 trun := &mp4.Trun{ // <trun/> 64 FullBox: mp4.FullBox{ 65 Version: 1, 66 Flags: [3]byte{0, byte(flags >> 8), byte(flags)}, 67 }, 68 SampleCount: uint32(len(pt.Samples)), 69 } 70 71 for _, sample := range pt.Samples { 72 var flags uint32 73 if sample.IsNonSyncSample { 74 flags |= sampleFlagIsNonSyncSample 75 } 76 77 trun.Entries = append(trun.Entries, mp4.TrunEntry{ 78 SampleDuration: sample.Duration, 79 SampleSize: uint32(len(sample.Payload)), 80 SampleFlags: flags, 81 SampleCompositionTimeOffsetV1: sample.PTSOffset, 82 }) 83 } 84 85 trunOffset, err := w.writeBox(trun) 86 if err != nil { 87 return nil, 0, err 88 } 89 90 err = w.writeBoxEnd() // </traf> 91 if err != nil { 92 return nil, 0, err 93 } 94 95 return trun, trunOffset, nil 96 }