diff --git a/compound_packet.go b/compound_packet.go index 9407258..a621c61 100644 --- a/compound_packet.go +++ b/compound_packet.go @@ -110,6 +110,15 @@ func (c CompoundPacket) Marshal() ([]byte, error) { return Marshal(p) } +// MarshalSize returns the size of the packet once marshaled +func (c CompoundPacket) MarshalSize() int { + l := 0 + for _, p := range c { + l += p.MarshalSize() + } + return l +} + // Unmarshal decodes a CompoundPacket from binary. func (c *CompoundPacket) Unmarshal(rawData []byte) error { out := make(CompoundPacket, 0) diff --git a/extended_report.go b/extended_report.go index 9e39c7b..db7ca41 100644 --- a/extended_report.go +++ b/extended_report.go @@ -545,6 +545,11 @@ func (b *UnknownReportBlock) setupBlockHeader() { func (b *UnknownReportBlock) unpackBlockHeader() { } +// MarshalSize returns the size of the packet once marshaled +func (x ExtendedReport) MarshalSize() int { + return wireSize(x) +} + // Marshal encodes the ExtendedReport in binary func (x ExtendedReport) Marshal() ([]byte, error) { for _, p := range x.Reports { diff --git a/full_intra_request.go b/full_intra_request.go index e778e6d..7c67c50 100644 --- a/full_intra_request.go +++ b/full_intra_request.go @@ -88,11 +88,12 @@ func (p *FullIntraRequest) Header() Header { return Header{ Count: FormatFIR, Type: TypePayloadSpecificFeedback, - Length: uint16((p.len() / 4) - 1), + Length: uint16((p.MarshalSize() / 4) - 1), } } -func (p *FullIntraRequest) len() int { +// MarshalSize returns the size of the packet once marshaled +func (p *FullIntraRequest) MarshalSize() int { return headerLength + firOffset + len(p.FIR)*8 } diff --git a/goodbye.go b/goodbye.go index 7879fb9..bda1785 100644 --- a/goodbye.go +++ b/goodbye.go @@ -32,7 +32,7 @@ func (g Goodbye) Marshal() ([]byte, error) { * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ - rawPacket := make([]byte, g.len()) + rawPacket := make([]byte, g.MarshalSize()) packetBody := rawPacket[headerLength:] if len(g.Sources) > countMax { @@ -126,11 +126,12 @@ func (g *Goodbye) Header() Header { Padding: false, Count: uint8(len(g.Sources)), Type: TypeGoodbye, - Length: uint16((g.len() / 4) - 1), + Length: uint16((g.MarshalSize() / 4) - 1), } } -func (g *Goodbye) len() int { +// MarshalSize returns the size of the packet once marshaled +func (g *Goodbye) MarshalSize() int { srcsLength := len(g.Sources) * ssrcLength reasonLength := len(g.Reason) + 1 diff --git a/packet.go b/packet.go index fc937c1..cdb83c0 100644 --- a/packet.go +++ b/packet.go @@ -10,6 +10,7 @@ type Packet interface { Marshal() ([]byte, error) Unmarshal(rawPacket []byte) error + MarshalSize() int } // Unmarshal takes an entire udp datagram (which may consist of multiple RTCP packets) and diff --git a/picture_loss_indication.go b/picture_loss_indication.go index 40bd7bc..56a7de2 100644 --- a/picture_loss_indication.go +++ b/picture_loss_indication.go @@ -29,7 +29,7 @@ func (p PictureLossIndication) Marshal() ([]byte, error) { * * The semantics of this FB message is independent of the payload type. */ - rawPacket := make([]byte, p.len()) + rawPacket := make([]byte, p.MarshalSize()) packetBody := rawPacket[headerLength:] binary.BigEndian.PutUint32(packetBody, p.SenderSSRC) @@ -78,7 +78,8 @@ func (p *PictureLossIndication) Header() Header { } } -func (p *PictureLossIndication) len() int { +// MarshalSize returns the size of the packet once marshaled +func (p *PictureLossIndication) MarshalSize() int { return headerLength + ssrcLength*2 } diff --git a/rapid_resynchronization_request.go b/rapid_resynchronization_request.go index 48bbd4a..dc67d49 100644 --- a/rapid_resynchronization_request.go +++ b/rapid_resynchronization_request.go @@ -35,7 +35,7 @@ func (p RapidResynchronizationRequest) Marshal() ([]byte, error) { * * The semantics of this FB message is independent of the payload type. */ - rawPacket := make([]byte, p.len()) + rawPacket := make([]byte, p.MarshalSize()) packetBody := rawPacket[headerLength:] binary.BigEndian.PutUint32(packetBody, p.SenderSSRC) @@ -70,7 +70,8 @@ func (p *RapidResynchronizationRequest) Unmarshal(rawPacket []byte) error { return nil } -func (p *RapidResynchronizationRequest) len() int { +// MarshalSize returns the size of the packet once marshaled +func (p *RapidResynchronizationRequest) MarshalSize() int { return headerLength + rrrHeaderLength } diff --git a/raw_packet.go b/raw_packet.go index 291ee36..eafb034 100644 --- a/raw_packet.go +++ b/raw_packet.go @@ -43,3 +43,8 @@ func (r RawPacket) String() string { out := fmt.Sprintf("RawPacket: %v", ([]byte)(r)) return out } + +// MarshalSize returns the size of the packet once marshaled +func (r RawPacket) MarshalSize() int { + return len(r) +} diff --git a/receiver_estimated_maximum_bitrate.go b/receiver_estimated_maximum_bitrate.go index bd70973..7be57e6 100644 --- a/receiver_estimated_maximum_bitrate.go +++ b/receiver_estimated_maximum_bitrate.go @@ -42,9 +42,8 @@ func (p ReceiverEstimatedMaximumBitrate) Marshal() (buf []byte, err error) { return buf, nil } -// MarshalSize returns the size of the packet when marshaled. -// This can be used in conjunction with `MarshalTo` to avoid allocations. -func (p ReceiverEstimatedMaximumBitrate) MarshalSize() (n int) { +// MarshalSize returns the size of the packet once marshaled +func (p ReceiverEstimatedMaximumBitrate) MarshalSize() int { return 20 + 4*len(p.SSRCs) } diff --git a/receiver_report.go b/receiver_report.go index 0e2bb1f..e917702 100644 --- a/receiver_report.go +++ b/receiver_report.go @@ -58,7 +58,7 @@ func (r ReceiverReport) Marshal() ([]byte, error) { * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ - rawPacket := make([]byte, r.len()) + rawPacket := make([]byte, r.MarshalSize()) packetBody := rawPacket[headerLength:] binary.BigEndian.PutUint32(packetBody, r.SSRC) @@ -157,7 +157,8 @@ func (r *ReceiverReport) Unmarshal(rawPacket []byte) error { return nil } -func (r *ReceiverReport) len() int { +// MarshalSize returns the size of the packet once marshaled +func (r *ReceiverReport) MarshalSize() int { repsLength := 0 for _, rep := range r.Reports { repsLength += rep.len() @@ -170,7 +171,7 @@ func (r *ReceiverReport) Header() Header { return Header{ Count: uint8(len(r.Reports)), Type: TypeReceiverReport, - Length: uint16((r.len()/4)-1) + uint16(getPadding(len(r.ProfileExtensions))), + Length: uint16((r.MarshalSize()/4)-1) + uint16(getPadding(len(r.ProfileExtensions))), } } diff --git a/rfc8888.go b/rfc8888.go index 9a3e337..544c6e3 100644 --- a/rfc8888.go +++ b/rfc8888.go @@ -94,6 +94,11 @@ func (b CCFeedbackReport) DestinationSSRC() []uint32 { // Len returns the length of the report in bytes func (b *CCFeedbackReport) Len() int { + return b.MarshalSize() +} + +// MarshalSize returns the size of the packet once marshaled +func (b *CCFeedbackReport) MarshalSize() int { n := 0 for _, block := range b.ReportBlocks { n += block.len() @@ -107,7 +112,7 @@ func (b *CCFeedbackReport) Header() Header { Padding: false, Count: FormatCCFB, Type: TypeTransportSpecificFeedback, - Length: uint16(b.Len()/4 - 1), + Length: uint16(b.MarshalSize()/4 - 1), } } diff --git a/sender_report.go b/sender_report.go index dc5138e..aaee0ee 100644 --- a/sender_report.go +++ b/sender_report.go @@ -96,7 +96,7 @@ func (r SenderReport) Marshal() ([]byte, error) { * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ - rawPacket := make([]byte, r.len()) + rawPacket := make([]byte, r.MarshalSize()) packetBody := rawPacket[headerLength:] binary.BigEndian.PutUint32(packetBody[srSSRCOffset:], r.SSRC) @@ -228,7 +228,8 @@ func (r *SenderReport) DestinationSSRC() []uint32 { return out } -func (r *SenderReport) len() int { +// MarshalSize returns the size of the packet once marshaled +func (r *SenderReport) MarshalSize() int { repsLength := 0 for _, rep := range r.Reports { repsLength += rep.len() @@ -241,7 +242,7 @@ func (r *SenderReport) Header() Header { return Header{ Count: uint8(len(r.Reports)), Type: TypeSenderReport, - Length: uint16((r.len() / 4) - 1), + Length: uint16((r.MarshalSize() / 4) - 1), } } diff --git a/slice_loss_indication.go b/slice_loss_indication.go index 73926dd..014fcb7 100644 --- a/slice_loss_indication.go +++ b/slice_loss_indication.go @@ -93,7 +93,8 @@ func (p *SliceLossIndication) Unmarshal(rawPacket []byte) error { return nil } -func (p *SliceLossIndication) len() int { +// MarshalSize returns the size of the packet once marshaled +func (p *SliceLossIndication) MarshalSize() int { return headerLength + sliOffset + (len(p.SLI) * 4) } @@ -102,7 +103,7 @@ func (p *SliceLossIndication) Header() Header { return Header{ Count: FormatSLI, Type: TypeTransportSpecificFeedback, - Length: uint16((p.len() / 4) - 1), + Length: uint16((p.MarshalSize() / 4) - 1), } } diff --git a/source_description.go b/source_description.go index 28fccdb..fc29d8e 100644 --- a/source_description.go +++ b/source_description.go @@ -97,7 +97,7 @@ func (s SourceDescription) Marshal() ([]byte, error) { * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ */ - rawPacket := make([]byte, s.len()) + rawPacket := make([]byte, s.MarshalSize()) packetBody := rawPacket[headerLength:] chunkOffset := 0 @@ -169,7 +169,8 @@ func (s *SourceDescription) Unmarshal(rawPacket []byte) error { return nil } -func (s *SourceDescription) len() int { +// MarshalSize returns the size of the packet once marshaled +func (s *SourceDescription) MarshalSize() int { chunksLength := 0 for _, c := range s.Chunks { chunksLength += c.len() @@ -182,7 +183,7 @@ func (s *SourceDescription) Header() Header { return Header{ Count: uint8(len(s.Chunks)), Type: TypeSourceDescription, - Length: uint16((s.len() / 4) - 1), + Length: uint16((s.MarshalSize() / 4) - 1), } } @@ -251,7 +252,7 @@ func (s *SourceDescriptionChunk) Unmarshal(rawPacket []byte) error { return err } s.Items = append(s.Items, it) - i += it.len() + i += it.Len() } return errPacketTooShort @@ -260,7 +261,7 @@ func (s *SourceDescriptionChunk) Unmarshal(rawPacket []byte) error { func (s SourceDescriptionChunk) len() int { chunkLen := sdesSourceLen for _, it := range s.Items { - chunkLen += it.len() + chunkLen += it.Len() } chunkLen += sdesTypeLen // for terminating null octet @@ -280,7 +281,8 @@ type SourceDescriptionItem struct { Text string } -func (s SourceDescriptionItem) len() int { +// Len returns the length of the SourceDescriptionItem when encoded as binary. +func (s SourceDescriptionItem) Len() int { /* * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 diff --git a/transport_layer_cc.go b/transport_layer_cc.go index ce2ecaa..55b2162 100644 --- a/transport_layer_cc.go +++ b/transport_layer_cc.go @@ -363,13 +363,18 @@ func (t *TransportLayerCC) packetLen() uint16 { // Len return total bytes with padding func (t *TransportLayerCC) Len() uint16 { + return uint16(t.MarshalSize()) +} + +// MarshalSize returns the size of the packet once marshaled +func (t *TransportLayerCC) MarshalSize() int { n := t.packetLen() // has padding if n%4 != 0 { n = (n/4 + 1) * 4 } - return n + return int(n) } func (t TransportLayerCC) String() string { @@ -399,7 +404,7 @@ func (t TransportLayerCC) Marshal() ([]byte, error) { return nil, err } - payload := make([]byte, t.Len()-headerLength) + payload := make([]byte, t.MarshalSize()-headerLength) binary.BigEndian.PutUint32(payload, t.SenderSSRC) binary.BigEndian.PutUint32(payload[4:], t.MediaSSRC) binary.BigEndian.PutUint16(payload[baseSequenceNumberOffset:], t.BaseSequenceNumber) @@ -430,7 +435,7 @@ func (t TransportLayerCC) Marshal() ([]byte, error) { } if t.Header.Padding { - payload[len(payload)-1] = uint8(t.Len() - t.packetLen()) + payload[len(payload)-1] = uint8(t.MarshalSize() - int(t.packetLen())) } return append(header, payload...), nil diff --git a/transport_layer_nack.go b/transport_layer_nack.go index 3d22801..802b915 100644 --- a/transport_layer_nack.go +++ b/transport_layer_nack.go @@ -151,7 +151,8 @@ func (p *TransportLayerNack) Unmarshal(rawPacket []byte) error { return nil } -func (p *TransportLayerNack) len() int { +// MarshalSize returns the size of the packet once marshaled +func (p *TransportLayerNack) MarshalSize() int { return headerLength + nackOffset + (len(p.Nacks) * 4) } @@ -160,7 +161,7 @@ func (p *TransportLayerNack) Header() Header { return Header{ Count: FormatTLN, Type: TypeTransportSpecificFeedback, - Length: uint16((p.len() / 4) - 1), + Length: uint16((p.MarshalSize() / 4) - 1), } }