Files

133 lines
2.5 KiB
Go

package subgroup
import (
"fmt"
"io"
"github.com/bluenviron/mediamtx/internal/protocols/moq/property"
"github.com/bluenviron/mediamtx/internal/protocols/moq/varint"
)
const (
maxPropsLen = 128 * 1024
maxPayloadSize = 10 * 1024 * 1024
objectStatusEndOfGroup = 0x03
objectStatusEndOfTrack = 0x04
)
// Object is an object of a subgroup stream.
// spec:
// * draft-17, section 10.4.2
// * draft-18/19, section 11.4.2
type Object struct {
IDDelta uint64
Properties property.Properties
Payload []byte
}
func (o *Object) read(r io.Reader, header *Header) error {
var idDelta varint.Varint
if err := idDelta.Read(r); err != nil {
return err
}
o.IDDelta = uint64(idDelta)
if header.Properties {
var propsLen varint.Varint
err := propsLen.Read(r)
if err != nil {
return err
}
if propsLen > 0 {
if propsLen > maxPropsLen {
return fmt.Errorf("properties too large: %d", propsLen)
}
props := make([]byte, propsLen)
_, err = io.ReadFull(r, props)
if err != nil {
return err
}
err = o.Properties.Unmarshal(props)
if err != nil {
return err
}
}
}
var payloadLen varint.Varint
err := payloadLen.Read(r)
if err != nil {
return err
}
if payloadLen == 0 {
var status varint.Varint
if err = status.Read(r); err != nil {
return err
}
if status != objectStatusEndOfGroup && status != objectStatusEndOfTrack {
return fmt.Errorf("unexpected status: 0x%x", status)
}
return nil
}
if payloadLen > maxPayloadSize {
return fmt.Errorf("payload too large: %d", payloadLen)
}
o.Payload = make([]byte, payloadLen)
_, err = io.ReadFull(r, o.Payload)
if err != nil {
return err
}
return nil
}
func (o Object) marshalSize(header *Header) int {
propsFieldSize := 0
if header.Properties {
propsLen := o.Properties.MarshalSize()
propsFieldSize = varint.Varint(propsLen).MarshalSize() + propsLen
}
if len(o.Payload) == 0 {
return varint.Varint(o.IDDelta).MarshalSize() + propsFieldSize + 2
}
return varint.Varint(o.IDDelta).MarshalSize() +
propsFieldSize +
varint.Varint(len(o.Payload)).MarshalSize() +
len(o.Payload)
}
func (o Object) marshalTo(buf []byte, header *Header) int {
n := varint.Varint(o.IDDelta).MarshalTo(buf)
if header.Properties {
propsLen := o.Properties.MarshalSize()
n += varint.Varint(propsLen).MarshalTo(buf[n:])
n += o.Properties.MarshalTo(buf[n:])
}
if len(o.Payload) == 0 {
buf[n] = 0x00
n++
buf[n] = objectStatusEndOfGroup
n++
return n
}
n += varint.Varint(len(o.Payload)).MarshalTo(buf[n:])
n += copy(buf[n:], o.Payload)
return n
}