mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
For regression test, add srs-bench to 3rdparty
This commit is contained in:
parent
de87dd427d
commit
876210f6c9
1158 changed files with 256967 additions and 3 deletions
24
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/.gitignore
generated
vendored
Normal file
24
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
### JetBrains IDE ###
|
||||
#####################
|
||||
.idea/
|
||||
|
||||
### Emacs Temporary Files ###
|
||||
#############################
|
||||
*~
|
||||
|
||||
### Folders ###
|
||||
###############
|
||||
bin/
|
||||
vendor/
|
||||
node_modules/
|
||||
|
||||
### Files ###
|
||||
#############
|
||||
*.ivf
|
||||
*.ogg
|
||||
tags
|
||||
cover.out
|
||||
*.sw[poe]
|
||||
*.wasm
|
||||
examples/sfu-ws/cert.pem
|
||||
examples/sfu-ws/key.pem
|
89
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/.golangci.yml
generated
vendored
Normal file
89
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/.golangci.yml
generated
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
linters-settings:
|
||||
govet:
|
||||
check-shadowing: true
|
||||
misspell:
|
||||
locale: US
|
||||
exhaustive:
|
||||
default-signifies-exhaustive: true
|
||||
gomodguard:
|
||||
blocked:
|
||||
modules:
|
||||
- github.com/pkg/errors:
|
||||
recommendations:
|
||||
- errors
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers
|
||||
- bodyclose # checks whether HTTP response body is closed successfully
|
||||
- deadcode # Finds unused code
|
||||
- depguard # Go linter that checks if package imports are in a list of acceptable packages
|
||||
- dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f())
|
||||
- dupl # Tool for code clone detection
|
||||
- errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases
|
||||
- exhaustive # check exhaustiveness of enum switch statements
|
||||
- exportloopref # checks for pointers to enclosing loop variables
|
||||
- gci # Gci control golang package import order and make it always deterministic.
|
||||
- gochecknoglobals # Checks that no globals are present in Go code
|
||||
- gochecknoinits # Checks that no init functions are present in Go code
|
||||
- gocognit # Computes and checks the cognitive complexity of functions
|
||||
- goconst # Finds repeated strings that could be replaced by a constant
|
||||
- gocritic # The most opinionated Go source code linter
|
||||
- godox # Tool for detection of FIXME, TODO and other comment keywords
|
||||
- goerr113 # Golang linter to check the errors handling expressions
|
||||
- gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification
|
||||
- gofumpt # Gofumpt checks whether code was gofumpt-ed.
|
||||
- goheader # Checks is file header matches to pattern
|
||||
- goimports # Goimports does everything that gofmt does. Additionally it checks unused imports
|
||||
- golint # Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes
|
||||
- gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations.
|
||||
- goprintffuncname # Checks that printf-like functions are named with `f` at the end
|
||||
- gosec # Inspects source code for security problems
|
||||
- gosimple # Linter for Go source code that specializes in simplifying a code
|
||||
- govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string
|
||||
- ineffassign # Detects when assignments to existing variables are not used
|
||||
- misspell # Finds commonly misspelled English words in comments
|
||||
- nakedret # Finds naked returns in functions greater than a specified function length
|
||||
- noctx # noctx finds sending http request without context.Context
|
||||
- scopelint # Scopelint checks for unpinned variables in go programs
|
||||
- staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks
|
||||
- structcheck # Finds unused struct fields
|
||||
- stylecheck # Stylecheck is a replacement for golint
|
||||
- typecheck # Like the front-end of a Go compiler, parses and type-checks Go code
|
||||
- unconvert # Remove unnecessary type conversions
|
||||
- unparam # Reports unused function parameters
|
||||
- unused # Checks Go code for unused constants, variables, functions and types
|
||||
- varcheck # Finds unused global variables and constants
|
||||
- whitespace # Tool for detection of leading and trailing whitespace
|
||||
disable:
|
||||
- funlen # Tool for detection of long functions
|
||||
- gocyclo # Computes and checks the cyclomatic complexity of functions
|
||||
- godot # Check if comments end in a period
|
||||
- gomnd # An analyzer to detect magic numbers.
|
||||
- lll # Reports long lines
|
||||
- maligned # Tool to detect Go structs that would take less memory if their fields were sorted
|
||||
- nestif # Reports deeply nested if statements
|
||||
- nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity
|
||||
- nolintlint # Reports ill-formed or insufficient nolint directives
|
||||
- prealloc # Finds slice declarations that could potentially be preallocated
|
||||
- rowserrcheck # checks whether Err of rows is checked successfully
|
||||
- sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed.
|
||||
- testpackage # linter that makes you use a separate _test package
|
||||
- wsl # Whitespace Linter - Forces you to use empty lines!
|
||||
|
||||
issues:
|
||||
exclude-use-default: false
|
||||
exclude-rules:
|
||||
# Allow complex tests, better to be self contained
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- gocognit
|
||||
|
||||
# Allow complex main function in examples
|
||||
- path: examples
|
||||
text: "of func `main` is high"
|
||||
linters:
|
||||
- gocognit
|
||||
|
||||
run:
|
||||
skip-dirs-use-default: false
|
21
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/LICENSE
generated
vendored
Normal file
21
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2018
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
49
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/README.md
generated
vendored
Normal file
49
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/README.md
generated
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
<h1 align="center">
|
||||
<br>
|
||||
Pion RTCP
|
||||
<br>
|
||||
</h1>
|
||||
<h4 align="center">A Go implementation of RTCP</h4>
|
||||
<p align="center">
|
||||
<a href="https://pion.ly"><img src="https://img.shields.io/badge/pion-rtcp-gray.svg?longCache=true&colorB=brightgreen" alt="Pion RTCP"></a>
|
||||
<a href="https://sourcegraph.com/github.com/pion/rtcp?badge"><img src="https://sourcegraph.com/github.com/pion/rtcp/-/badge.svg" alt="Sourcegraph Widget"></a>
|
||||
<a href="https://pion.ly/slack"><img src="https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=brightgreen" alt="Slack Widget"></a>
|
||||
<br>
|
||||
<a href="https://travis-ci.org/pion/rtcp"><img src="https://travis-ci.org/pion/rtcp.svg?branch=master" alt="Build Status"></a>
|
||||
<a href="https://pkg.go.dev/github.com/pion/rtcp"><img src="https://godoc.org/github.com/pion/rtcp?status.svg" alt="GoDoc"></a>
|
||||
<a href="https://codecov.io/gh/pion/rtcp"><img src="https://codecov.io/gh/pion/rtcp/branch/master/graph/badge.svg" alt="Coverage Status"></a>
|
||||
<a href="https://goreportcard.com/report/github.com/pion/rtcp"><img src="https://goreportcard.com/badge/github.com/pion/rtcp" alt="Go Report Card"></a>
|
||||
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
|
||||
</p>
|
||||
<br>
|
||||
|
||||
See [DESIGN.md](DESIGN.md) for an overview of features and future goals.
|
||||
|
||||
### Roadmap
|
||||
The library is used as a part of our WebRTC implementation. Please refer to that [roadmap](https://github.com/pion/webrtc/issues/9) to track our major milestones.
|
||||
|
||||
### Community
|
||||
Pion has an active community on the [Golang Slack](https://invite.slack.golangbridge.org/). Sign up and join the **#pion** channel for discussions and support. You can also use [Pion mailing list](https://groups.google.com/forum/#!forum/pion).
|
||||
|
||||
We are always looking to support **your projects**. Please reach out if you have something to build!
|
||||
|
||||
If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly)
|
||||
|
||||
### Contributing
|
||||
Check out the **[contributing wiki](https://github.com/pion/webrtc/wiki/Contributing)** to join the group of amazing people making this project possible:
|
||||
|
||||
* [Max Hawkins](https://github.com/maxhawkins) - *Original Author*
|
||||
* [Woodrow Douglass](https://github.com/wdouglass) *RTCP, RTP improvements, G.722 support, Bugfixes*
|
||||
* [Sean DuBois](https://github.com/Sean-Der) - *Linter fixes*
|
||||
* [adwpc](https://github.com/adwpc)
|
||||
* [Luke Curley](https://github.com/kixelated)
|
||||
* [Hugo Arregui](https://github.com/hugoArregui)
|
||||
* [Atsushi Watanabe](https://github.com/at-wat)
|
||||
* [Juliusz Chroboczek](https://github.com/jech)
|
||||
* [Gabor Pongracz](https://github.com/pongraczgabor87)
|
||||
* [Simone Gotti](https://github.com/sgotti)
|
||||
* [lllf](https://github.com/LittleLightLittleFire)
|
||||
* [cnderrauber](https://github.com/cnderrauber)
|
||||
|
||||
### License
|
||||
MIT License - see [LICENSE](LICENSE) for full text
|
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/codecov.yml
generated
vendored
Normal file
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/codecov.yml
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
#
|
||||
# DO NOT EDIT THIS FILE
|
||||
#
|
||||
# It is automatically copied from https://github.com/pion/.goassets repository.
|
||||
#
|
||||
|
||||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
# Allow decreasing 2% of total coverage to avoid noise.
|
||||
threshold: 2%
|
||||
patch:
|
||||
default:
|
||||
target: 70%
|
||||
only_pulls: true
|
||||
|
||||
ignore:
|
||||
- "examples/*"
|
||||
- "examples/**/*"
|
136
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/compound_packet.go
generated
vendored
Normal file
136
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/compound_packet.go
generated
vendored
Normal file
|
@ -0,0 +1,136 @@
|
|||
package rtcp
|
||||
|
||||
// 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
|
||||
|
||||
var _ Packet = (*CompoundPacket)(nil) // assert is a 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)
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
if err := c.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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()
|
||||
}
|
39
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/doc.go
generated
vendored
Normal file
39
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
Package rtcp implements encoding and decoding of RTCP packets according to RFCs 3550 and 5506.
|
||||
|
||||
RTCP is a sister protocol of the Real-time Transport Protocol (RTP). Its basic functionality
|
||||
and packet structure is defined in RFC 3550. RTCP provides out-of-band statistics and control
|
||||
information for an RTP session. It partners with RTP in the delivery and packaging of multimedia data,
|
||||
but does not transport any media data itself.
|
||||
|
||||
The primary function of RTCP is to provide feedback on the quality of service (QoS)
|
||||
in media distribution by periodically sending statistics information such as transmitted octet
|
||||
and packet counts, packet loss, packet delay variation, and round-trip delay time to participants
|
||||
in a streaming multimedia session. An application may use this information to control quality of
|
||||
service parameters, perhaps by limiting flow, or using a different codec.
|
||||
|
||||
Decoding RTCP packets:
|
||||
|
||||
pkt, err := rtcp.Unmarshal(rtcpData)
|
||||
// ...
|
||||
|
||||
switch p := pkt.(type) {
|
||||
case *rtcp.CompoundPacket:
|
||||
...
|
||||
case *rtcp.PictureLossIndication:
|
||||
...
|
||||
default:
|
||||
...
|
||||
}
|
||||
|
||||
Encoding RTCP packets:
|
||||
|
||||
pkt := &rtcp.PictureLossIndication{
|
||||
SenderSSRC: senderSSRC,
|
||||
MediaSSRC: mediaSSRC
|
||||
}
|
||||
pliData, err := pkt.Marshal()
|
||||
// ...
|
||||
|
||||
*/
|
||||
package rtcp
|
30
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/errors.go
generated
vendored
Normal file
30
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/errors.go
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
package rtcp
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
errWrongMarshalSize = errors.New("rtcp: wrong marshal size")
|
||||
errInvalidTotalLost = errors.New("rtcp: invalid total lost count")
|
||||
errInvalidHeader = errors.New("rtcp: invalid header")
|
||||
errEmptyCompound = errors.New("rtcp: empty compound packet")
|
||||
errBadFirstPacket = errors.New("rtcp: first packet in compound must be SR or RR")
|
||||
errMissingCNAME = errors.New("rtcp: compound missing SourceDescription with CNAME")
|
||||
errPacketBeforeCNAME = errors.New("rtcp: feedback packet seen before CNAME")
|
||||
errTooManyReports = errors.New("rtcp: too many reports")
|
||||
errTooManyChunks = errors.New("rtcp: too many chunks")
|
||||
errTooManySources = errors.New("rtcp: too many sources")
|
||||
errPacketTooShort = errors.New("rtcp: packet too short")
|
||||
errWrongType = errors.New("rtcp: wrong packet type")
|
||||
errSDESTextTooLong = errors.New("rtcp: sdes must be < 255 octets long")
|
||||
errSDESMissingType = errors.New("rtcp: sdes item missing type")
|
||||
errReasonTooLong = errors.New("rtcp: reason must be < 255 octets long")
|
||||
errBadVersion = errors.New("rtcp: invalid packet version")
|
||||
errWrongPadding = errors.New("rtcp: invalid padding value")
|
||||
errWrongFeedbackType = errors.New("rtcp: wrong feedback message type")
|
||||
errWrongPayloadType = errors.New("rtcp: wrong payload type")
|
||||
errHeaderTooSmall = errors.New("rtcp: header length is too small")
|
||||
errSSRCMustBeZero = errors.New("rtcp: media SSRC must be 0")
|
||||
errMissingREMBidentifier = errors.New("missing REMB identifier")
|
||||
errSSRCNumAndLengthMismatch = errors.New("SSRC num and length do not match")
|
||||
errInvalidSizeOrStartIndex = errors.New("invalid size or startIndex")
|
||||
)
|
107
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/full_intra_request.go
generated
vendored
Normal file
107
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/full_intra_request.go
generated
vendored
Normal file
|
@ -0,0 +1,107 @@
|
|||
package rtcp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// A FIREntry is a (SSRC, seqno) pair, as carried by FullIntraRequest.
|
||||
type FIREntry struct {
|
||||
SSRC uint32
|
||||
SequenceNumber uint8
|
||||
}
|
||||
|
||||
// The FullIntraRequest packet is used to reliably request an Intra frame
|
||||
// in a video stream. See RFC 5104 Section 3.5.1. This is not for loss
|
||||
// recovery, which should use PictureLossIndication (PLI) instead.
|
||||
type FullIntraRequest struct {
|
||||
SenderSSRC uint32
|
||||
MediaSSRC uint32
|
||||
|
||||
FIR []FIREntry
|
||||
}
|
||||
|
||||
const (
|
||||
firOffset = 8
|
||||
)
|
||||
|
||||
var _ Packet = (*FullIntraRequest)(nil)
|
||||
|
||||
// Marshal encodes the FullIntraRequest
|
||||
func (p FullIntraRequest) Marshal() ([]byte, error) {
|
||||
rawPacket := make([]byte, firOffset+(len(p.FIR)*8))
|
||||
binary.BigEndian.PutUint32(rawPacket, p.SenderSSRC)
|
||||
binary.BigEndian.PutUint32(rawPacket[4:], p.MediaSSRC)
|
||||
for i, fir := range p.FIR {
|
||||
binary.BigEndian.PutUint32(rawPacket[firOffset+8*i:], fir.SSRC)
|
||||
rawPacket[firOffset+8*i+4] = fir.SequenceNumber
|
||||
}
|
||||
h := p.Header()
|
||||
hData, err := h.Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return append(hData, rawPacket...), nil
|
||||
}
|
||||
|
||||
// Unmarshal decodes the TransportLayerNack
|
||||
func (p *FullIntraRequest) Unmarshal(rawPacket []byte) error {
|
||||
if len(rawPacket) < (headerLength + ssrcLength) {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
var h Header
|
||||
if err := h.Unmarshal(rawPacket); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(rawPacket) < (headerLength + int(4*h.Length)) {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
if h.Type != TypePayloadSpecificFeedback || h.Count != FormatFIR {
|
||||
return errWrongType
|
||||
}
|
||||
|
||||
p.SenderSSRC = binary.BigEndian.Uint32(rawPacket[headerLength:])
|
||||
p.MediaSSRC = binary.BigEndian.Uint32(rawPacket[headerLength+ssrcLength:])
|
||||
for i := headerLength + firOffset; i < (headerLength + int(h.Length*4)); i += 8 {
|
||||
p.FIR = append(p.FIR, FIREntry{
|
||||
binary.BigEndian.Uint32(rawPacket[i:]),
|
||||
rawPacket[i+4],
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Header returns the Header associated with this packet.
|
||||
func (p *FullIntraRequest) Header() Header {
|
||||
return Header{
|
||||
Count: FormatFIR,
|
||||
Type: TypePayloadSpecificFeedback,
|
||||
Length: uint16((p.len() / 4) - 1),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *FullIntraRequest) len() int {
|
||||
return headerLength + firOffset + len(p.FIR)*8
|
||||
}
|
||||
|
||||
func (p *FullIntraRequest) String() string {
|
||||
out := fmt.Sprintf("FullIntraRequest %x %x",
|
||||
p.SenderSSRC, p.MediaSSRC)
|
||||
for _, e := range p.FIR {
|
||||
out += fmt.Sprintf(" (%x %v)", e.SSRC, e.SequenceNumber)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// DestinationSSRC returns an array of SSRC values that this packet refers to.
|
||||
func (p *FullIntraRequest) DestinationSSRC() []uint32 {
|
||||
ssrcs := make([]uint32, 0, len(p.FIR))
|
||||
for _, entry := range p.FIR {
|
||||
ssrcs = append(ssrcs, entry.SSRC)
|
||||
}
|
||||
return ssrcs
|
||||
}
|
51
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/fuzz.go
generated
vendored
Normal file
51
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/fuzz.go
generated
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
// +build gofuzz
|
||||
|
||||
package rtcp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Fuzz implements a randomized fuzz test of the rtcp
|
||||
// parser using go-fuzz.
|
||||
//
|
||||
// To run the fuzzer, first download go-fuzz:
|
||||
// `go get github.com/dvyukov/go-fuzz/...`
|
||||
//
|
||||
// Then build the testing package:
|
||||
// `go-fuzz-build github.com/pion/webrtc`
|
||||
//
|
||||
// And run the fuzzer on the corpus:
|
||||
// ```
|
||||
// mkdir workdir
|
||||
//
|
||||
// # optionally add a starter corpus of valid rtcp packets.
|
||||
// # the corpus should be as compact and diverse as possible.
|
||||
// cp -r ~/my-rtcp-packets workdir/corpus
|
||||
//
|
||||
// go-fuzz -bin=ase-fuzz.zip -workdir=workdir
|
||||
// ````
|
||||
func Fuzz(data []byte) int {
|
||||
r := NewReader(bytes.NewReader(data))
|
||||
for {
|
||||
_, data, err := r.ReadPacket()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
packet, err := Unmarshal(data)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
if _, err := packet.Marshal(); err != nil {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
5
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/go.mod
generated
vendored
Normal file
5
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/go.mod
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
module github.com/pion/rtcp
|
||||
|
||||
go 1.13
|
||||
|
||||
require github.com/stretchr/testify v1.6.1
|
11
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/go.sum
generated
vendored
Normal file
11
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/go.sum
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
146
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/goodbye.go
generated
vendored
Normal file
146
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/goodbye.go
generated
vendored
Normal file
|
@ -0,0 +1,146 @@
|
|||
package rtcp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
// The Goodbye packet indicates that one or more sources are no longer active.
|
||||
type Goodbye struct {
|
||||
// The SSRC/CSRC identifiers that are no longer active
|
||||
Sources []uint32
|
||||
// Optional text indicating the reason for leaving, e.g., "camera malfunction" or "RTP loop detected"
|
||||
Reason string
|
||||
}
|
||||
|
||||
var _ Packet = (*Goodbye)(nil) // assert is a Packet
|
||||
|
||||
// Marshal encodes the Goodbye packet in binary
|
||||
func (g Goodbye) Marshal() ([]byte, error) {
|
||||
/*
|
||||
* 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
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* |V=2|P| SC | PT=BYE=203 | length |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | SSRC/CSRC |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* : ... :
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* (opt) | length | reason for leaving ...
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
rawPacket := make([]byte, g.len())
|
||||
packetBody := rawPacket[headerLength:]
|
||||
|
||||
if len(g.Sources) > countMax {
|
||||
return nil, errTooManySources
|
||||
}
|
||||
|
||||
for i, s := range g.Sources {
|
||||
binary.BigEndian.PutUint32(packetBody[i*ssrcLength:], s)
|
||||
}
|
||||
|
||||
if g.Reason != "" {
|
||||
reason := []byte(g.Reason)
|
||||
|
||||
if len(reason) > sdesMaxOctetCount {
|
||||
return nil, errReasonTooLong
|
||||
}
|
||||
|
||||
reasonOffset := len(g.Sources) * ssrcLength
|
||||
packetBody[reasonOffset] = uint8(len(reason))
|
||||
copy(packetBody[reasonOffset+1:], reason)
|
||||
}
|
||||
|
||||
hData, err := g.Header().Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(rawPacket, hData)
|
||||
|
||||
return rawPacket, nil
|
||||
}
|
||||
|
||||
// Unmarshal decodes the Goodbye packet from binary
|
||||
func (g *Goodbye) Unmarshal(rawPacket []byte) error {
|
||||
/*
|
||||
* 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
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* |V=2|P| SC | PT=BYE=203 | length |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | SSRC/CSRC |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* : ... :
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* (opt) | length | reason for leaving ...
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
var header Header
|
||||
if err := header.Unmarshal(rawPacket); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if header.Type != TypeGoodbye {
|
||||
return errWrongType
|
||||
}
|
||||
|
||||
if getPadding(len(rawPacket)) != 0 {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
g.Sources = make([]uint32, header.Count)
|
||||
|
||||
reasonOffset := int(headerLength + header.Count*ssrcLength)
|
||||
if reasonOffset > len(rawPacket) {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
for i := 0; i < int(header.Count); i++ {
|
||||
offset := headerLength + i*ssrcLength
|
||||
|
||||
g.Sources[i] = binary.BigEndian.Uint32(rawPacket[offset:])
|
||||
}
|
||||
|
||||
if reasonOffset < len(rawPacket) {
|
||||
reasonLen := int(rawPacket[reasonOffset])
|
||||
reasonEnd := reasonOffset + 1 + reasonLen
|
||||
|
||||
if reasonEnd > len(rawPacket) {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
g.Reason = string(rawPacket[reasonOffset+1 : reasonEnd])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Header returns the Header associated with this packet.
|
||||
func (g *Goodbye) Header() Header {
|
||||
return Header{
|
||||
Padding: false,
|
||||
Count: uint8(len(g.Sources)),
|
||||
Type: TypeGoodbye,
|
||||
Length: uint16((g.len() / 4) - 1),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Goodbye) len() int {
|
||||
srcsLength := len(g.Sources) * ssrcLength
|
||||
reasonLength := len(g.Reason) + 1
|
||||
|
||||
l := headerLength + srcsLength + reasonLength
|
||||
|
||||
// align to 32-bit boundary
|
||||
return l + getPadding(l)
|
||||
}
|
||||
|
||||
// DestinationSSRC returns an array of SSRC values that this packet refers to.
|
||||
func (g *Goodbye) DestinationSSRC() []uint32 {
|
||||
out := make([]uint32, len(g.Sources))
|
||||
copy(out, g.Sources)
|
||||
return out
|
||||
}
|
140
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/header.go
generated
vendored
Normal file
140
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/header.go
generated
vendored
Normal file
|
@ -0,0 +1,140 @@
|
|||
package rtcp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
// PacketType specifies the type of an RTCP packet
|
||||
type PacketType uint8
|
||||
|
||||
// RTCP packet types registered with IANA. See: https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml#rtp-parameters-4
|
||||
const (
|
||||
TypeSenderReport PacketType = 200 // RFC 3550, 6.4.1
|
||||
TypeReceiverReport PacketType = 201 // RFC 3550, 6.4.2
|
||||
TypeSourceDescription PacketType = 202 // RFC 3550, 6.5
|
||||
TypeGoodbye PacketType = 203 // RFC 3550, 6.6
|
||||
TypeApplicationDefined PacketType = 204 // RFC 3550, 6.7 (unimplemented)
|
||||
TypeTransportSpecificFeedback PacketType = 205 // RFC 4585, 6051
|
||||
TypePayloadSpecificFeedback PacketType = 206 // RFC 4585, 6.3
|
||||
|
||||
)
|
||||
|
||||
// Transport and Payload specific feedback messages overload the count field to act as a message type. those are listed here
|
||||
const (
|
||||
FormatSLI uint8 = 2
|
||||
FormatPLI uint8 = 1
|
||||
FormatFIR uint8 = 4
|
||||
FormatTLN uint8 = 1
|
||||
FormatRRR uint8 = 5
|
||||
FormatREMB uint8 = 15
|
||||
|
||||
//https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#page-5
|
||||
FormatTCC uint8 = 15
|
||||
)
|
||||
|
||||
func (p PacketType) String() string {
|
||||
switch p {
|
||||
case TypeSenderReport:
|
||||
return "SR"
|
||||
case TypeReceiverReport:
|
||||
return "RR"
|
||||
case TypeSourceDescription:
|
||||
return "SDES"
|
||||
case TypeGoodbye:
|
||||
return "BYE"
|
||||
case TypeApplicationDefined:
|
||||
return "APP"
|
||||
case TypeTransportSpecificFeedback:
|
||||
return "TSFB"
|
||||
case TypePayloadSpecificFeedback:
|
||||
return "PSFB"
|
||||
default:
|
||||
return string(p)
|
||||
}
|
||||
}
|
||||
|
||||
const rtpVersion = 2
|
||||
|
||||
// A Header is the common header shared by all RTCP packets
|
||||
type Header struct {
|
||||
// If the padding bit is set, this individual RTCP packet contains
|
||||
// some additional padding octets at the end which are not part of
|
||||
// the control information but are included in the length field.
|
||||
Padding bool
|
||||
// The number of reception reports, sources contained or FMT in this packet (depending on the Type)
|
||||
Count uint8
|
||||
// The RTCP packet type for this packet
|
||||
Type PacketType
|
||||
// The length of this RTCP packet in 32-bit words minus one,
|
||||
// including the header and any padding.
|
||||
Length uint16
|
||||
}
|
||||
|
||||
const (
|
||||
headerLength = 4
|
||||
versionShift = 6
|
||||
versionMask = 0x3
|
||||
paddingShift = 5
|
||||
paddingMask = 0x1
|
||||
countShift = 0
|
||||
countMask = 0x1f
|
||||
countMax = (1 << 5) - 1
|
||||
)
|
||||
|
||||
// Marshal encodes the Header in binary
|
||||
func (h Header) Marshal() ([]byte, error) {
|
||||
/*
|
||||
* 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
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* |V=2|P| RC | PT=SR=200 | length |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
rawPacket := make([]byte, headerLength)
|
||||
|
||||
rawPacket[0] |= rtpVersion << versionShift
|
||||
|
||||
if h.Padding {
|
||||
rawPacket[0] |= 1 << paddingShift
|
||||
}
|
||||
|
||||
if h.Count > 31 {
|
||||
return nil, errInvalidHeader
|
||||
}
|
||||
rawPacket[0] |= h.Count << countShift
|
||||
|
||||
rawPacket[1] = uint8(h.Type)
|
||||
|
||||
binary.BigEndian.PutUint16(rawPacket[2:], h.Length)
|
||||
|
||||
return rawPacket, nil
|
||||
}
|
||||
|
||||
// Unmarshal decodes the Header from binary
|
||||
func (h *Header) Unmarshal(rawPacket []byte) error {
|
||||
if len(rawPacket) < headerLength {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* |V=2|P| RC | PT | length |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
version := rawPacket[0] >> versionShift & versionMask
|
||||
if version != rtpVersion {
|
||||
return errBadVersion
|
||||
}
|
||||
|
||||
h.Padding = (rawPacket[0] >> paddingShift & paddingMask) > 0
|
||||
h.Count = rawPacket[0] >> countShift & countMask
|
||||
|
||||
h.Type = PacketType(rawPacket[1])
|
||||
|
||||
h.Length = binary.BigEndian.Uint16(rawPacket[2:])
|
||||
|
||||
return nil
|
||||
}
|
115
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/packet.go
generated
vendored
Normal file
115
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/packet.go
generated
vendored
Normal file
|
@ -0,0 +1,115 @@
|
|||
package rtcp
|
||||
|
||||
// Packet represents an RTCP packet, a protocol used for out-of-band statistics and control information for an RTP session
|
||||
type Packet interface {
|
||||
// DestinationSSRC returns an array of SSRC values that this packet refers to.
|
||||
DestinationSSRC() []uint32
|
||||
|
||||
Marshal() ([]byte, error)
|
||||
Unmarshal(rawPacket []byte) error
|
||||
}
|
||||
|
||||
// Unmarshal takes an entire udp datagram (which may consist of multiple RTCP packets) and
|
||||
// returns the unmarshaled packets it contains.
|
||||
//
|
||||
// If this is a reduced-size RTCP packet a feedback packet (Goodbye, SliceLossIndication, etc)
|
||||
// will be returned. Otherwise, the underlying type of the returned packet will be
|
||||
// CompoundPacket.
|
||||
func Unmarshal(rawData []byte) ([]Packet, error) {
|
||||
var packets []Packet
|
||||
for len(rawData) != 0 {
|
||||
p, processed, err := unmarshal(rawData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
packets = append(packets, p)
|
||||
rawData = rawData[processed:]
|
||||
}
|
||||
|
||||
switch len(packets) {
|
||||
// Empty packet
|
||||
case 0:
|
||||
return nil, errInvalidHeader
|
||||
// Multiple Packets
|
||||
default:
|
||||
return packets, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Marshal takes an array of Packets and serializes them to a single buffer
|
||||
func Marshal(packets []Packet) ([]byte, error) {
|
||||
out := make([]byte, 0)
|
||||
for _, p := range packets {
|
||||
data, err := p.Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, data...)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// unmarshal is a factory which pulls the first RTCP packet from a bytestream,
|
||||
// and returns it's parsed representation, and the amount of data that was processed.
|
||||
func unmarshal(rawData []byte) (packet Packet, bytesprocessed int, err error) {
|
||||
var h Header
|
||||
|
||||
err = h.Unmarshal(rawData)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
bytesprocessed = int(h.Length+1) * 4
|
||||
if bytesprocessed > len(rawData) {
|
||||
return nil, 0, errPacketTooShort
|
||||
}
|
||||
inPacket := rawData[:bytesprocessed]
|
||||
|
||||
switch h.Type {
|
||||
case TypeSenderReport:
|
||||
packet = new(SenderReport)
|
||||
|
||||
case TypeReceiverReport:
|
||||
packet = new(ReceiverReport)
|
||||
|
||||
case TypeSourceDescription:
|
||||
packet = new(SourceDescription)
|
||||
|
||||
case TypeGoodbye:
|
||||
packet = new(Goodbye)
|
||||
|
||||
case TypeTransportSpecificFeedback:
|
||||
switch h.Count {
|
||||
case FormatTLN:
|
||||
packet = new(TransportLayerNack)
|
||||
case FormatRRR:
|
||||
packet = new(RapidResynchronizationRequest)
|
||||
case FormatTCC:
|
||||
packet = new(TransportLayerCC)
|
||||
default:
|
||||
packet = new(RawPacket)
|
||||
}
|
||||
|
||||
case TypePayloadSpecificFeedback:
|
||||
switch h.Count {
|
||||
case FormatPLI:
|
||||
packet = new(PictureLossIndication)
|
||||
case FormatSLI:
|
||||
packet = new(SliceLossIndication)
|
||||
case FormatREMB:
|
||||
packet = new(ReceiverEstimatedMaximumBitrate)
|
||||
case FormatFIR:
|
||||
packet = new(FullIntraRequest)
|
||||
default:
|
||||
packet = new(RawPacket)
|
||||
}
|
||||
|
||||
default:
|
||||
packet = new(RawPacket)
|
||||
}
|
||||
|
||||
err = packet.Unmarshal(inPacket)
|
||||
|
||||
return packet, bytesprocessed, err
|
||||
}
|
91
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/picture_loss_indication.go
generated
vendored
Normal file
91
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/picture_loss_indication.go
generated
vendored
Normal file
|
@ -0,0 +1,91 @@
|
|||
package rtcp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// The PictureLossIndication packet informs the encoder about the loss of an undefined amount of coded video data belonging to one or more pictures
|
||||
type PictureLossIndication struct {
|
||||
// SSRC of sender
|
||||
SenderSSRC uint32
|
||||
|
||||
// SSRC where the loss was experienced
|
||||
MediaSSRC uint32
|
||||
}
|
||||
|
||||
var _ Packet = (*PictureLossIndication)(nil) // assert is a Packet
|
||||
|
||||
const (
|
||||
pliLength = 2
|
||||
)
|
||||
|
||||
// Marshal encodes the PictureLossIndication in binary
|
||||
func (p PictureLossIndication) Marshal() ([]byte, error) {
|
||||
/*
|
||||
* PLI does not require parameters. Therefore, the length field MUST be
|
||||
* 2, and there MUST NOT be any Feedback Control Information.
|
||||
*
|
||||
* The semantics of this FB message is independent of the payload type.
|
||||
*/
|
||||
rawPacket := make([]byte, p.len())
|
||||
packetBody := rawPacket[headerLength:]
|
||||
|
||||
binary.BigEndian.PutUint32(packetBody, p.SenderSSRC)
|
||||
binary.BigEndian.PutUint32(packetBody[4:], p.MediaSSRC)
|
||||
|
||||
h := Header{
|
||||
Count: FormatPLI,
|
||||
Type: TypePayloadSpecificFeedback,
|
||||
Length: pliLength,
|
||||
}
|
||||
hData, err := h.Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(rawPacket, hData)
|
||||
|
||||
return rawPacket, nil
|
||||
}
|
||||
|
||||
// Unmarshal decodes the PictureLossIndication from binary
|
||||
func (p *PictureLossIndication) Unmarshal(rawPacket []byte) error {
|
||||
if len(rawPacket) < (headerLength + (ssrcLength * 2)) {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
var h Header
|
||||
if err := h.Unmarshal(rawPacket); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if h.Type != TypePayloadSpecificFeedback || h.Count != FormatPLI {
|
||||
return errWrongType
|
||||
}
|
||||
|
||||
p.SenderSSRC = binary.BigEndian.Uint32(rawPacket[headerLength:])
|
||||
p.MediaSSRC = binary.BigEndian.Uint32(rawPacket[headerLength+ssrcLength:])
|
||||
return nil
|
||||
}
|
||||
|
||||
// Header returns the Header associated with this packet.
|
||||
func (p *PictureLossIndication) Header() Header {
|
||||
return Header{
|
||||
Count: FormatPLI,
|
||||
Type: TypePayloadSpecificFeedback,
|
||||
Length: pliLength,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PictureLossIndication) len() int {
|
||||
return headerLength + ssrcLength*2
|
||||
}
|
||||
|
||||
func (p *PictureLossIndication) String() string {
|
||||
return fmt.Sprintf("PictureLossIndication %x %x", p.SenderSSRC, p.MediaSSRC)
|
||||
}
|
||||
|
||||
// DestinationSSRC returns an array of SSRC values that this packet refers to.
|
||||
func (p *PictureLossIndication) DestinationSSRC() []uint32 {
|
||||
return []uint32{p.MediaSSRC}
|
||||
}
|
88
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/rapid_resynchronization_request.go
generated
vendored
Normal file
88
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/rapid_resynchronization_request.go
generated
vendored
Normal file
|
@ -0,0 +1,88 @@
|
|||
package rtcp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// The RapidResynchronizationRequest packet informs the encoder about the loss of an undefined amount of coded video data belonging to one or more pictures
|
||||
type RapidResynchronizationRequest struct {
|
||||
// SSRC of sender
|
||||
SenderSSRC uint32
|
||||
|
||||
// SSRC of the media source
|
||||
MediaSSRC uint32
|
||||
}
|
||||
|
||||
var _ Packet = (*RapidResynchronizationRequest)(nil) // assert is a Packet
|
||||
|
||||
const (
|
||||
rrrLength = 2
|
||||
rrrHeaderLength = ssrcLength * 2
|
||||
rrrMediaOffset = 4
|
||||
)
|
||||
|
||||
// Marshal encodes the RapidResynchronizationRequest in binary
|
||||
func (p RapidResynchronizationRequest) Marshal() ([]byte, error) {
|
||||
/*
|
||||
* RRR does not require parameters. Therefore, the length field MUST be
|
||||
* 2, and there MUST NOT be any Feedback Control Information.
|
||||
*
|
||||
* The semantics of this FB message is independent of the payload type.
|
||||
*/
|
||||
rawPacket := make([]byte, p.len())
|
||||
packetBody := rawPacket[headerLength:]
|
||||
|
||||
binary.BigEndian.PutUint32(packetBody, p.SenderSSRC)
|
||||
binary.BigEndian.PutUint32(packetBody[rrrMediaOffset:], p.MediaSSRC)
|
||||
|
||||
hData, err := p.Header().Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(rawPacket, hData)
|
||||
|
||||
return rawPacket, nil
|
||||
}
|
||||
|
||||
// Unmarshal decodes the RapidResynchronizationRequest from binary
|
||||
func (p *RapidResynchronizationRequest) Unmarshal(rawPacket []byte) error {
|
||||
if len(rawPacket) < (headerLength + (ssrcLength * 2)) {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
var h Header
|
||||
if err := h.Unmarshal(rawPacket); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if h.Type != TypeTransportSpecificFeedback || h.Count != FormatRRR {
|
||||
return errWrongType
|
||||
}
|
||||
|
||||
p.SenderSSRC = binary.BigEndian.Uint32(rawPacket[headerLength:])
|
||||
p.MediaSSRC = binary.BigEndian.Uint32(rawPacket[headerLength+ssrcLength:])
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *RapidResynchronizationRequest) len() int {
|
||||
return headerLength + rrrHeaderLength
|
||||
}
|
||||
|
||||
// Header returns the Header associated with this packet.
|
||||
func (p *RapidResynchronizationRequest) Header() Header {
|
||||
return Header{
|
||||
Count: FormatRRR,
|
||||
Type: TypeTransportSpecificFeedback,
|
||||
Length: rrrLength,
|
||||
}
|
||||
}
|
||||
|
||||
// DestinationSSRC returns an array of SSRC values that this packet refers to.
|
||||
func (p *RapidResynchronizationRequest) DestinationSSRC() []uint32 {
|
||||
return []uint32{p.MediaSSRC}
|
||||
}
|
||||
|
||||
func (p *RapidResynchronizationRequest) String() string {
|
||||
return fmt.Sprintf("RapidResynchronizationRequest %x %x", p.SenderSSRC, p.MediaSSRC)
|
||||
}
|
44
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/raw_packet.go
generated
vendored
Normal file
44
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/raw_packet.go
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
package rtcp
|
||||
|
||||
import "fmt"
|
||||
|
||||
// RawPacket represents an unparsed RTCP packet. It's returned by Unmarshal when
|
||||
// a packet with an unknown type is encountered.
|
||||
type RawPacket []byte
|
||||
|
||||
var _ Packet = (*RawPacket)(nil) // assert is a Packet
|
||||
|
||||
// Marshal encodes the packet in binary.
|
||||
func (r RawPacket) Marshal() ([]byte, error) {
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// Unmarshal decodes the packet from binary.
|
||||
func (r *RawPacket) Unmarshal(b []byte) error {
|
||||
if len(b) < (headerLength) {
|
||||
return errPacketTooShort
|
||||
}
|
||||
*r = b
|
||||
|
||||
var h Header
|
||||
return h.Unmarshal(b)
|
||||
}
|
||||
|
||||
// Header returns the Header associated with this packet.
|
||||
func (r RawPacket) Header() Header {
|
||||
var h Header
|
||||
if err := h.Unmarshal(r); err != nil {
|
||||
return Header{}
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
// DestinationSSRC returns an array of SSRC values that this packet refers to.
|
||||
func (r *RawPacket) DestinationSSRC() []uint32 {
|
||||
return []uint32{}
|
||||
}
|
||||
|
||||
func (r RawPacket) String() string {
|
||||
out := fmt.Sprintf("RawPacket: %v", ([]byte)(r))
|
||||
return out
|
||||
}
|
284
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/receiver_estimated_maximum_bitrate.go
generated
vendored
Normal file
284
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/receiver_estimated_maximum_bitrate.go
generated
vendored
Normal file
|
@ -0,0 +1,284 @@
|
|||
package rtcp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
// ReceiverEstimatedMaximumBitrate contains the receiver's estimated maximum bitrate.
|
||||
// see: https://tools.ietf.org/html/draft-alvestrand-rmcat-remb-03
|
||||
type ReceiverEstimatedMaximumBitrate struct {
|
||||
// SSRC of sender
|
||||
SenderSSRC uint32
|
||||
|
||||
// Estimated maximum bitrate
|
||||
Bitrate uint64
|
||||
|
||||
// SSRC entries which this packet applies to
|
||||
SSRCs []uint32
|
||||
}
|
||||
|
||||
var _ Packet = (*ReceiverEstimatedMaximumBitrate)(nil) // assert is a Packet
|
||||
|
||||
// Marshal serializes the packet and returns a byte slice.
|
||||
func (p ReceiverEstimatedMaximumBitrate) Marshal() (buf []byte, err error) {
|
||||
// Allocate a buffer of the exact output size.
|
||||
buf = make([]byte, p.MarshalSize())
|
||||
|
||||
// Write to our buffer.
|
||||
n, err := p.MarshalTo(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// This will always be true but just to be safe.
|
||||
if n != len(buf) {
|
||||
return nil, errWrongMarshalSize
|
||||
}
|
||||
|
||||
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) {
|
||||
return 20 + 4*len(p.SSRCs)
|
||||
}
|
||||
|
||||
// MarshalTo serializes the packet to the given byte slice.
|
||||
func (p ReceiverEstimatedMaximumBitrate) MarshalTo(buf []byte) (n int, err error) {
|
||||
/*
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|V=2|P| FMT=15 | PT=206 | length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| SSRC of packet sender |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| SSRC of media source |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Unique identifier 'R' 'E' 'M' 'B' |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Num SSRC | BR Exp | BR Mantissa |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| SSRC feedback |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| ... |
|
||||
*/
|
||||
|
||||
size := p.MarshalSize()
|
||||
if len(buf) < size {
|
||||
return 0, errPacketTooShort
|
||||
}
|
||||
|
||||
buf[0] = 143 // v=2, p=0, fmt=15
|
||||
buf[1] = 206
|
||||
|
||||
// Length of this packet in 32-bit words minus one.
|
||||
length := uint16((p.MarshalSize() / 4) - 1)
|
||||
binary.BigEndian.PutUint16(buf[2:4], length)
|
||||
|
||||
binary.BigEndian.PutUint32(buf[4:8], p.SenderSSRC)
|
||||
binary.BigEndian.PutUint32(buf[8:12], 0) // always zero
|
||||
|
||||
// ALL HAIL REMB
|
||||
buf[12] = 'R'
|
||||
buf[13] = 'E'
|
||||
buf[14] = 'M'
|
||||
buf[15] = 'B'
|
||||
|
||||
// Write the length of the ssrcs to follow at the end
|
||||
buf[16] = byte(len(p.SSRCs))
|
||||
|
||||
// We can only encode 18 bits of information in the mantissa.
|
||||
// The exponent lets us shift to the left up to 64 places (6-bits).
|
||||
// We actually need a uint82 to encode the largest possible number,
|
||||
// but uint64 should be good enough for 2.3 exabytes per second.
|
||||
|
||||
// So we need to truncate the bitrate and use the exponent for the shift.
|
||||
// bitrate = mantissa * (1 << exp)
|
||||
|
||||
// Calculate the total shift based on the leading number of zeroes.
|
||||
// This will be negative if there is no shift required.
|
||||
shift := uint(64 - bits.LeadingZeros64(p.Bitrate))
|
||||
|
||||
var mantissa uint
|
||||
var exp uint
|
||||
|
||||
if shift <= 18 {
|
||||
// Fit everything in the mantissa because we can.
|
||||
mantissa = uint(p.Bitrate)
|
||||
exp = 0
|
||||
} else {
|
||||
// We can only use 18 bits of precision, so truncate.
|
||||
mantissa = uint(p.Bitrate >> (shift - 18))
|
||||
exp = shift - 18
|
||||
}
|
||||
|
||||
// We can't quite use the binary package because
|
||||
// a) it's a uint24 and b) the exponent is only 6-bits
|
||||
// Just trust me; this is big-endian encoding.
|
||||
buf[17] = byte((exp << 2) | (mantissa >> 16))
|
||||
buf[18] = byte(mantissa >> 8)
|
||||
buf[19] = byte(mantissa)
|
||||
|
||||
// Write the SSRCs at the very end.
|
||||
n = 20
|
||||
for _, ssrc := range p.SSRCs {
|
||||
binary.BigEndian.PutUint32(buf[n:n+4], ssrc)
|
||||
n += 4
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// Unmarshal reads a REMB packet from the given byte slice.
|
||||
func (p *ReceiverEstimatedMaximumBitrate) Unmarshal(buf []byte) (err error) {
|
||||
/*
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|V=2|P| FMT=15 | PT=206 | length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| SSRC of packet sender |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| SSRC of media source |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Unique identifier 'R' 'E' 'M' 'B' |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Num SSRC | BR Exp | BR Mantissa |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| SSRC feedback |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| ... |
|
||||
*/
|
||||
|
||||
// 20 bytes is the size of the packet with no SSRCs
|
||||
if len(buf) < 20 {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
// version must be 2
|
||||
version := buf[0] >> 6
|
||||
if version != 2 {
|
||||
return fmt.Errorf("%w expected(2) actual(%d)", errBadVersion, version)
|
||||
}
|
||||
|
||||
// padding must be unset
|
||||
padding := (buf[0] >> 5) & 1
|
||||
if padding != 0 {
|
||||
return fmt.Errorf("%w expected(0) actual(%d)", errWrongPadding, padding)
|
||||
}
|
||||
|
||||
// fmt must be 15
|
||||
fmtVal := buf[0] & 31
|
||||
if fmtVal != 15 {
|
||||
return fmt.Errorf("%w expected(15) actual(%d)", errWrongFeedbackType, fmtVal)
|
||||
}
|
||||
|
||||
// Must be payload specific feedback
|
||||
if buf[1] != 206 {
|
||||
return fmt.Errorf("%w expected(206) actual(%d)", errWrongPayloadType, buf[1])
|
||||
}
|
||||
|
||||
// length is the number of 32-bit words, minus 1
|
||||
length := binary.BigEndian.Uint16(buf[2:4])
|
||||
size := int((length + 1) * 4)
|
||||
|
||||
// There's not way this could be legit
|
||||
if size < 20 {
|
||||
return errHeaderTooSmall
|
||||
}
|
||||
|
||||
// Make sure the buffer is large enough.
|
||||
if len(buf) < size {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
// The sender SSRC is 32-bits
|
||||
p.SenderSSRC = binary.BigEndian.Uint32(buf[4:8])
|
||||
|
||||
// The destination SSRC must be 0
|
||||
media := binary.BigEndian.Uint32(buf[8:12])
|
||||
if media != 0 {
|
||||
return errSSRCMustBeZero
|
||||
}
|
||||
|
||||
// REMB rules all around me
|
||||
if !bytes.Equal(buf[12:16], []byte{'R', 'E', 'M', 'B'}) {
|
||||
return errMissingREMBidentifier
|
||||
}
|
||||
|
||||
// The next byte is the number of SSRC entries at the end.
|
||||
num := int(buf[16])
|
||||
|
||||
// Now we know the expected size, make sure they match.
|
||||
if size != 20+4*num {
|
||||
return errSSRCNumAndLengthMismatch
|
||||
}
|
||||
|
||||
// Get the 6-bit exponent value.
|
||||
exp := buf[17] >> 2
|
||||
|
||||
// The remaining 2-bits plus the next 16-bits are the mantissa.
|
||||
mantissa := uint64(buf[17]&3)<<16 | uint64(buf[18])<<8 | uint64(buf[19])
|
||||
|
||||
// bitrate = mantissa * 2^exp
|
||||
|
||||
if exp > 46 {
|
||||
// NOTE: We intentionally truncate values so they fit in a uint64.
|
||||
// Otherwise we would need a uint82.
|
||||
// This is 2.3 exabytes per second, which should be good enough.
|
||||
p.Bitrate = ^uint64(0)
|
||||
} else {
|
||||
p.Bitrate = mantissa << exp
|
||||
}
|
||||
|
||||
// Clear any existing SSRCs
|
||||
p.SSRCs = nil
|
||||
|
||||
// Loop over and parse the SSRC entires at the end.
|
||||
// We already verified that size == num * 4
|
||||
for n := 20; n < size; n += 4 {
|
||||
ssrc := binary.BigEndian.Uint32(buf[n : n+4])
|
||||
p.SSRCs = append(p.SSRCs, ssrc)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Header returns the Header associated with this packet.
|
||||
func (p *ReceiverEstimatedMaximumBitrate) Header() Header {
|
||||
return Header{
|
||||
Count: FormatREMB,
|
||||
Type: TypePayloadSpecificFeedback,
|
||||
Length: uint16((p.MarshalSize() / 4) - 1),
|
||||
}
|
||||
}
|
||||
|
||||
// String prints the REMB packet in a human-readable format.
|
||||
func (p *ReceiverEstimatedMaximumBitrate) String() string {
|
||||
// Keep a table of powers to units for fast conversion.
|
||||
bitUnits := []string{"b", "Kb", "Mb", "Gb", "Tb", "Pb", "Eb"}
|
||||
|
||||
// Do some unit conversions because b/s is far too difficult to read.
|
||||
bitrate := float64(p.Bitrate)
|
||||
powers := 0
|
||||
|
||||
// Keep dividing the bitrate until it's under 1000
|
||||
for bitrate >= 1000.0 && powers < len(bitUnits) {
|
||||
bitrate /= 1000.0
|
||||
powers++
|
||||
}
|
||||
|
||||
unit := bitUnits[powers]
|
||||
|
||||
return fmt.Sprintf("ReceiverEstimatedMaximumBitrate %x %.2f %s/s", p.SenderSSRC, bitrate, unit)
|
||||
}
|
||||
|
||||
// DestinationSSRC returns an array of SSRC values that this packet refers to.
|
||||
func (p *ReceiverEstimatedMaximumBitrate) DestinationSSRC() []uint32 {
|
||||
return p.SSRCs
|
||||
}
|
193
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/receiver_report.go
generated
vendored
Normal file
193
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/receiver_report.go
generated
vendored
Normal file
|
@ -0,0 +1,193 @@
|
|||
package rtcp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// A ReceiverReport (RR) packet provides reception quality feedback for an RTP stream
|
||||
type ReceiverReport struct {
|
||||
// The synchronization source identifier for the originator of this RR packet.
|
||||
SSRC uint32
|
||||
// Zero or more reception report blocks depending on the number of other
|
||||
// sources heard by this sender since the last report. Each reception report
|
||||
// block conveys statistics on the reception of RTP packets from a
|
||||
// single synchronization source.
|
||||
Reports []ReceptionReport
|
||||
// Extension contains additional, payload-specific information that needs to
|
||||
// be reported regularly about the receiver.
|
||||
ProfileExtensions []byte
|
||||
}
|
||||
|
||||
var _ Packet = (*ReceiverReport)(nil) // assert is a Packet
|
||||
|
||||
const (
|
||||
ssrcLength = 4
|
||||
rrSSRCOffset = headerLength
|
||||
rrReportOffset = rrSSRCOffset + ssrcLength
|
||||
)
|
||||
|
||||
// Marshal encodes the ReceiverReport in binary
|
||||
func (r ReceiverReport) Marshal() ([]byte, error) {
|
||||
/*
|
||||
* 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
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* header |V=2|P| RC | PT=RR=201 | length |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | SSRC of packet sender |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* report | SSRC_1 (SSRC of first source) |
|
||||
* block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* 1 | fraction lost | cumulative number of packets lost |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | extended highest sequence number received |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | interarrival jitter |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | last SR (LSR) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | delay since last SR (DLSR) |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* report | SSRC_2 (SSRC of second source) |
|
||||
* block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* 2 : ... :
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* | profile-specific extensions |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
rawPacket := make([]byte, r.len())
|
||||
packetBody := rawPacket[headerLength:]
|
||||
|
||||
binary.BigEndian.PutUint32(packetBody, r.SSRC)
|
||||
|
||||
for i, rp := range r.Reports {
|
||||
data, err := rp.Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
offset := ssrcLength + receptionReportLength*i
|
||||
copy(packetBody[offset:], data)
|
||||
}
|
||||
|
||||
if len(r.Reports) > countMax {
|
||||
return nil, errTooManyReports
|
||||
}
|
||||
|
||||
pe := make([]byte, len(r.ProfileExtensions))
|
||||
copy(pe, r.ProfileExtensions)
|
||||
|
||||
// if the length of the profile extensions isn't devisible
|
||||
// by 4, we need to pad the end.
|
||||
for (len(pe) & 0x3) != 0 {
|
||||
pe = append(pe, 0)
|
||||
}
|
||||
|
||||
rawPacket = append(rawPacket, pe...)
|
||||
|
||||
hData, err := r.Header().Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(rawPacket, hData)
|
||||
|
||||
return rawPacket, nil
|
||||
}
|
||||
|
||||
// Unmarshal decodes the ReceiverReport from binary
|
||||
func (r *ReceiverReport) Unmarshal(rawPacket []byte) error {
|
||||
/*
|
||||
* 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
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* header |V=2|P| RC | PT=RR=201 | length |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | SSRC of packet sender |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* report | SSRC_1 (SSRC of first source) |
|
||||
* block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* 1 | fraction lost | cumulative number of packets lost |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | extended highest sequence number received |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | interarrival jitter |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | last SR (LSR) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | delay since last SR (DLSR) |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* report | SSRC_2 (SSRC of second source) |
|
||||
* block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* 2 : ... :
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* | profile-specific extensions |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
if len(rawPacket) < (headerLength + ssrcLength) {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
var h Header
|
||||
if err := h.Unmarshal(rawPacket); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if h.Type != TypeReceiverReport {
|
||||
return errWrongType
|
||||
}
|
||||
|
||||
r.SSRC = binary.BigEndian.Uint32(rawPacket[rrSSRCOffset:])
|
||||
|
||||
for i := rrReportOffset; i < len(rawPacket) && len(r.Reports) < int(h.Count); i += receptionReportLength {
|
||||
var rr ReceptionReport
|
||||
if err := rr.Unmarshal(rawPacket[i:]); err != nil {
|
||||
return err
|
||||
}
|
||||
r.Reports = append(r.Reports, rr)
|
||||
}
|
||||
r.ProfileExtensions = rawPacket[rrReportOffset+(len(r.Reports)*receptionReportLength):]
|
||||
|
||||
if uint8(len(r.Reports)) != h.Count {
|
||||
return errInvalidHeader
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ReceiverReport) len() int {
|
||||
repsLength := 0
|
||||
for _, rep := range r.Reports {
|
||||
repsLength += rep.len()
|
||||
}
|
||||
return headerLength + ssrcLength + repsLength
|
||||
}
|
||||
|
||||
// Header returns the Header associated with this packet.
|
||||
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))),
|
||||
}
|
||||
}
|
||||
|
||||
// DestinationSSRC returns an array of SSRC values that this packet refers to.
|
||||
func (r *ReceiverReport) DestinationSSRC() []uint32 {
|
||||
out := make([]uint32, len(r.Reports))
|
||||
for i, v := range r.Reports {
|
||||
out[i] = v.SSRC
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (r ReceiverReport) String() string {
|
||||
out := fmt.Sprintf("ReceiverReport from %x\n", r.SSRC)
|
||||
out += "\tSSRC \tLost\tLastSequence\n"
|
||||
for _, i := range r.Reports {
|
||||
out += fmt.Sprintf("\t%x\t%d/%d\t%d\n", i.SSRC, i.FractionLost, i.TotalLost, i.LastSequenceNumber)
|
||||
}
|
||||
out += fmt.Sprintf("\tProfile Extension Data: %v\n", r.ProfileExtensions)
|
||||
return out
|
||||
}
|
130
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/reception_report.go
generated
vendored
Normal file
130
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/reception_report.go
generated
vendored
Normal file
|
@ -0,0 +1,130 @@
|
|||
package rtcp
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
// A ReceptionReport block conveys statistics on the reception of RTP packets
|
||||
// from a single synchronization source.
|
||||
type ReceptionReport struct {
|
||||
// The SSRC identifier of the source to which the information in this
|
||||
// reception report block pertains.
|
||||
SSRC uint32
|
||||
// The fraction of RTP data packets from source SSRC lost since the
|
||||
// previous SR or RR packet was sent, expressed as a fixed point
|
||||
// number with the binary point at the left edge of the field.
|
||||
FractionLost uint8
|
||||
// The total number of RTP data packets from source SSRC that have
|
||||
// been lost since the beginning of reception.
|
||||
TotalLost uint32
|
||||
// The low 16 bits contain the highest sequence number received in an
|
||||
// RTP data packet from source SSRC, and the most significant 16
|
||||
// bits extend that sequence number with the corresponding count of
|
||||
// sequence number cycles.
|
||||
LastSequenceNumber uint32
|
||||
// An estimate of the statistical variance of the RTP data packet
|
||||
// interarrival time, measured in timestamp units and expressed as an
|
||||
// unsigned integer.
|
||||
Jitter uint32
|
||||
// The middle 32 bits out of 64 in the NTP timestamp received as part of
|
||||
// the most recent RTCP sender report (SR) packet from source SSRC. If no
|
||||
// SR has been received yet, the field is set to zero.
|
||||
LastSenderReport uint32
|
||||
// The delay, expressed in units of 1/65536 seconds, between receiving the
|
||||
// last SR packet from source SSRC and sending this reception report block.
|
||||
// If no SR packet has been received yet from SSRC, the field is set to zero.
|
||||
Delay uint32
|
||||
}
|
||||
|
||||
const (
|
||||
receptionReportLength = 24
|
||||
fractionLostOffset = 4
|
||||
totalLostOffset = 5
|
||||
lastSeqOffset = 8
|
||||
jitterOffset = 12
|
||||
lastSROffset = 16
|
||||
delayOffset = 20
|
||||
)
|
||||
|
||||
// Marshal encodes the ReceptionReport in binary
|
||||
func (r ReceptionReport) Marshal() ([]byte, error) {
|
||||
/*
|
||||
* 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
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* | SSRC |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | fraction lost | cumulative number of packets lost |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | extended highest sequence number received |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | interarrival jitter |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | last SR (LSR) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | delay since last SR (DLSR) |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*/
|
||||
|
||||
rawPacket := make([]byte, receptionReportLength)
|
||||
|
||||
binary.BigEndian.PutUint32(rawPacket, r.SSRC)
|
||||
|
||||
rawPacket[fractionLostOffset] = r.FractionLost
|
||||
|
||||
// pack TotalLost into 24 bits
|
||||
if r.TotalLost >= (1 << 25) {
|
||||
return nil, errInvalidTotalLost
|
||||
}
|
||||
tlBytes := rawPacket[totalLostOffset:]
|
||||
tlBytes[0] = byte(r.TotalLost >> 16)
|
||||
tlBytes[1] = byte(r.TotalLost >> 8)
|
||||
tlBytes[2] = byte(r.TotalLost)
|
||||
|
||||
binary.BigEndian.PutUint32(rawPacket[lastSeqOffset:], r.LastSequenceNumber)
|
||||
binary.BigEndian.PutUint32(rawPacket[jitterOffset:], r.Jitter)
|
||||
binary.BigEndian.PutUint32(rawPacket[lastSROffset:], r.LastSenderReport)
|
||||
binary.BigEndian.PutUint32(rawPacket[delayOffset:], r.Delay)
|
||||
|
||||
return rawPacket, nil
|
||||
}
|
||||
|
||||
// Unmarshal decodes the ReceptionReport from binary
|
||||
func (r *ReceptionReport) Unmarshal(rawPacket []byte) error {
|
||||
if len(rawPacket) < receptionReportLength {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* | SSRC |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | fraction lost | cumulative number of packets lost |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | extended highest sequence number received |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | interarrival jitter |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | last SR (LSR) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | delay since last SR (DLSR) |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*/
|
||||
|
||||
r.SSRC = binary.BigEndian.Uint32(rawPacket)
|
||||
r.FractionLost = rawPacket[fractionLostOffset]
|
||||
|
||||
tlBytes := rawPacket[totalLostOffset:]
|
||||
r.TotalLost = uint32(tlBytes[2]) | uint32(tlBytes[1])<<8 | uint32(tlBytes[0])<<16
|
||||
|
||||
r.LastSequenceNumber = binary.BigEndian.Uint32(rawPacket[lastSeqOffset:])
|
||||
r.Jitter = binary.BigEndian.Uint32(rawPacket[jitterOffset:])
|
||||
r.LastSenderReport = binary.BigEndian.Uint32(rawPacket[lastSROffset:])
|
||||
r.Delay = binary.BigEndian.Uint32(rawPacket[delayOffset:])
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ReceptionReport) len() int {
|
||||
return receptionReportLength
|
||||
}
|
15
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/renovate.json
generated
vendored
Normal file
15
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/renovate.json
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"extends": [
|
||||
"config:base"
|
||||
],
|
||||
"postUpdateOptions": [
|
||||
"gomodTidy"
|
||||
],
|
||||
"commitBody": "Generated by renovateBot",
|
||||
"packageRules": [
|
||||
{
|
||||
"packagePatterns": ["^golang.org/x/"],
|
||||
"schedule": ["on the first day of the month"]
|
||||
}
|
||||
]
|
||||
}
|
260
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/sender_report.go
generated
vendored
Normal file
260
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/sender_report.go
generated
vendored
Normal file
|
@ -0,0 +1,260 @@
|
|||
package rtcp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// A SenderReport (SR) packet provides reception quality feedback for an RTP stream
|
||||
type SenderReport struct {
|
||||
// The synchronization source identifier for the originator of this SR packet.
|
||||
SSRC uint32
|
||||
// The wallclock time when this report was sent so that it may be used in
|
||||
// combination with timestamps returned in reception reports from other
|
||||
// receivers to measure round-trip propagation to those receivers.
|
||||
NTPTime uint64
|
||||
// Corresponds to the same time as the NTP timestamp (above), but in
|
||||
// the same units and with the same random offset as the RTP
|
||||
// timestamps in data packets. This correspondence may be used for
|
||||
// intra- and inter-media synchronization for sources whose NTP
|
||||
// timestamps are synchronized, and may be used by media-independent
|
||||
// receivers to estimate the nominal RTP clock frequency.
|
||||
RTPTime uint32
|
||||
// The total number of RTP data packets transmitted by the sender
|
||||
// since starting transmission up until the time this SR packet was
|
||||
// generated.
|
||||
PacketCount uint32
|
||||
// The total number of payload octets (i.e., not including header or
|
||||
// padding) transmitted in RTP data packets by the sender since
|
||||
// starting transmission up until the time this SR packet was
|
||||
// generated.
|
||||
OctetCount uint32
|
||||
// Zero or more reception report blocks depending on the number of other
|
||||
// sources heard by this sender since the last report. Each reception report
|
||||
// block conveys statistics on the reception of RTP packets from a
|
||||
// single synchronization source.
|
||||
Reports []ReceptionReport
|
||||
// ProfileExtensions contains additional, payload-specific information that needs to
|
||||
// be reported regularly about the sender.
|
||||
ProfileExtensions []byte
|
||||
}
|
||||
|
||||
var _ Packet = (*SenderReport)(nil) // assert is a Packet
|
||||
|
||||
const (
|
||||
srHeaderLength = 24
|
||||
srSSRCOffset = 0
|
||||
srNTPOffset = srSSRCOffset + ssrcLength
|
||||
ntpTimeLength = 8
|
||||
srRTPOffset = srNTPOffset + ntpTimeLength
|
||||
rtpTimeLength = 4
|
||||
srPacketCountOffset = srRTPOffset + rtpTimeLength
|
||||
srPacketCountLength = 4
|
||||
srOctetCountOffset = srPacketCountOffset + srPacketCountLength
|
||||
srOctetCountLength = 4
|
||||
srReportOffset = srOctetCountOffset + srOctetCountLength
|
||||
)
|
||||
|
||||
// Marshal encodes the SenderReport in binary
|
||||
func (r SenderReport) Marshal() ([]byte, error) {
|
||||
/*
|
||||
* 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
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* header |V=2|P| RC | PT=SR=200 | length |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | SSRC of sender |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* sender | NTP timestamp, most significant word |
|
||||
* info +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | NTP timestamp, least significant word |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | RTP timestamp |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | sender's packet count |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | sender's octet count |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* report | SSRC_1 (SSRC of first source) |
|
||||
* block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* 1 | fraction lost | cumulative number of packets lost |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | extended highest sequence number received |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | interarrival jitter |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | last SR (LSR) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | delay since last SR (DLSR) |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* report | SSRC_2 (SSRC of second source) |
|
||||
* block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* 2 : ... :
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* | profile-specific extensions |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
rawPacket := make([]byte, r.len())
|
||||
packetBody := rawPacket[headerLength:]
|
||||
|
||||
binary.BigEndian.PutUint32(packetBody[srSSRCOffset:], r.SSRC)
|
||||
binary.BigEndian.PutUint64(packetBody[srNTPOffset:], r.NTPTime)
|
||||
binary.BigEndian.PutUint32(packetBody[srRTPOffset:], r.RTPTime)
|
||||
binary.BigEndian.PutUint32(packetBody[srPacketCountOffset:], r.PacketCount)
|
||||
binary.BigEndian.PutUint32(packetBody[srOctetCountOffset:], r.OctetCount)
|
||||
|
||||
offset := srHeaderLength
|
||||
for _, rp := range r.Reports {
|
||||
data, err := rp.Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(packetBody[offset:], data)
|
||||
offset += receptionReportLength
|
||||
}
|
||||
|
||||
if len(r.Reports) > countMax {
|
||||
return nil, errTooManyReports
|
||||
}
|
||||
|
||||
copy(packetBody[offset:], r.ProfileExtensions)
|
||||
|
||||
hData, err := r.Header().Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(rawPacket, hData)
|
||||
|
||||
return rawPacket, nil
|
||||
}
|
||||
|
||||
// Unmarshal decodes the SenderReport from binary
|
||||
func (r *SenderReport) Unmarshal(rawPacket []byte) error {
|
||||
/*
|
||||
* 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
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* header |V=2|P| RC | PT=SR=200 | length |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | SSRC of sender |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* sender | NTP timestamp, most significant word |
|
||||
* info +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | NTP timestamp, least significant word |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | RTP timestamp |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | sender's packet count |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | sender's octet count |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* report | SSRC_1 (SSRC of first source) |
|
||||
* block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* 1 | fraction lost | cumulative number of packets lost |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | extended highest sequence number received |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | interarrival jitter |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | last SR (LSR) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | delay since last SR (DLSR) |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* report | SSRC_2 (SSRC of second source) |
|
||||
* block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* 2 : ... :
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* | profile-specific extensions |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
if len(rawPacket) < (headerLength + srHeaderLength) {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
var h Header
|
||||
if err := h.Unmarshal(rawPacket); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if h.Type != TypeSenderReport {
|
||||
return errWrongType
|
||||
}
|
||||
|
||||
packetBody := rawPacket[headerLength:]
|
||||
|
||||
r.SSRC = binary.BigEndian.Uint32(packetBody[srSSRCOffset:])
|
||||
r.NTPTime = binary.BigEndian.Uint64(packetBody[srNTPOffset:])
|
||||
r.RTPTime = binary.BigEndian.Uint32(packetBody[srRTPOffset:])
|
||||
r.PacketCount = binary.BigEndian.Uint32(packetBody[srPacketCountOffset:])
|
||||
r.OctetCount = binary.BigEndian.Uint32(packetBody[srOctetCountOffset:])
|
||||
|
||||
offset := srReportOffset
|
||||
for i := 0; i < int(h.Count); i++ {
|
||||
rrEnd := offset + receptionReportLength
|
||||
if rrEnd > len(packetBody) {
|
||||
return errPacketTooShort
|
||||
}
|
||||
rrBody := packetBody[offset : offset+receptionReportLength]
|
||||
offset = rrEnd
|
||||
|
||||
var rr ReceptionReport
|
||||
if err := rr.Unmarshal(rrBody); err != nil {
|
||||
return err
|
||||
}
|
||||
r.Reports = append(r.Reports, rr)
|
||||
}
|
||||
|
||||
if offset < len(packetBody) {
|
||||
r.ProfileExtensions = packetBody[offset:]
|
||||
}
|
||||
|
||||
if uint8(len(r.Reports)) != h.Count {
|
||||
return errInvalidHeader
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DestinationSSRC returns an array of SSRC values that this packet refers to.
|
||||
func (r *SenderReport) DestinationSSRC() []uint32 {
|
||||
out := make([]uint32, len(r.Reports)+1)
|
||||
for i, v := range r.Reports {
|
||||
out[i] = v.SSRC
|
||||
}
|
||||
out[len(r.Reports)] = r.SSRC
|
||||
return out
|
||||
}
|
||||
|
||||
func (r *SenderReport) len() int {
|
||||
repsLength := 0
|
||||
for _, rep := range r.Reports {
|
||||
repsLength += rep.len()
|
||||
}
|
||||
return headerLength + srHeaderLength + repsLength + len(r.ProfileExtensions)
|
||||
}
|
||||
|
||||
// Header returns the Header associated with this packet.
|
||||
func (r *SenderReport) Header() Header {
|
||||
return Header{
|
||||
Count: uint8(len(r.Reports)),
|
||||
Type: TypeSenderReport,
|
||||
Length: uint16((r.len() / 4) - 1),
|
||||
}
|
||||
}
|
||||
|
||||
func (r SenderReport) String() string {
|
||||
out := fmt.Sprintf("SenderReport from %x\n", r.SSRC)
|
||||
out += fmt.Sprintf("\tNTPTime:\t%d\n", r.NTPTime)
|
||||
out += fmt.Sprintf("\tRTPTIme:\t%d\n", r.RTPTime)
|
||||
out += fmt.Sprintf("\tPacketCount:\t%d\n", r.PacketCount)
|
||||
out += fmt.Sprintf("\tOctetCount:\t%d\n", r.OctetCount)
|
||||
|
||||
out += "\tSSRC \tLost\tLastSequence\n"
|
||||
for _, i := range r.Reports {
|
||||
out += fmt.Sprintf("\t%x\t%d/%d\t%d\n", i.SSRC, i.FractionLost, i.TotalLost, i.LastSequenceNumber)
|
||||
}
|
||||
out += fmt.Sprintf("\tProfile Extension Data: %v\n", r.ProfileExtensions)
|
||||
return out
|
||||
}
|
115
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/slice_loss_indication.go
generated
vendored
Normal file
115
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/slice_loss_indication.go
generated
vendored
Normal file
|
@ -0,0 +1,115 @@
|
|||
package rtcp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
// SLIEntry represents a single entry to the SLI packet's
|
||||
// list of lost slices.
|
||||
type SLIEntry struct {
|
||||
// ID of first lost slice
|
||||
First uint16
|
||||
|
||||
// Number of lost slices
|
||||
Number uint16
|
||||
|
||||
// ID of related picture
|
||||
Picture uint8
|
||||
}
|
||||
|
||||
// The SliceLossIndication packet informs the encoder about the loss of a picture slice
|
||||
type SliceLossIndication struct {
|
||||
// SSRC of sender
|
||||
SenderSSRC uint32
|
||||
|
||||
// SSRC of the media source
|
||||
MediaSSRC uint32
|
||||
|
||||
SLI []SLIEntry
|
||||
}
|
||||
|
||||
var _ Packet = (*SliceLossIndication)(nil) // assert is a Packet
|
||||
|
||||
const (
|
||||
sliLength = 2
|
||||
sliOffset = 8
|
||||
)
|
||||
|
||||
// Marshal encodes the SliceLossIndication in binary
|
||||
func (p SliceLossIndication) Marshal() ([]byte, error) {
|
||||
if len(p.SLI)+sliLength > math.MaxUint8 {
|
||||
return nil, errTooManyReports
|
||||
}
|
||||
|
||||
rawPacket := make([]byte, sliOffset+(len(p.SLI)*4))
|
||||
binary.BigEndian.PutUint32(rawPacket, p.SenderSSRC)
|
||||
binary.BigEndian.PutUint32(rawPacket[4:], p.MediaSSRC)
|
||||
for i, s := range p.SLI {
|
||||
sli := ((uint32(s.First) & 0x1FFF) << 19) |
|
||||
((uint32(s.Number) & 0x1FFF) << 6) |
|
||||
(uint32(s.Picture) & 0x3F)
|
||||
binary.BigEndian.PutUint32(rawPacket[sliOffset+(4*i):], sli)
|
||||
}
|
||||
hData, err := p.Header().Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return append(hData, rawPacket...), nil
|
||||
}
|
||||
|
||||
// Unmarshal decodes the SliceLossIndication from binary
|
||||
func (p *SliceLossIndication) Unmarshal(rawPacket []byte) error {
|
||||
if len(rawPacket) < (headerLength + ssrcLength) {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
var h Header
|
||||
if err := h.Unmarshal(rawPacket); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(rawPacket) < (headerLength + int(4*h.Length)) {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
if h.Type != TypeTransportSpecificFeedback || h.Count != FormatSLI {
|
||||
return errWrongType
|
||||
}
|
||||
|
||||
p.SenderSSRC = binary.BigEndian.Uint32(rawPacket[headerLength:])
|
||||
p.MediaSSRC = binary.BigEndian.Uint32(rawPacket[headerLength+ssrcLength:])
|
||||
for i := headerLength + sliOffset; i < (headerLength + int(h.Length*4)); i += 4 {
|
||||
sli := binary.BigEndian.Uint32(rawPacket[i:])
|
||||
p.SLI = append(p.SLI, SLIEntry{
|
||||
First: uint16((sli >> 19) & 0x1FFF),
|
||||
Number: uint16((sli >> 6) & 0x1FFF),
|
||||
Picture: uint8(sli & 0x3F),
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *SliceLossIndication) len() int {
|
||||
return headerLength + sliOffset + (len(p.SLI) * 4)
|
||||
}
|
||||
|
||||
// Header returns the Header associated with this packet.
|
||||
func (p *SliceLossIndication) Header() Header {
|
||||
return Header{
|
||||
Count: FormatSLI,
|
||||
Type: TypeTransportSpecificFeedback,
|
||||
Length: uint16((p.len() / 4) - 1),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *SliceLossIndication) String() string {
|
||||
return fmt.Sprintf("SliceLossIndication %x %x %+v", p.SenderSSRC, p.MediaSSRC, p.SLI)
|
||||
}
|
||||
|
||||
// DestinationSSRC returns an array of SSRC values that this packet refers to.
|
||||
func (p *SliceLossIndication) DestinationSSRC() []uint32 {
|
||||
return []uint32{p.MediaSSRC}
|
||||
}
|
352
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/source_description.go
generated
vendored
Normal file
352
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/source_description.go
generated
vendored
Normal file
|
@ -0,0 +1,352 @@
|
|||
package rtcp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// SDESType is the item type used in the RTCP SDES control packet.
|
||||
type SDESType uint8
|
||||
|
||||
// RTP SDES item types registered with IANA. See: https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml#rtp-parameters-5
|
||||
const (
|
||||
SDESEnd SDESType = iota // end of SDES list RFC 3550, 6.5
|
||||
SDESCNAME // canonical name RFC 3550, 6.5.1
|
||||
SDESName // user name RFC 3550, 6.5.2
|
||||
SDESEmail // user's electronic mail address RFC 3550, 6.5.3
|
||||
SDESPhone // user's phone number RFC 3550, 6.5.4
|
||||
SDESLocation // geographic user location RFC 3550, 6.5.5
|
||||
SDESTool // name of application or tool RFC 3550, 6.5.6
|
||||
SDESNote // notice about the source RFC 3550, 6.5.7
|
||||
SDESPrivate // private extensions RFC 3550, 6.5.8 (not implemented)
|
||||
)
|
||||
|
||||
func (s SDESType) String() string {
|
||||
switch s {
|
||||
case SDESEnd:
|
||||
return "END"
|
||||
case SDESCNAME:
|
||||
return "CNAME"
|
||||
case SDESName:
|
||||
return "NAME"
|
||||
case SDESEmail:
|
||||
return "EMAIL"
|
||||
case SDESPhone:
|
||||
return "PHONE"
|
||||
case SDESLocation:
|
||||
return "LOC"
|
||||
case SDESTool:
|
||||
return "TOOL"
|
||||
case SDESNote:
|
||||
return "NOTE"
|
||||
case SDESPrivate:
|
||||
return "PRIV"
|
||||
default:
|
||||
return string(s)
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
sdesSourceLen = 4
|
||||
sdesTypeLen = 1
|
||||
sdesTypeOffset = 0
|
||||
sdesOctetCountLen = 1
|
||||
sdesOctetCountOffset = 1
|
||||
sdesMaxOctetCount = (1 << 8) - 1
|
||||
sdesTextOffset = 2
|
||||
)
|
||||
|
||||
// A SourceDescription (SDES) packet describes the sources in an RTP stream.
|
||||
type SourceDescription struct {
|
||||
Chunks []SourceDescriptionChunk
|
||||
}
|
||||
|
||||
var _ Packet = (*SourceDescription)(nil) // assert is a Packet
|
||||
|
||||
// Marshal encodes the SourceDescription in binary
|
||||
func (s SourceDescription) Marshal() ([]byte, error) {
|
||||
/*
|
||||
* 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
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* header |V=2|P| SC | PT=SDES=202 | length |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* chunk | SSRC/CSRC_1 |
|
||||
* 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | SDES items |
|
||||
* | ... |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* chunk | SSRC/CSRC_2 |
|
||||
* 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | SDES items |
|
||||
* | ... |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*/
|
||||
|
||||
rawPacket := make([]byte, s.len())
|
||||
packetBody := rawPacket[headerLength:]
|
||||
|
||||
chunkOffset := 0
|
||||
for _, c := range s.Chunks {
|
||||
data, err := c.Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(packetBody[chunkOffset:], data)
|
||||
chunkOffset += len(data)
|
||||
}
|
||||
|
||||
if len(s.Chunks) > countMax {
|
||||
return nil, errTooManyChunks
|
||||
}
|
||||
|
||||
hData, err := s.Header().Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(rawPacket, hData)
|
||||
|
||||
return rawPacket, nil
|
||||
}
|
||||
|
||||
// Unmarshal decodes the SourceDescription from binary
|
||||
func (s *SourceDescription) Unmarshal(rawPacket []byte) error {
|
||||
/*
|
||||
* 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
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* header |V=2|P| SC | PT=SDES=202 | length |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* chunk | SSRC/CSRC_1 |
|
||||
* 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | SDES items |
|
||||
* | ... |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* chunk | SSRC/CSRC_2 |
|
||||
* 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | SDES items |
|
||||
* | ... |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*/
|
||||
|
||||
var h Header
|
||||
if err := h.Unmarshal(rawPacket); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if h.Type != TypeSourceDescription {
|
||||
return errWrongType
|
||||
}
|
||||
|
||||
for i := headerLength; i < len(rawPacket); {
|
||||
var chunk SourceDescriptionChunk
|
||||
if err := chunk.Unmarshal(rawPacket[i:]); err != nil {
|
||||
return err
|
||||
}
|
||||
s.Chunks = append(s.Chunks, chunk)
|
||||
|
||||
i += chunk.len()
|
||||
}
|
||||
|
||||
if len(s.Chunks) != int(h.Count) {
|
||||
return errInvalidHeader
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SourceDescription) len() int {
|
||||
chunksLength := 0
|
||||
for _, c := range s.Chunks {
|
||||
chunksLength += c.len()
|
||||
}
|
||||
return headerLength + chunksLength
|
||||
}
|
||||
|
||||
// Header returns the Header associated with this packet.
|
||||
func (s *SourceDescription) Header() Header {
|
||||
return Header{
|
||||
Count: uint8(len(s.Chunks)),
|
||||
Type: TypeSourceDescription,
|
||||
Length: uint16((s.len() / 4) - 1),
|
||||
}
|
||||
}
|
||||
|
||||
// A SourceDescriptionChunk contains items describing a single RTP source
|
||||
type SourceDescriptionChunk struct {
|
||||
// The source (ssrc) or contributing source (csrc) identifier this packet describes
|
||||
Source uint32
|
||||
Items []SourceDescriptionItem
|
||||
}
|
||||
|
||||
// Marshal encodes the SourceDescriptionChunk in binary
|
||||
func (s SourceDescriptionChunk) Marshal() ([]byte, error) {
|
||||
/*
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* | SSRC/CSRC_1 |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | SDES items |
|
||||
* | ... |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*/
|
||||
|
||||
rawPacket := make([]byte, sdesSourceLen)
|
||||
binary.BigEndian.PutUint32(rawPacket, s.Source)
|
||||
|
||||
for _, it := range s.Items {
|
||||
data, err := it.Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rawPacket = append(rawPacket, data...)
|
||||
}
|
||||
|
||||
// The list of items in each chunk MUST be terminated by one or more null octets
|
||||
rawPacket = append(rawPacket, uint8(SDESEnd))
|
||||
|
||||
// additional null octets MUST be included if needed to pad until the next 32-bit boundary
|
||||
rawPacket = append(rawPacket, make([]byte, getPadding(len(rawPacket)))...)
|
||||
|
||||
return rawPacket, nil
|
||||
}
|
||||
|
||||
// Unmarshal decodes the SourceDescriptionChunk from binary
|
||||
func (s *SourceDescriptionChunk) Unmarshal(rawPacket []byte) error {
|
||||
/*
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* | SSRC/CSRC_1 |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | SDES items |
|
||||
* | ... |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*/
|
||||
|
||||
if len(rawPacket) < (sdesSourceLen + sdesTypeLen) {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
s.Source = binary.BigEndian.Uint32(rawPacket)
|
||||
|
||||
for i := 4; i < len(rawPacket); {
|
||||
if pktType := SDESType(rawPacket[i]); pktType == SDESEnd {
|
||||
return nil
|
||||
}
|
||||
|
||||
var it SourceDescriptionItem
|
||||
if err := it.Unmarshal(rawPacket[i:]); err != nil {
|
||||
return err
|
||||
}
|
||||
s.Items = append(s.Items, it)
|
||||
i += it.len()
|
||||
}
|
||||
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
func (s SourceDescriptionChunk) len() int {
|
||||
len := sdesSourceLen
|
||||
for _, it := range s.Items {
|
||||
len += it.len()
|
||||
}
|
||||
len += sdesTypeLen // for terminating null octet
|
||||
|
||||
// align to 32-bit boundary
|
||||
len += getPadding(len)
|
||||
|
||||
return len
|
||||
}
|
||||
|
||||
// A SourceDescriptionItem is a part of a SourceDescription that describes a stream.
|
||||
type SourceDescriptionItem struct {
|
||||
// The type identifier for this item. eg, SDESCNAME for canonical name description.
|
||||
//
|
||||
// Type zero or SDESEnd is interpreted as the end of an item list and cannot be used.
|
||||
Type SDESType
|
||||
// Text is a unicode text blob associated with the item. Its meaning varies based on the item's Type.
|
||||
Text string
|
||||
}
|
||||
|
||||
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
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | CNAME=1 | length | user and domain name ...
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
return sdesTypeLen + sdesOctetCountLen + len([]byte(s.Text))
|
||||
}
|
||||
|
||||
// Marshal encodes the SourceDescriptionItem in binary
|
||||
func (s SourceDescriptionItem) Marshal() ([]byte, error) {
|
||||
/*
|
||||
* 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
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | CNAME=1 | length | user and domain name ...
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
if s.Type == SDESEnd {
|
||||
return nil, errSDESMissingType
|
||||
}
|
||||
|
||||
rawPacket := make([]byte, sdesTypeLen+sdesOctetCountLen)
|
||||
|
||||
rawPacket[sdesTypeOffset] = uint8(s.Type)
|
||||
|
||||
txtBytes := []byte(s.Text)
|
||||
octetCount := len(txtBytes)
|
||||
if octetCount > sdesMaxOctetCount {
|
||||
return nil, errSDESTextTooLong
|
||||
}
|
||||
rawPacket[sdesOctetCountOffset] = uint8(octetCount)
|
||||
|
||||
rawPacket = append(rawPacket, txtBytes...)
|
||||
|
||||
return rawPacket, nil
|
||||
}
|
||||
|
||||
// Unmarshal decodes the SourceDescriptionItem from binary
|
||||
func (s *SourceDescriptionItem) Unmarshal(rawPacket []byte) error {
|
||||
/*
|
||||
* 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
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | CNAME=1 | length | user and domain name ...
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
if len(rawPacket) < (sdesTypeLen + sdesOctetCountLen) {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
s.Type = SDESType(rawPacket[sdesTypeOffset])
|
||||
|
||||
octetCount := int(rawPacket[sdesOctetCountOffset])
|
||||
if sdesTextOffset+octetCount > len(rawPacket) {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
txtBytes := rawPacket[sdesTextOffset : sdesTextOffset+octetCount]
|
||||
s.Text = string(txtBytes)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DestinationSSRC returns an array of SSRC values that this packet refers to.
|
||||
func (s *SourceDescription) DestinationSSRC() []uint32 {
|
||||
out := make([]uint32, len(s.Chunks))
|
||||
for i, v := range s.Chunks {
|
||||
out[i] = v.Source
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (s *SourceDescription) String() string {
|
||||
out := "Source Description:\n"
|
||||
for _, c := range s.Chunks {
|
||||
out += fmt.Sprintf("\t%x: %s\n", c.Source, c.Items)
|
||||
}
|
||||
return out
|
||||
}
|
560
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/transport_layer_cc.go
generated
vendored
Normal file
560
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/transport_layer_cc.go
generated
vendored
Normal file
|
@ -0,0 +1,560 @@
|
|||
package rtcp
|
||||
|
||||
// Author: adwpc
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
// https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#page-5
|
||||
// 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
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// |V=2|P| FMT=15 | PT=205 | length |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | SSRC of packet sender |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | SSRC of media source |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | base sequence number | packet status count |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | reference time | fb pkt. count |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | packet chunk | packet chunk |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// . .
|
||||
// . .
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | packet chunk | recv delta | recv delta |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// . .
|
||||
// . .
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | recv delta | recv delta | zero padding |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
// for packet status chunk
|
||||
const (
|
||||
// type of packet status chunk
|
||||
TypeTCCRunLengthChunk = 0
|
||||
TypeTCCStatusVectorChunk = 1
|
||||
|
||||
// len of packet status chunk
|
||||
packetStatusChunkLength = 2
|
||||
)
|
||||
|
||||
// type of packet status symbol and recv delta
|
||||
const (
|
||||
// https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#section-3.1.1
|
||||
TypeTCCPacketNotReceived = uint16(iota)
|
||||
TypeTCCPacketReceivedSmallDelta
|
||||
TypeTCCPacketReceivedLargeDelta
|
||||
// https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#page-7
|
||||
// see Example 2: "packet received, w/o recv delta"
|
||||
TypeTCCPacketReceivedWithoutDelta
|
||||
)
|
||||
|
||||
// for status vector chunk
|
||||
const (
|
||||
// https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#section-3.1.4
|
||||
TypeTCCSymbolSizeOneBit = 0
|
||||
TypeTCCSymbolSizeTwoBit = 1
|
||||
|
||||
// Notice: RFC is wrong: "packet received" (0) and "packet not received" (1)
|
||||
// if S == TypeTCCSymbolSizeOneBit, symbol list will be: TypeTCCPacketNotReceived TypeTCCPacketReceivedSmallDelta
|
||||
// if S == TypeTCCSymbolSizeTwoBit, symbol list will be same as above:
|
||||
)
|
||||
|
||||
func numOfBitsOfSymbolSize() map[uint16]uint16 {
|
||||
return map[uint16]uint16{
|
||||
TypeTCCSymbolSizeOneBit: 1,
|
||||
TypeTCCSymbolSizeTwoBit: 2,
|
||||
}
|
||||
}
|
||||
|
||||
var _ Packet = (*TransportLayerCC)(nil) // assert is a Packet
|
||||
|
||||
var (
|
||||
errPacketStatusChunkLength = errors.New("packet status chunk must be 2 bytes")
|
||||
errDeltaExceedLimit = errors.New("delta exceed limit")
|
||||
)
|
||||
|
||||
// PacketStatusChunk has two kinds:
|
||||
// RunLengthChunk and StatusVectorChunk
|
||||
type PacketStatusChunk interface {
|
||||
Marshal() ([]byte, error)
|
||||
Unmarshal(rawPacket []byte) error
|
||||
}
|
||||
|
||||
// RunLengthChunk T=TypeTCCRunLengthChunk
|
||||
// 0 1
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// |T| S | Run Length |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
type RunLengthChunk struct {
|
||||
PacketStatusChunk
|
||||
|
||||
// T = TypeTCCRunLengthChunk
|
||||
Type uint16
|
||||
|
||||
// S: type of packet status
|
||||
// kind: TypeTCCPacketNotReceived or...
|
||||
PacketStatusSymbol uint16
|
||||
|
||||
// RunLength: count of S
|
||||
RunLength uint16
|
||||
}
|
||||
|
||||
// Marshal ..
|
||||
func (r RunLengthChunk) Marshal() ([]byte, error) {
|
||||
chunk := make([]byte, 2)
|
||||
|
||||
// append 1 bit '0'
|
||||
dst, err := setNBitsOfUint16(0, 1, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// append 2 bit PacketStatusSymbol
|
||||
dst, err = setNBitsOfUint16(dst, 2, 1, r.PacketStatusSymbol)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// append 13 bit RunLength
|
||||
dst, err = setNBitsOfUint16(dst, 13, 3, r.RunLength)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
binary.BigEndian.PutUint16(chunk, dst)
|
||||
return chunk, nil
|
||||
}
|
||||
|
||||
// Unmarshal ..
|
||||
func (r *RunLengthChunk) Unmarshal(rawPacket []byte) error {
|
||||
if len(rawPacket) != packetStatusChunkLength {
|
||||
return errPacketStatusChunkLength
|
||||
}
|
||||
|
||||
// record type
|
||||
r.Type = TypeTCCRunLengthChunk
|
||||
|
||||
// get PacketStatusSymbol
|
||||
// r.PacketStatusSymbol = uint16(rawPacket[0] >> 5 & 0x03)
|
||||
r.PacketStatusSymbol = getNBitsFromByte(rawPacket[0], 1, 2)
|
||||
|
||||
// get RunLength
|
||||
// r.RunLength = uint16(rawPacket[0]&0x1F)*256 + uint16(rawPacket[1])
|
||||
r.RunLength = getNBitsFromByte(rawPacket[0], 3, 5)<<8 + uint16(rawPacket[1])
|
||||
return nil
|
||||
}
|
||||
|
||||
// StatusVectorChunk T=typeStatusVecotrChunk
|
||||
// 0 1
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// |T|S| symbol list |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
type StatusVectorChunk struct {
|
||||
PacketStatusChunk
|
||||
// T = TypeTCCRunLengthChunk
|
||||
Type uint16
|
||||
|
||||
// TypeTCCSymbolSizeOneBit or TypeTCCSymbolSizeTwoBit
|
||||
SymbolSize uint16
|
||||
|
||||
// when SymbolSize = TypeTCCSymbolSizeOneBit, SymbolList is 14*1bit:
|
||||
// TypeTCCSymbolListPacketReceived or TypeTCCSymbolListPacketNotReceived
|
||||
// when SymbolSize = TypeTCCSymbolSizeTwoBit, SymbolList is 7*2bit:
|
||||
// TypeTCCPacketNotReceived TypeTCCPacketReceivedSmallDelta TypeTCCPacketReceivedLargeDelta or typePacketReserved
|
||||
SymbolList []uint16
|
||||
}
|
||||
|
||||
// Marshal ..
|
||||
func (r StatusVectorChunk) Marshal() ([]byte, error) {
|
||||
chunk := make([]byte, 2)
|
||||
|
||||
// set first bit '1'
|
||||
dst, err := setNBitsOfUint16(0, 1, 0, 1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// set second bit SymbolSize
|
||||
dst, err = setNBitsOfUint16(dst, 1, 1, r.SymbolSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
numOfBits := numOfBitsOfSymbolSize()[r.SymbolSize]
|
||||
// append 14 bit SymbolList
|
||||
for i, s := range r.SymbolList {
|
||||
index := numOfBits*uint16(i) + 2
|
||||
dst, err = setNBitsOfUint16(dst, numOfBits, index, s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
binary.BigEndian.PutUint16(chunk, dst)
|
||||
// set SymbolList(bit8-15)
|
||||
// chunk[1] = uint8(r.SymbolList) & 0x0f
|
||||
return chunk, nil
|
||||
}
|
||||
|
||||
// Unmarshal ..
|
||||
func (r *StatusVectorChunk) Unmarshal(rawPacket []byte) error {
|
||||
if len(rawPacket) != packetStatusChunkLength {
|
||||
return errPacketStatusChunkLength
|
||||
}
|
||||
|
||||
r.Type = TypeTCCStatusVectorChunk
|
||||
r.SymbolSize = getNBitsFromByte(rawPacket[0], 1, 1)
|
||||
|
||||
if r.SymbolSize == TypeTCCSymbolSizeOneBit {
|
||||
for i := uint16(0); i < 6; i++ {
|
||||
r.SymbolList = append(r.SymbolList, getNBitsFromByte(rawPacket[0], 2+i, 1))
|
||||
}
|
||||
for i := uint16(0); i < 8; i++ {
|
||||
r.SymbolList = append(r.SymbolList, getNBitsFromByte(rawPacket[1], i, 1))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if r.SymbolSize == TypeTCCSymbolSizeTwoBit {
|
||||
for i := uint16(0); i < 3; i++ {
|
||||
r.SymbolList = append(r.SymbolList, getNBitsFromByte(rawPacket[0], 2+i*2, 2))
|
||||
}
|
||||
for i := uint16(0); i < 4; i++ {
|
||||
r.SymbolList = append(r.SymbolList, getNBitsFromByte(rawPacket[1], i*2, 2))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
r.SymbolSize = getNBitsFromByte(rawPacket[0], 2, 6)<<8 + uint16(rawPacket[1])
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
// TypeTCCDeltaScaleFactor https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#section-3.1.5
|
||||
TypeTCCDeltaScaleFactor = 250
|
||||
)
|
||||
|
||||
// RecvDelta are represented as multiples of 250us
|
||||
// small delta is 1 byte: [0,63.75]ms = [0, 63750]us = [0, 255]*250us
|
||||
// big delta is 2 bytes: [-8192.0, 8191.75]ms = [-8192000, 8191750]us = [-32768, 32767]*250us
|
||||
// https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#section-3.1.5
|
||||
type RecvDelta struct {
|
||||
Type uint16
|
||||
// us
|
||||
Delta int64
|
||||
}
|
||||
|
||||
// Marshal ..
|
||||
func (r RecvDelta) Marshal() ([]byte, error) {
|
||||
delta := r.Delta / TypeTCCDeltaScaleFactor
|
||||
|
||||
// small delta
|
||||
if r.Type == TypeTCCPacketReceivedSmallDelta && delta >= 0 && delta <= math.MaxUint8 {
|
||||
deltaChunk := make([]byte, 1)
|
||||
deltaChunk[0] = byte(delta)
|
||||
return deltaChunk, nil
|
||||
}
|
||||
|
||||
// big delta
|
||||
if r.Type == TypeTCCPacketReceivedLargeDelta && delta >= math.MinInt16 && delta <= math.MaxInt16 {
|
||||
deltaChunk := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(deltaChunk, uint16(delta))
|
||||
return deltaChunk, nil
|
||||
}
|
||||
|
||||
// overflow
|
||||
return nil, errDeltaExceedLimit
|
||||
}
|
||||
|
||||
// Unmarshal ..
|
||||
func (r *RecvDelta) Unmarshal(rawPacket []byte) error {
|
||||
chunkLen := len(rawPacket)
|
||||
|
||||
// must be 1 or 2 bytes
|
||||
if chunkLen != 1 && chunkLen != 2 {
|
||||
return errDeltaExceedLimit
|
||||
}
|
||||
|
||||
if chunkLen == 1 {
|
||||
r.Type = TypeTCCPacketReceivedSmallDelta
|
||||
r.Delta = TypeTCCDeltaScaleFactor * int64(rawPacket[0])
|
||||
return nil
|
||||
}
|
||||
|
||||
r.Type = TypeTCCPacketReceivedLargeDelta
|
||||
r.Delta = TypeTCCDeltaScaleFactor * int64(int16(binary.BigEndian.Uint16(rawPacket)))
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
// the offset after header
|
||||
baseSequenceNumberOffset = 8
|
||||
packetStatusCountOffset = 10
|
||||
referenceTimeOffset = 12
|
||||
fbPktCountOffset = 15
|
||||
packetChunkOffset = 16
|
||||
)
|
||||
|
||||
// TransportLayerCC for sender-BWE
|
||||
// https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#page-5
|
||||
type TransportLayerCC struct {
|
||||
// header
|
||||
Header Header
|
||||
|
||||
// SSRC of sender
|
||||
SenderSSRC uint32
|
||||
|
||||
// SSRC of the media source
|
||||
MediaSSRC uint32
|
||||
|
||||
// Transport wide sequence of rtp extension
|
||||
BaseSequenceNumber uint16
|
||||
|
||||
// PacketStatusCount
|
||||
PacketStatusCount uint16
|
||||
|
||||
// ReferenceTime
|
||||
ReferenceTime uint32
|
||||
|
||||
// FbPktCount
|
||||
FbPktCount uint8
|
||||
|
||||
// PacketChunks
|
||||
PacketChunks []PacketStatusChunk
|
||||
|
||||
// RecvDeltas
|
||||
RecvDeltas []*RecvDelta
|
||||
}
|
||||
|
||||
// Header returns the Header associated with this packet.
|
||||
// func (t *TransportLayerCC) Header() Header {
|
||||
// return t.Header
|
||||
// return Header{
|
||||
// Padding: true,
|
||||
// Count: FormatTCC,
|
||||
// Type: TypeTCCTransportSpecificFeedback,
|
||||
// // https://tools.ietf.org/html/rfc4585#page-33
|
||||
// Length: uint16((t.len() / 4) - 1),
|
||||
// }
|
||||
// }
|
||||
|
||||
func (t *TransportLayerCC) packetLen() uint16 {
|
||||
n := uint16(headerLength + packetChunkOffset + len(t.PacketChunks)*2)
|
||||
for _, d := range t.RecvDeltas {
|
||||
delta := d.Delta / TypeTCCDeltaScaleFactor
|
||||
|
||||
// small delta
|
||||
if delta >= 0 && delta <= math.MaxUint8 {
|
||||
n++
|
||||
} else {
|
||||
n += 2
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// Len return total bytes with padding
|
||||
func (t *TransportLayerCC) Len() uint16 {
|
||||
n := t.packetLen()
|
||||
// has padding
|
||||
if n%4 != 0 {
|
||||
n = (n/4 + 1) * 4
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
func (t TransportLayerCC) String() string {
|
||||
out := fmt.Sprintf("TransportLayerCC:\n\tHeader %v\n", t.Header)
|
||||
out += fmt.Sprintf("TransportLayerCC:\n\tSender Ssrc %d\n", t.SenderSSRC)
|
||||
out += fmt.Sprintf("\tMedia Ssrc %d\n", t.MediaSSRC)
|
||||
out += fmt.Sprintf("\tBase Sequence Number %d\n", t.BaseSequenceNumber)
|
||||
out += fmt.Sprintf("\tStatus Count %d\n", t.PacketStatusCount)
|
||||
out += fmt.Sprintf("\tReference Time %d\n", t.ReferenceTime)
|
||||
out += fmt.Sprintf("\tFeedback Packet Count %d\n", t.FbPktCount)
|
||||
out += "\tPacketChunks "
|
||||
for _, chunk := range t.PacketChunks {
|
||||
out += fmt.Sprintf("%+v ", chunk)
|
||||
}
|
||||
out += "\n\tRecvDeltas "
|
||||
for _, delta := range t.RecvDeltas {
|
||||
out += fmt.Sprintf("%+v ", delta)
|
||||
}
|
||||
out += "\n"
|
||||
return out
|
||||
}
|
||||
|
||||
// Marshal encodes the TransportLayerCC in binary
|
||||
func (t TransportLayerCC) Marshal() ([]byte, error) {
|
||||
header, err := t.Header.Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
payload := make([]byte, t.Len()-headerLength)
|
||||
binary.BigEndian.PutUint32(payload, t.SenderSSRC)
|
||||
binary.BigEndian.PutUint32(payload[4:], t.MediaSSRC)
|
||||
binary.BigEndian.PutUint16(payload[baseSequenceNumberOffset:], t.BaseSequenceNumber)
|
||||
binary.BigEndian.PutUint16(payload[packetStatusCountOffset:], t.PacketStatusCount)
|
||||
ReferenceTimeAndFbPktCount := appendNBitsToUint32(0, 24, t.ReferenceTime)
|
||||
ReferenceTimeAndFbPktCount = appendNBitsToUint32(ReferenceTimeAndFbPktCount, 8, uint32(t.FbPktCount))
|
||||
binary.BigEndian.PutUint32(payload[referenceTimeOffset:], ReferenceTimeAndFbPktCount)
|
||||
|
||||
for i, chunk := range t.PacketChunks {
|
||||
b, err := chunk.Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(payload[packetChunkOffset+i*2:], b)
|
||||
}
|
||||
|
||||
recvDeltaOffset := packetChunkOffset + len(t.PacketChunks)*2
|
||||
var i int
|
||||
for _, delta := range t.RecvDeltas {
|
||||
b, err := delta.Marshal()
|
||||
if err == nil {
|
||||
copy(payload[recvDeltaOffset+i:], b)
|
||||
i++
|
||||
if delta.Type == TypeTCCPacketReceivedLargeDelta {
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if t.Header.Padding {
|
||||
payload[len(payload)-1] = uint8(t.Len() - t.packetLen())
|
||||
}
|
||||
|
||||
return append(header, payload...), nil
|
||||
}
|
||||
|
||||
// Unmarshal ..
|
||||
func (t *TransportLayerCC) Unmarshal(rawPacket []byte) error { //nolint:gocognit
|
||||
if len(rawPacket) < (headerLength + ssrcLength) {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
if err := t.Header.Unmarshal(rawPacket); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// https://tools.ietf.org/html/rfc4585#page-33
|
||||
// header's length + payload's length
|
||||
totalLength := 4 * (t.Header.Length + 1)
|
||||
|
||||
if totalLength <= headerLength+packetChunkOffset {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
if len(rawPacket) < int(totalLength) {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
if t.Header.Type != TypeTransportSpecificFeedback || t.Header.Count != FormatTCC {
|
||||
return errWrongType
|
||||
}
|
||||
|
||||
t.SenderSSRC = binary.BigEndian.Uint32(rawPacket[headerLength:])
|
||||
t.MediaSSRC = binary.BigEndian.Uint32(rawPacket[headerLength+ssrcLength:])
|
||||
t.BaseSequenceNumber = binary.BigEndian.Uint16(rawPacket[headerLength+baseSequenceNumberOffset:])
|
||||
t.PacketStatusCount = binary.BigEndian.Uint16(rawPacket[headerLength+packetStatusCountOffset:])
|
||||
t.ReferenceTime = get24BitsFromBytes(rawPacket[headerLength+referenceTimeOffset : headerLength+referenceTimeOffset+3])
|
||||
t.FbPktCount = rawPacket[headerLength+fbPktCountOffset]
|
||||
|
||||
packetStatusPos := uint16(headerLength + packetChunkOffset)
|
||||
var processedPacketNum uint16
|
||||
for processedPacketNum < t.PacketStatusCount {
|
||||
if packetStatusPos+packetStatusChunkLength >= totalLength {
|
||||
return errPacketTooShort
|
||||
}
|
||||
typ := getNBitsFromByte(rawPacket[packetStatusPos : packetStatusPos+1][0], 0, 1)
|
||||
var iPacketStatus PacketStatusChunk
|
||||
switch typ {
|
||||
case TypeTCCRunLengthChunk:
|
||||
packetStatus := &RunLengthChunk{Type: typ}
|
||||
iPacketStatus = packetStatus
|
||||
err := packetStatus.Unmarshal(rawPacket[packetStatusPos : packetStatusPos+2])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
packetNumberToProcess := min(t.PacketStatusCount-processedPacketNum, packetStatus.RunLength)
|
||||
if packetStatus.PacketStatusSymbol == TypeTCCPacketReceivedSmallDelta ||
|
||||
packetStatus.PacketStatusSymbol == TypeTCCPacketReceivedLargeDelta {
|
||||
for j := uint16(0); j < packetNumberToProcess; j++ {
|
||||
t.RecvDeltas = append(t.RecvDeltas, &RecvDelta{Type: packetStatus.PacketStatusSymbol})
|
||||
}
|
||||
}
|
||||
processedPacketNum += packetNumberToProcess
|
||||
case TypeTCCStatusVectorChunk:
|
||||
packetStatus := &StatusVectorChunk{Type: typ}
|
||||
iPacketStatus = packetStatus
|
||||
err := packetStatus.Unmarshal(rawPacket[packetStatusPos : packetStatusPos+2])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if packetStatus.SymbolSize == TypeTCCSymbolSizeOneBit {
|
||||
for j := 0; j < len(packetStatus.SymbolList); j++ {
|
||||
if packetStatus.SymbolList[j] == TypeTCCPacketReceivedSmallDelta {
|
||||
t.RecvDeltas = append(t.RecvDeltas, &RecvDelta{Type: TypeTCCPacketReceivedSmallDelta})
|
||||
}
|
||||
}
|
||||
}
|
||||
if packetStatus.SymbolSize == TypeTCCSymbolSizeTwoBit {
|
||||
for j := 0; j < len(packetStatus.SymbolList); j++ {
|
||||
if packetStatus.SymbolList[j] == TypeTCCPacketReceivedSmallDelta || packetStatus.SymbolList[j] == TypeTCCPacketReceivedLargeDelta {
|
||||
t.RecvDeltas = append(t.RecvDeltas, &RecvDelta{Type: packetStatus.SymbolList[j]})
|
||||
}
|
||||
}
|
||||
}
|
||||
processedPacketNum += uint16(len(packetStatus.SymbolList))
|
||||
}
|
||||
packetStatusPos += packetStatusChunkLength
|
||||
t.PacketChunks = append(t.PacketChunks, iPacketStatus)
|
||||
}
|
||||
|
||||
recvDeltasPos := packetStatusPos
|
||||
for _, delta := range t.RecvDeltas {
|
||||
if recvDeltasPos >= totalLength {
|
||||
return errPacketTooShort
|
||||
}
|
||||
if delta.Type == TypeTCCPacketReceivedSmallDelta {
|
||||
err := delta.Unmarshal(rawPacket[recvDeltasPos : recvDeltasPos+1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
recvDeltasPos++
|
||||
}
|
||||
if delta.Type == TypeTCCPacketReceivedLargeDelta {
|
||||
err := delta.Unmarshal(rawPacket[recvDeltasPos : recvDeltasPos+2])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
recvDeltasPos += 2
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DestinationSSRC returns an array of SSRC values that this packet refers to.
|
||||
func (t TransportLayerCC) DestinationSSRC() []uint32 {
|
||||
return []uint32{t.MediaSSRC}
|
||||
}
|
||||
|
||||
func min(x, y uint16) uint16 {
|
||||
if x < y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
174
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/transport_layer_nack.go
generated
vendored
Normal file
174
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/transport_layer_nack.go
generated
vendored
Normal file
|
@ -0,0 +1,174 @@
|
|||
package rtcp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
// PacketBitmap shouldn't be used like a normal integral,
|
||||
// so it's type is masked here. Access it with PacketList().
|
||||
type PacketBitmap uint16
|
||||
|
||||
// NackPair is a wire-representation of a collection of
|
||||
// Lost RTP packets
|
||||
type NackPair struct {
|
||||
// ID of lost packets
|
||||
PacketID uint16
|
||||
|
||||
// Bitmask of following lost packets
|
||||
LostPackets PacketBitmap
|
||||
}
|
||||
|
||||
// The TransportLayerNack packet informs the encoder about the loss of a transport packet
|
||||
// IETF RFC 4585, Section 6.2.1
|
||||
// https://tools.ietf.org/html/rfc4585#section-6.2.1
|
||||
type TransportLayerNack struct {
|
||||
// SSRC of sender
|
||||
SenderSSRC uint32
|
||||
|
||||
// SSRC of the media source
|
||||
MediaSSRC uint32
|
||||
|
||||
Nacks []NackPair
|
||||
}
|
||||
|
||||
var _ Packet = (*TransportLayerNack)(nil) // assert is a Packet
|
||||
|
||||
// NackPairsFromSequenceNumbers generates a slice of NackPair from a list of SequenceNumbers
|
||||
// This handles generating the proper values for PacketID/LostPackets
|
||||
func NackPairsFromSequenceNumbers(sequenceNumbers []uint16) (pairs []NackPair) {
|
||||
if len(sequenceNumbers) == 0 {
|
||||
return []NackPair{}
|
||||
}
|
||||
|
||||
nackPair := &NackPair{PacketID: sequenceNumbers[0]}
|
||||
for i := 1; i < len(sequenceNumbers); i++ {
|
||||
m := sequenceNumbers[i]
|
||||
|
||||
if m-nackPair.PacketID > 16 {
|
||||
pairs = append(pairs, *nackPair)
|
||||
nackPair = &NackPair{PacketID: m}
|
||||
continue
|
||||
}
|
||||
|
||||
nackPair.LostPackets |= 1 << (m - nackPair.PacketID - 1)
|
||||
}
|
||||
pairs = append(pairs, *nackPair)
|
||||
return
|
||||
}
|
||||
|
||||
// Range calls f sequentially for each sequence number covered by n.
|
||||
// If f returns false, Range stops the iteration.
|
||||
func (n *NackPair) Range(f func(seqno uint16) bool) {
|
||||
more := f(n.PacketID)
|
||||
if !more {
|
||||
return
|
||||
}
|
||||
|
||||
b := n.LostPackets
|
||||
for i := uint16(0); b != 0; i++ {
|
||||
if (b & (1 << i)) != 0 {
|
||||
b &^= (1 << i)
|
||||
more = f(n.PacketID + i + 1)
|
||||
if !more {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PacketList returns a list of Nack'd packets that's referenced by a NackPair
|
||||
func (n *NackPair) PacketList() []uint16 {
|
||||
out := make([]uint16, 0, 17)
|
||||
n.Range(func(seqno uint16) bool {
|
||||
out = append(out, seqno)
|
||||
return true
|
||||
})
|
||||
return out
|
||||
}
|
||||
|
||||
const (
|
||||
tlnLength = 2
|
||||
nackOffset = 8
|
||||
)
|
||||
|
||||
// Marshal encodes the TransportLayerNack in binary
|
||||
func (p TransportLayerNack) Marshal() ([]byte, error) {
|
||||
if len(p.Nacks)+tlnLength > math.MaxUint8 {
|
||||
return nil, errTooManyReports
|
||||
}
|
||||
|
||||
rawPacket := make([]byte, nackOffset+(len(p.Nacks)*4))
|
||||
binary.BigEndian.PutUint32(rawPacket, p.SenderSSRC)
|
||||
binary.BigEndian.PutUint32(rawPacket[4:], p.MediaSSRC)
|
||||
for i := 0; i < len(p.Nacks); i++ {
|
||||
binary.BigEndian.PutUint16(rawPacket[nackOffset+(4*i):], p.Nacks[i].PacketID)
|
||||
binary.BigEndian.PutUint16(rawPacket[nackOffset+(4*i)+2:], uint16(p.Nacks[i].LostPackets))
|
||||
}
|
||||
h := p.Header()
|
||||
hData, err := h.Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return append(hData, rawPacket...), nil
|
||||
}
|
||||
|
||||
// Unmarshal decodes the TransportLayerNack from binary
|
||||
func (p *TransportLayerNack) Unmarshal(rawPacket []byte) error {
|
||||
if len(rawPacket) < (headerLength + ssrcLength) {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
var h Header
|
||||
if err := h.Unmarshal(rawPacket); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(rawPacket) < (headerLength + int(4*h.Length)) {
|
||||
return errPacketTooShort
|
||||
}
|
||||
|
||||
if h.Type != TypeTransportSpecificFeedback || h.Count != FormatTLN {
|
||||
return errWrongType
|
||||
}
|
||||
|
||||
p.SenderSSRC = binary.BigEndian.Uint32(rawPacket[headerLength:])
|
||||
p.MediaSSRC = binary.BigEndian.Uint32(rawPacket[headerLength+ssrcLength:])
|
||||
for i := headerLength + nackOffset; i < (headerLength + int(h.Length*4)); i += 4 {
|
||||
p.Nacks = append(p.Nacks, NackPair{
|
||||
binary.BigEndian.Uint16(rawPacket[i:]),
|
||||
PacketBitmap(binary.BigEndian.Uint16(rawPacket[i+2:])),
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *TransportLayerNack) len() int {
|
||||
return headerLength + nackOffset + (len(p.Nacks) * 4)
|
||||
}
|
||||
|
||||
// Header returns the Header associated with this packet.
|
||||
func (p *TransportLayerNack) Header() Header {
|
||||
return Header{
|
||||
Count: FormatTLN,
|
||||
Type: TypeTransportSpecificFeedback,
|
||||
Length: uint16((p.len() / 4) - 1),
|
||||
}
|
||||
}
|
||||
|
||||
func (p TransportLayerNack) String() string {
|
||||
out := fmt.Sprintf("TransportLayerNack from %x\n", p.SenderSSRC)
|
||||
out += fmt.Sprintf("\tMedia Ssrc %x\n", p.MediaSSRC)
|
||||
out += "\tID\tLostPackets\n"
|
||||
for _, i := range p.Nacks {
|
||||
out += fmt.Sprintf("\t%d\t%b\n", i.PacketID, i.LostPackets)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// DestinationSSRC returns an array of SSRC values that this packet refers to.
|
||||
func (p *TransportLayerNack) DestinationSSRC() []uint32 {
|
||||
return []uint32{p.MediaSSRC}
|
||||
}
|
38
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/util.go
generated
vendored
Normal file
38
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/util.go
generated
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
package rtcp
|
||||
|
||||
// getPadding Returns the padding required to make the length a multiple of 4
|
||||
func getPadding(len int) int {
|
||||
if len%4 == 0 {
|
||||
return 0
|
||||
}
|
||||
return 4 - (len % 4)
|
||||
}
|
||||
|
||||
// setNBitsOfUint16 will truncate the value to size, left-shift to startIndex position and set
|
||||
func setNBitsOfUint16(src, size, startIndex, val uint16) (uint16, error) {
|
||||
if startIndex+size > 16 {
|
||||
return 0, errInvalidSizeOrStartIndex
|
||||
}
|
||||
|
||||
// truncate val to size bits
|
||||
val &= (1 << size) - 1
|
||||
|
||||
return src | (val << (16 - size - startIndex)), nil
|
||||
}
|
||||
|
||||
// appendBit32 will left-shift and append n bits of val
|
||||
func appendNBitsToUint32(src, n, val uint32) uint32 {
|
||||
return (src << n) | (val & (0xFFFFFFFF >> (32 - n)))
|
||||
}
|
||||
|
||||
// getNBit get n bits from 1 byte, begin with a position
|
||||
func getNBitsFromByte(b byte, begin, n uint16) uint16 {
|
||||
endShift := 8 - (begin + n)
|
||||
mask := (0xFF >> begin) & uint8(0xFF<<endShift)
|
||||
return uint16(b&mask) >> endShift
|
||||
}
|
||||
|
||||
// get24BitFromBytes get 24bits from `[3]byte` slice
|
||||
func get24BitsFromBytes(b []byte) uint32 {
|
||||
return uint32(b[0])<<16 + uint32(b[1])<<8 + uint32(b[2])
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue