直播:后台 JWT 推流、前台画中画;WebRTC 服务与 Nginx WebSocket 代理
Made-with: Cursor
This commit is contained in:
161
server/vendor/github.com/pion/rtcp/compound_packet.go
generated
vendored
Normal file
161
server/vendor/github.com/pion/rtcp/compound_packet.go
generated
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package rtcp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// A CompoundPacket is a collection of RTCP packets transmitted as a single packet with
|
||||
// the underlying protocol (for example UDP).
|
||||
//
|
||||
// To maximize the resolution of receiption statistics, the first Packet in a CompoundPacket
|
||||
// must always be either a SenderReport or a ReceiverReport. This is true even if no data
|
||||
// has been sent or received, in which case an empty ReceiverReport must be sent, and even
|
||||
// if the only other RTCP packet in the compound packet is a Goodbye.
|
||||
//
|
||||
// Next, a SourceDescription containing a CNAME item must be included in each CompoundPacket
|
||||
// to identify the source and to begin associating media for purposes such as lip-sync.
|
||||
//
|
||||
// Other RTCP packet types may follow in any order. Packet types may appear more than once.
|
||||
type CompoundPacket []Packet
|
||||
|
||||
// Validate returns an error if this is not an RFC-compliant CompoundPacket.
|
||||
func (c CompoundPacket) Validate() error {
|
||||
if len(c) == 0 {
|
||||
return errEmptyCompound
|
||||
}
|
||||
|
||||
// SenderReport and ReceiverReport are the only types that
|
||||
// are allowed to be the first packet in a compound datagram
|
||||
switch c[0].(type) {
|
||||
case *SenderReport, *ReceiverReport:
|
||||
// ok
|
||||
default:
|
||||
return errBadFirstPacket
|
||||
}
|
||||
|
||||
for _, pkt := range c[1:] {
|
||||
switch p := pkt.(type) {
|
||||
// If the number of RecetpionReports exceeds 31 additional ReceiverReports
|
||||
// can be included here.
|
||||
case *ReceiverReport:
|
||||
continue
|
||||
|
||||
// A SourceDescription containing a CNAME must be included in every
|
||||
// CompoundPacket.
|
||||
case *SourceDescription:
|
||||
var hasCNAME bool
|
||||
for _, c := range p.Chunks {
|
||||
for _, it := range c.Items {
|
||||
if it.Type == SDESCNAME {
|
||||
hasCNAME = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !hasCNAME {
|
||||
return errMissingCNAME
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
// Other packets are not permitted before the CNAME
|
||||
default:
|
||||
return errPacketBeforeCNAME
|
||||
}
|
||||
}
|
||||
|
||||
// CNAME never reached
|
||||
return errMissingCNAME
|
||||
}
|
||||
|
||||
// CNAME returns the CNAME that *must* be present in every CompoundPacket
|
||||
func (c CompoundPacket) CNAME() (string, error) {
|
||||
var err error
|
||||
|
||||
if len(c) < 1 {
|
||||
return "", errEmptyCompound
|
||||
}
|
||||
|
||||
for _, pkt := range c[1:] {
|
||||
sdes, ok := pkt.(*SourceDescription)
|
||||
if ok {
|
||||
for _, c := range sdes.Chunks {
|
||||
for _, it := range c.Items {
|
||||
if it.Type == SDESCNAME {
|
||||
return it.Text, err
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_, ok := pkt.(*ReceiverReport)
|
||||
if !ok {
|
||||
err = errPacketBeforeCNAME
|
||||
}
|
||||
}
|
||||
}
|
||||
return "", errMissingCNAME
|
||||
}
|
||||
|
||||
// Marshal encodes the CompoundPacket as binary.
|
||||
func (c CompoundPacket) Marshal() ([]byte, error) {
|
||||
if err := c.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p := []Packet(c)
|
||||
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)
|
||||
for len(rawData) != 0 {
|
||||
p, processed, err := unmarshal(rawData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out = append(out, p)
|
||||
rawData = rawData[processed:]
|
||||
}
|
||||
*c = out
|
||||
|
||||
return c.Validate()
|
||||
}
|
||||
|
||||
// DestinationSSRC returns the synchronization sources associated with this
|
||||
// CompoundPacket's reception report.
|
||||
func (c CompoundPacket) DestinationSSRC() []uint32 {
|
||||
if len(c) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return c[0].DestinationSSRC()
|
||||
}
|
||||
|
||||
func (c CompoundPacket) String() string {
|
||||
out := "CompoundPacket\n"
|
||||
for _, p := range c {
|
||||
stringer, canString := p.(fmt.Stringer)
|
||||
if canString {
|
||||
out += stringer.String()
|
||||
} else {
|
||||
out += stringify(p)
|
||||
}
|
||||
}
|
||||
out = strings.TrimSuffix(strings.ReplaceAll(out, "\n", "\n\t"), "\t")
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user