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  }