2021-04-20 01:59:55 +08:00
|
|
|
package fmp4io
|
|
|
|
|
2025-01-24 14:45:45 +08:00
|
|
|
import "git.r-2.top/kunmeng/vdk/utils/bits/pio"
|
2021-04-20 01:59:55 +08:00
|
|
|
|
|
|
|
const SIDX = Tag(0x73696478)
|
|
|
|
|
|
|
|
type SegmentIndex struct {
|
|
|
|
FullAtom
|
|
|
|
ReferenceID uint32
|
|
|
|
TimeScale uint32
|
|
|
|
EarliestPTS uint64
|
|
|
|
FirstOffset uint64
|
|
|
|
References []SegmentReference
|
|
|
|
}
|
|
|
|
|
|
|
|
type SegmentReference struct {
|
|
|
|
ReferencesBox bool
|
|
|
|
ReferencedSize uint32
|
|
|
|
SubsegmentDuration uint32
|
|
|
|
StartsWithSAP bool
|
|
|
|
SAPType uint8
|
|
|
|
SAPDeltaTime uint32
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s SegmentIndex) Tag() Tag {
|
|
|
|
return SIDX
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s SegmentIndex) Len() (n int) {
|
|
|
|
n = s.FullAtom.atomLen()
|
|
|
|
n += 4
|
|
|
|
n += 4
|
|
|
|
if s.Version == 0 {
|
|
|
|
n += 4
|
|
|
|
n += 4
|
|
|
|
} else {
|
|
|
|
n += 8
|
|
|
|
n += 8
|
|
|
|
}
|
|
|
|
n += 2
|
|
|
|
n += 2
|
|
|
|
n += 12 * len(s.References)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s SegmentIndex) Marshal(b []byte) (n int) {
|
|
|
|
n = s.FullAtom.marshalAtom(b, SIDX)
|
|
|
|
pio.PutU32BE(b[n:], s.ReferenceID)
|
|
|
|
n += 4
|
|
|
|
pio.PutU32BE(b[n:], s.TimeScale)
|
|
|
|
n += 4
|
|
|
|
if s.Version == 0 {
|
|
|
|
pio.PutU32BE(b[n:], uint32(s.EarliestPTS))
|
|
|
|
n += 4
|
|
|
|
pio.PutU32BE(b[n:], uint32(s.FirstOffset))
|
|
|
|
n += 4
|
|
|
|
} else {
|
|
|
|
pio.PutU64BE(b[n:], s.EarliestPTS)
|
|
|
|
n += 8
|
|
|
|
pio.PutU64BE(b[n:], s.FirstOffset)
|
|
|
|
n += 8
|
|
|
|
}
|
|
|
|
n += 2
|
|
|
|
pio.PutU16BE(b[n:], uint16(len(s.References)))
|
|
|
|
n += 2
|
|
|
|
for _, ref := range s.References {
|
|
|
|
v := ref.ReferencedSize
|
|
|
|
if ref.ReferencesBox {
|
|
|
|
v |= 1 << 31
|
|
|
|
}
|
|
|
|
pio.PutU32BE(b[n:], v)
|
|
|
|
n += 4
|
|
|
|
pio.PutU32BE(b[n:], ref.SubsegmentDuration)
|
|
|
|
n += 4
|
|
|
|
v = (uint32(ref.SAPType) << 28) | ref.SAPDeltaTime
|
|
|
|
if ref.StartsWithSAP {
|
|
|
|
v |= 1 << 31
|
|
|
|
}
|
|
|
|
pio.PutU32BE(b[n:], v)
|
|
|
|
n += 4
|
|
|
|
}
|
|
|
|
pio.PutU32BE(b, uint32(n))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *SegmentIndex) Unmarshal(b []byte, offset int) (n int, err error) {
|
|
|
|
n, err = s.FullAtom.unmarshalAtom(b, offset)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if len(b) < n+8 {
|
|
|
|
return 0, parseErr("ReferenceID", n+offset, nil)
|
|
|
|
}
|
|
|
|
s.ReferenceID = pio.U32BE(b[n:])
|
|
|
|
n += 4
|
|
|
|
s.TimeScale = pio.U32BE(b[n:])
|
|
|
|
n += 4
|
|
|
|
if s.Version == 0 {
|
|
|
|
if len(b) < n+8 {
|
|
|
|
return 0, parseErr("EarliestPTS", n+offset, nil)
|
|
|
|
}
|
|
|
|
s.EarliestPTS = uint64(pio.U32BE(b[n:]))
|
|
|
|
n += 4
|
|
|
|
s.FirstOffset = uint64(pio.U32BE(b[n:]))
|
|
|
|
n += 4
|
|
|
|
} else {
|
|
|
|
if len(b) < n+16 {
|
|
|
|
return 0, parseErr("EarliestPTS", n+offset, nil)
|
|
|
|
}
|
|
|
|
s.EarliestPTS = pio.U64BE(b[n:])
|
|
|
|
n += 8
|
|
|
|
s.FirstOffset = pio.U64BE(b[n:])
|
|
|
|
n += 8
|
|
|
|
}
|
|
|
|
if len(b) < n+4 {
|
|
|
|
return 0, parseErr("ReferenceCount", n+offset, nil)
|
|
|
|
}
|
|
|
|
n += 2
|
|
|
|
refCount := int(pio.U16BE(b[n:]))
|
|
|
|
n += 2
|
|
|
|
if len(b) < n+(12*refCount) {
|
|
|
|
return 0, parseErr("SegmentReference", n+offset, nil)
|
|
|
|
}
|
|
|
|
s.References = make([]SegmentReference, refCount)
|
|
|
|
for i := range s.References {
|
|
|
|
ref := &s.References[i]
|
|
|
|
refSize := pio.U32BE(b[n:])
|
|
|
|
n += 4
|
|
|
|
if refSize&(1<<31) != 0 {
|
|
|
|
ref.ReferencesBox = true
|
|
|
|
}
|
|
|
|
ref.ReferencedSize = refSize &^ ((1 << 31) - 1)
|
|
|
|
ref.SubsegmentDuration = pio.U32BE(b[n:])
|
|
|
|
n += 4
|
|
|
|
sapDelta := pio.U32BE(b[:n])
|
|
|
|
n += 4
|
|
|
|
if sapDelta&(1<<31) != 0 {
|
|
|
|
ref.StartsWithSAP = true
|
|
|
|
}
|
|
|
|
ref.SAPType = uint8(0x7 & (sapDelta >> 28))
|
|
|
|
ref.SAPDeltaTime = sapDelta &^ ((1 << 28) - 1)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s SegmentIndex) Children() []Atom {
|
|
|
|
return nil
|
|
|
|
}
|