mirror of
https://github.com/livekit/livekit.git
synced 2026-03-30 17:45:40 +00:00
421 lines
11 KiB
Go
421 lines
11 KiB
Go
package dependencydescriptor
|
|
|
|
import "errors"
|
|
|
|
type DependencyDescriptorReader struct {
|
|
// Output.
|
|
descriptor *DependencyDescriptor
|
|
|
|
// Values that are needed while reading the descriptor, but can be discarded
|
|
// when reading is complete.
|
|
buffer *BitStreamReader
|
|
frameDependencyTemplateId int
|
|
activeDecodeTargetsPresentFlag bool
|
|
customDtisFlag bool
|
|
customFdiffsFlag bool
|
|
customChainsFlag bool
|
|
structure *FrameDependencyStructure
|
|
}
|
|
|
|
func NewDependencyDescriptorReader(buf []byte, structure *FrameDependencyStructure, descriptor *DependencyDescriptor) *DependencyDescriptorReader {
|
|
buffer := NewBitStreamReader(buf)
|
|
return &DependencyDescriptorReader{
|
|
buffer: buffer,
|
|
descriptor: descriptor,
|
|
structure: structure,
|
|
}
|
|
}
|
|
|
|
func (r *DependencyDescriptorReader) Parse() (int, error) {
|
|
if err := r.readMandatoryFields(); err != nil {
|
|
return 0, err
|
|
}
|
|
if len(r.buffer.buf) > 3 {
|
|
err := r.readExtendedFields()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
}
|
|
|
|
if r.descriptor.AttachedStructure != nil {
|
|
r.structure = r.descriptor.AttachedStructure
|
|
}
|
|
|
|
if r.structure == nil {
|
|
r.buffer.Invalidate()
|
|
return 0, errors.New("DependencyDescriptorReader: Structure is nil")
|
|
}
|
|
|
|
if r.activeDecodeTargetsPresentFlag {
|
|
bitmask, err := r.buffer.ReadBits(r.structure.NumDecodeTargets)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
mask := uint32(bitmask)
|
|
r.descriptor.ActiveDecodeTargetsBitmask = &mask
|
|
}
|
|
|
|
err := r.readFrameDependencyDefinition()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return r.buffer.ReadedBytes(), nil
|
|
}
|
|
|
|
func (r *DependencyDescriptorReader) readMandatoryFields() error {
|
|
var err error
|
|
r.descriptor.FirstPacketInFrame, err = r.buffer.ReadBool()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
r.descriptor.LastPacketInFrame, err = r.buffer.ReadBool()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
templateID, err := r.buffer.ReadBits(6)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r.frameDependencyTemplateId = int(templateID)
|
|
|
|
frameNumber, err := r.buffer.ReadBits(16)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r.descriptor.FrameNumber = uint16(frameNumber)
|
|
return nil
|
|
}
|
|
|
|
func (r *DependencyDescriptorReader) readExtendedFields() error {
|
|
|
|
templateDependencyStructurePresentFlag, err := r.buffer.ReadBool()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
flag, err := r.buffer.ReadBool()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r.activeDecodeTargetsPresentFlag = flag
|
|
|
|
flag, err = r.buffer.ReadBool()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r.customDtisFlag = flag
|
|
|
|
flag, err = r.buffer.ReadBool()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r.customFdiffsFlag = flag
|
|
|
|
flag, err = r.buffer.ReadBool()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r.customChainsFlag = flag
|
|
|
|
if templateDependencyStructurePresentFlag {
|
|
err = r.readTemplateDependencyStructure()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if r.descriptor.AttachedStructure == nil {
|
|
return errors.New("DependencyDescriptorReader: has templateDependencyStructurePresentFlag but AttachedStructure is nil")
|
|
}
|
|
bitmask := uint32((uint64(1) << r.descriptor.AttachedStructure.NumDecodeTargets) - 1)
|
|
r.descriptor.ActiveDecodeTargetsBitmask = &bitmask
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *DependencyDescriptorReader) readTemplateDependencyStructure() error {
|
|
r.descriptor.AttachedStructure = &FrameDependencyStructure{}
|
|
structureId, err := r.buffer.ReadBits(6)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r.descriptor.AttachedStructure.StructureId = int(structureId)
|
|
|
|
numDecodeTargets, err := r.buffer.ReadBits(5)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r.descriptor.AttachedStructure.NumDecodeTargets = int(numDecodeTargets) + 1
|
|
|
|
if err = r.readTemplateLayers(); err != nil {
|
|
return err
|
|
}
|
|
if err = r.readTemplateDtis(); err != nil {
|
|
return err
|
|
}
|
|
if err = r.readTemplateFdiffs(); err != nil {
|
|
return err
|
|
}
|
|
if err = r.readTemplateChains(); err != nil {
|
|
return err
|
|
}
|
|
|
|
flag, err := r.buffer.ReadBool()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if flag {
|
|
return r.readResolutions()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type nextLayerIdcType int
|
|
|
|
const (
|
|
sameLayer nextLayerIdcType = iota
|
|
nextTemporalLayer
|
|
nextSpatialLayer
|
|
noMoreLayer
|
|
invalidLayer
|
|
)
|
|
|
|
func (r *DependencyDescriptorReader) readTemplateLayers() error {
|
|
var (
|
|
templates []*FrameDependencyTemplate
|
|
temporalId, spatialId int
|
|
nextLayerIdc nextLayerIdcType
|
|
)
|
|
for {
|
|
if len(templates) == MaxTemplates {
|
|
return errors.New("DependencyDescriptorReader: too many templates")
|
|
}
|
|
|
|
var lastTemplate FrameDependencyTemplate
|
|
templates = append(templates, &lastTemplate)
|
|
lastTemplate.TemporalId = temporalId
|
|
lastTemplate.SpatialId = spatialId
|
|
|
|
idc, err := r.buffer.ReadBits(2)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
nextLayerIdc = nextLayerIdcType(idc)
|
|
|
|
if nextLayerIdc == nextTemporalLayer {
|
|
temporalId++
|
|
if temporalId >= MaxTemporalIds {
|
|
return errors.New("DependencyDescriptorReader: too many temporal layers")
|
|
}
|
|
} else if nextLayerIdc == nextSpatialLayer {
|
|
spatialId++
|
|
temporalId = 0
|
|
if spatialId >= MaxSpatialIds {
|
|
return errors.New("DependencyDescriptorReader: too many spatial layers")
|
|
}
|
|
}
|
|
|
|
if !(nextLayerIdc != noMoreLayer && r.buffer.Ok()) {
|
|
break
|
|
}
|
|
}
|
|
|
|
r.descriptor.AttachedStructure.Templates = templates
|
|
return nil
|
|
}
|
|
|
|
func (r *DependencyDescriptorReader) readTemplateDtis() error {
|
|
structure := r.descriptor.AttachedStructure
|
|
for _, template := range structure.Templates {
|
|
if len(template.DecodeTargetIndications) < structure.NumDecodeTargets {
|
|
template.DecodeTargetIndications = append(template.DecodeTargetIndications, make([]DecodeTargetIndication, structure.NumDecodeTargets-len(template.DecodeTargetIndications))...)
|
|
} else {
|
|
template.DecodeTargetIndications = template.DecodeTargetIndications[:structure.NumDecodeTargets]
|
|
}
|
|
|
|
for i := range template.DecodeTargetIndications {
|
|
indication, err := r.buffer.ReadBits(2)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
template.DecodeTargetIndications[i] = DecodeTargetIndication(indication)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *DependencyDescriptorReader) readTemplateFdiffs() error {
|
|
for _, template := range r.descriptor.AttachedStructure.Templates {
|
|
for {
|
|
fdiffFollow, err := r.buffer.ReadBool()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !fdiffFollow {
|
|
break
|
|
}
|
|
fDiffMinusOne, err := r.buffer.ReadBits(4)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
template.FrameDiffs = append(template.FrameDiffs, int(fDiffMinusOne+1))
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *DependencyDescriptorReader) readTemplateChains() error {
|
|
structure := r.descriptor.AttachedStructure
|
|
|
|
numChains, err := r.buffer.ReadNonSymmetric(uint32(structure.NumDecodeTargets) + 1)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
structure.NumChains = int(numChains)
|
|
if structure.NumChains == 0 {
|
|
return nil
|
|
}
|
|
|
|
for i := 0; i < structure.NumDecodeTargets; i++ {
|
|
protectedByChain, err := r.buffer.ReadNonSymmetric(uint32(structure.NumChains))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
structure.DecodeTargetProtectedByChain = append(structure.DecodeTargetProtectedByChain, int(protectedByChain))
|
|
}
|
|
|
|
for _, frameTemplate := range structure.Templates {
|
|
for chainId := 0; chainId < structure.NumChains; chainId++ {
|
|
chainDiff, err := r.buffer.ReadBits(4)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
frameTemplate.ChainDiffs = append(frameTemplate.ChainDiffs, int(chainDiff))
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *DependencyDescriptorReader) readResolutions() error {
|
|
structure := r.descriptor.AttachedStructure
|
|
// The way templates are bitpacked, they are always ordered by spatial_id.
|
|
spatialLayers := structure.Templates[len(structure.Templates)-1].SpatialId + 1
|
|
for sid := 0; sid < spatialLayers; sid++ {
|
|
widthMinus1, err := r.buffer.ReadBits(16)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
heightMinus1, err := r.buffer.ReadBits(16)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
structure.Resolutions = append(structure.Resolutions, RenderResolution{
|
|
Width: int(widthMinus1 + 1),
|
|
Height: int(heightMinus1 + 1),
|
|
})
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *DependencyDescriptorReader) readFrameDependencyDefinition() error {
|
|
templateIndex := (r.frameDependencyTemplateId + MaxTemplates - r.structure.StructureId) % MaxTemplates
|
|
|
|
if templateIndex >= len(r.structure.Templates) {
|
|
r.buffer.Invalidate()
|
|
return errors.New("DependencyDescriptorReader: invalid template index")
|
|
}
|
|
|
|
// Copy all the fields from the matching template
|
|
r.descriptor.FrameDependencies = r.structure.Templates[templateIndex].Clone()
|
|
|
|
if r.customDtisFlag {
|
|
err := r.readFrameDtis()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if r.customFdiffsFlag {
|
|
err := r.readFrameFdiffs()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if r.customChainsFlag {
|
|
err := r.readFrameChains()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if len(r.structure.Resolutions) == 0 {
|
|
r.descriptor.Resolution = nil
|
|
} else {
|
|
// Format guarantees that if there were resolutions in the last structure,
|
|
// then each spatial layer got one.
|
|
if r.descriptor.FrameDependencies.SpatialId >= len(r.structure.Resolutions) {
|
|
r.buffer.Invalidate()
|
|
return errors.New("DependencyDescriptorReader: invalid spatial layer, should be less than the number of resolutions")
|
|
}
|
|
res := r.structure.Resolutions[r.descriptor.FrameDependencies.SpatialId]
|
|
r.descriptor.Resolution = &res
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *DependencyDescriptorReader) readFrameDtis() error {
|
|
if len(r.descriptor.FrameDependencies.DecodeTargetIndications) != r.structure.NumDecodeTargets {
|
|
return errors.New("DependencyDescriptorReader: decode target indications length mismatch with structure num decode targets")
|
|
}
|
|
|
|
for i := range r.descriptor.FrameDependencies.DecodeTargetIndications {
|
|
indication, err := r.buffer.ReadBits(2)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r.descriptor.FrameDependencies.DecodeTargetIndications[i] = DecodeTargetIndication(indication)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *DependencyDescriptorReader) readFrameFdiffs() error {
|
|
|
|
r.descriptor.FrameDependencies.FrameDiffs = r.descriptor.FrameDependencies.FrameDiffs[:0]
|
|
for {
|
|
nexFdiffSize, err := r.buffer.ReadBits(2)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if nexFdiffSize == 0 {
|
|
break
|
|
}
|
|
fDiffMinusOne, err := r.buffer.ReadBits(int(nexFdiffSize * 4))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r.descriptor.FrameDependencies.FrameDiffs = append(r.descriptor.FrameDependencies.FrameDiffs, int(fDiffMinusOne+1))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *DependencyDescriptorReader) readFrameChains() error {
|
|
if len(r.descriptor.FrameDependencies.ChainDiffs) != r.structure.NumChains {
|
|
return errors.New("DependencyDescriptorReader: chain diffs length mismatch with structure num chains")
|
|
}
|
|
|
|
for i := range r.descriptor.FrameDependencies.ChainDiffs {
|
|
chainDiff, err := r.buffer.ReadBits(8)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r.descriptor.FrameDependencies.ChainDiffs[i] = int(chainDiff)
|
|
}
|
|
return nil
|
|
}
|