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/rtp/.gitignore
generated
vendored
Normal file
24
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/.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/rtp/.golangci.yml
generated
vendored
Normal file
89
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/.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/rtp/LICENSE
generated
vendored
Normal file
21
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/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.
|
53
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/README.md
generated
vendored
Normal file
53
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/README.md
generated
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
<h1 align="center">
|
||||
<br>
|
||||
Pion RTP
|
||||
<br>
|
||||
</h1>
|
||||
<h4 align="center">A Go implementation of RTP</h4>
|
||||
<p align="center">
|
||||
<a href="https://pion.ly"><img src="https://img.shields.io/badge/pion-rtp-gray.svg?longCache=true&colorB=brightgreen" alt="Pion RTP"></a>
|
||||
<a href="https://sourcegraph.com/github.com/pion/rtp?badge"><img src="https://sourcegraph.com/github.com/pion/rtp/-/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/rtp"><img src="https://travis-ci.org/pion/rtp.svg?branch=master" alt="Build Status"></a>
|
||||
<a href="https://pkg.go.dev/github.com/pion/rtp"><img src="https://godoc.org/github.com/pion/rtp?status.svg" alt="GoDoc"></a>
|
||||
<a href="https://codecov.io/gh/pion/rtp"><img src="https://codecov.io/gh/pion/rtp/branch/master/graph/badge.svg" alt="Coverage Status"></a>
|
||||
<a href="https://goreportcard.com/report/github.com/pion/rtp"><img src="https://goreportcard.com/badge/github.com/pion/rtp" 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>
|
||||
|
||||
### 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:
|
||||
|
||||
* [John Bradley](https://github.com/kc5nra) - *Original Author*
|
||||
* [Sean DuBois](https://github.com/Sean-Der) - *Original Author*
|
||||
* [Woodrow Douglass](https://github.com/wdouglass) *RTCP, RTP improvements, G.722 support, Bugfixes*
|
||||
* [Michael MacDonald](https://github.com/mjmac)
|
||||
* [Luke Curley](https://github.com/kixelated) *Performance*
|
||||
* [Antoine Baché](https://github.com/Antonito) *Fixed crashes*
|
||||
* [Hugo Arregui](https://github.com/hugoArregui)
|
||||
* [Raphael Derosso Pereira](https://github.com/raphaelpereira)
|
||||
* [Atsushi Watanabe](https://github.com/at-wat)
|
||||
* [adwpc](https://github.com/adwpc) *add transport-cc extension*
|
||||
* [Bao Nguyen](https://github.com/sysbot) *add VP9 noop, bug fixes.
|
||||
* [Tarrence van As](https://github.com/tarrencev) *add audio level extension*
|
||||
* [Simone Gotti](https://github.com/sgotti)
|
||||
* [Guilherme Souza](https://github.com/gqgs)
|
||||
* [Rob Lofthouse](https://github.com/roblofthouse)
|
||||
* [Kazuyuki Honda](https://github.com/hakobera)
|
||||
* [Haiyang Wang](https://github.com/ocean2811)
|
||||
* [lxb](https://github.com/lxb531)
|
||||
|
||||
### License
|
||||
MIT License - see [LICENSE](LICENSE) for full text
|
78
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/abssendtimeextension.go
generated
vendored
Normal file
78
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/abssendtimeextension.go
generated
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
package rtp
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
absSendTimeExtensionSize = 3
|
||||
)
|
||||
|
||||
// AbsSendTimeExtension is a extension payload format in
|
||||
// http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
|
||||
type AbsSendTimeExtension struct {
|
||||
Timestamp uint64
|
||||
}
|
||||
|
||||
// Marshal serializes the members to buffer.
|
||||
func (t *AbsSendTimeExtension) Marshal() ([]byte, error) {
|
||||
return []byte{
|
||||
byte(t.Timestamp & 0xFF0000 >> 16),
|
||||
byte(t.Timestamp & 0xFF00 >> 8),
|
||||
byte(t.Timestamp & 0xFF),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Unmarshal parses the passed byte slice and stores the result in the members.
|
||||
func (t *AbsSendTimeExtension) Unmarshal(rawData []byte) error {
|
||||
if len(rawData) < absSendTimeExtensionSize {
|
||||
return errTooSmall
|
||||
}
|
||||
t.Timestamp = uint64(rawData[0])<<16 | uint64(rawData[1])<<8 | uint64(rawData[2])
|
||||
return nil
|
||||
}
|
||||
|
||||
// Estimate absolute send time according to the receive time.
|
||||
// Note that if the transmission delay is larger than 64 seconds, estimated time will be wrong.
|
||||
func (t *AbsSendTimeExtension) Estimate(receive time.Time) time.Time {
|
||||
receiveNTP := toNtpTime(receive)
|
||||
ntp := receiveNTP&0xFFFFFFC000000000 | (t.Timestamp&0xFFFFFF)<<14
|
||||
if receiveNTP < ntp {
|
||||
// Receive time must be always later than send time
|
||||
ntp -= 0x1000000 << 14
|
||||
}
|
||||
|
||||
return toTime(ntp)
|
||||
}
|
||||
|
||||
// NewAbsSendTimeExtension makes new AbsSendTimeExtension from time.Time.
|
||||
func NewAbsSendTimeExtension(sendTime time.Time) *AbsSendTimeExtension {
|
||||
return &AbsSendTimeExtension{
|
||||
Timestamp: toNtpTime(sendTime) >> 14,
|
||||
}
|
||||
}
|
||||
|
||||
func toNtpTime(t time.Time) uint64 {
|
||||
var s uint64
|
||||
var f uint64
|
||||
u := uint64(t.UnixNano())
|
||||
s = u / 1e9
|
||||
s += 0x83AA7E80 // offset in seconds between unix epoch and ntp epoch
|
||||
f = u % 1e9
|
||||
f <<= 32
|
||||
f /= 1e9
|
||||
s <<= 32
|
||||
|
||||
return s | f
|
||||
}
|
||||
|
||||
func toTime(t uint64) time.Time {
|
||||
s := t >> 32
|
||||
f := t & 0xFFFFFFFF
|
||||
f *= 1e9
|
||||
f >>= 32
|
||||
s -= 0x83AA7E80
|
||||
u := s*1e9 + f
|
||||
|
||||
return time.Unix(0, int64(u))
|
||||
}
|
60
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/audiolevelextension.go
generated
vendored
Normal file
60
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/audiolevelextension.go
generated
vendored
Normal file
|
@ -0,0 +1,60 @@
|
|||
package rtp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
const (
|
||||
// audioLevelExtensionSize One byte header size
|
||||
audioLevelExtensionSize = 1
|
||||
)
|
||||
|
||||
var errAudioLevelOverflow = errors.New("audio level overflow")
|
||||
|
||||
// AudioLevelExtension is a extension payload format described in
|
||||
// https://tools.ietf.org/html/rfc6464
|
||||
//
|
||||
// Implementation based on:
|
||||
// https://chromium.googlesource.com/external/webrtc/+/e2a017725570ead5946a4ca8235af27470ca0df9/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.cc#49
|
||||
//
|
||||
// One byte format:
|
||||
// 0 1
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | ID | len=0 |V| level |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
// Two byte format:
|
||||
// 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
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | ID | len=1 |V| level | 0 (pad) |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
type AudioLevelExtension struct {
|
||||
Level uint8
|
||||
Voice bool
|
||||
}
|
||||
|
||||
// Marshal serializes the members to buffer
|
||||
func (a *AudioLevelExtension) Marshal() ([]byte, error) {
|
||||
if a.Level > 127 {
|
||||
return nil, errAudioLevelOverflow
|
||||
}
|
||||
voice := uint8(0x00)
|
||||
if a.Voice {
|
||||
voice = 0x80
|
||||
}
|
||||
buf := make([]byte, audioLevelExtensionSize)
|
||||
buf[0] = voice | a.Level
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
// Unmarshal parses the passed byte slice and stores the result in the members
|
||||
func (a *AudioLevelExtension) Unmarshal(rawData []byte) error {
|
||||
if len(rawData) < audioLevelExtensionSize {
|
||||
return errTooSmall
|
||||
}
|
||||
a.Level = rawData[0] & 0x7F
|
||||
a.Voice = rawData[0]&0x80 != 0
|
||||
return nil
|
||||
}
|
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecov.yml
generated
vendored
Normal file
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/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/**/*"
|
2
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/codecs.go
generated
vendored
Normal file
2
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/codecs.go
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
// Package codecs implements codec specific RTP payloader/depayloaders
|
||||
package codecs
|
8
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/common.go
generated
vendored
Normal file
8
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/common.go
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
package codecs
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
11
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/error.go
generated
vendored
Normal file
11
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/error.go
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
package codecs
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
errShortPacket = errors.New("packet is not large enough")
|
||||
errNilPacket = errors.New("invalid nil packet")
|
||||
errTooManyPDiff = errors.New("too many PDiff")
|
||||
errTooManySpatialLayers = errors.New("too many spatial layers")
|
||||
errUnhandledNALUType = errors.New("NALU Type is unhandled")
|
||||
)
|
22
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/g711_packet.go
generated
vendored
Normal file
22
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/g711_packet.go
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
package codecs
|
||||
|
||||
// G711Payloader payloads G711 packets
|
||||
type G711Payloader struct{}
|
||||
|
||||
// Payload fragments an G711 packet across one or more byte arrays
|
||||
func (p *G711Payloader) Payload(mtu int, payload []byte) [][]byte {
|
||||
var out [][]byte
|
||||
if payload == nil || mtu <= 0 {
|
||||
return out
|
||||
}
|
||||
|
||||
for len(payload) > mtu {
|
||||
o := make([]byte, mtu)
|
||||
copy(o, payload[:mtu])
|
||||
payload = payload[mtu:]
|
||||
out = append(out, o)
|
||||
}
|
||||
o := make([]byte, len(payload))
|
||||
copy(o, payload)
|
||||
return append(out, o)
|
||||
}
|
22
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/g722_packet.go
generated
vendored
Normal file
22
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/g722_packet.go
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
package codecs
|
||||
|
||||
// G722Payloader payloads G722 packets
|
||||
type G722Payloader struct{}
|
||||
|
||||
// Payload fragments an G722 packet across one or more byte arrays
|
||||
func (p *G722Payloader) Payload(mtu int, payload []byte) [][]byte {
|
||||
var out [][]byte
|
||||
if payload == nil || mtu <= 0 {
|
||||
return out
|
||||
}
|
||||
|
||||
for len(payload) > mtu {
|
||||
o := make([]byte, mtu)
|
||||
copy(o, payload[:mtu])
|
||||
payload = payload[mtu:]
|
||||
out = append(out, o)
|
||||
}
|
||||
o := make([]byte, len(payload))
|
||||
copy(o, payload)
|
||||
return append(out, o)
|
||||
}
|
205
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/h264_packet.go
generated
vendored
Normal file
205
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/h264_packet.go
generated
vendored
Normal file
|
@ -0,0 +1,205 @@
|
|||
package codecs
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// H264Payloader payloads H264 packets
|
||||
type H264Payloader struct{}
|
||||
|
||||
const (
|
||||
stapaNALUType = 24
|
||||
fuaNALUType = 28
|
||||
|
||||
fuaHeaderSize = 2
|
||||
stapaHeaderSize = 1
|
||||
stapaNALULengthSize = 2
|
||||
|
||||
naluTypeBitmask = 0x1F
|
||||
naluRefIdcBitmask = 0x60
|
||||
fuaStartBitmask = 0x80
|
||||
)
|
||||
|
||||
func annexbNALUStartCode() []byte { return []byte{0x00, 0x00, 0x00, 0x01} }
|
||||
|
||||
func emitNalus(nals []byte, emit func([]byte)) {
|
||||
nextInd := func(nalu []byte, start int) (indStart int, indLen int) {
|
||||
zeroCount := 0
|
||||
|
||||
for i, b := range nalu[start:] {
|
||||
if b == 0 {
|
||||
zeroCount++
|
||||
continue
|
||||
} else if b == 1 {
|
||||
if zeroCount >= 2 {
|
||||
return start + i - zeroCount, zeroCount + 1
|
||||
}
|
||||
}
|
||||
zeroCount = 0
|
||||
}
|
||||
return -1, -1
|
||||
}
|
||||
|
||||
nextIndStart, nextIndLen := nextInd(nals, 0)
|
||||
if nextIndStart == -1 {
|
||||
emit(nals)
|
||||
} else {
|
||||
for nextIndStart != -1 {
|
||||
prevStart := nextIndStart + nextIndLen
|
||||
nextIndStart, nextIndLen = nextInd(nals, prevStart)
|
||||
if nextIndStart != -1 {
|
||||
emit(nals[prevStart:nextIndStart])
|
||||
} else {
|
||||
// Emit until end of stream, no end indicator found
|
||||
emit(nals[prevStart:])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Payload fragments a H264 packet across one or more byte arrays
|
||||
func (p *H264Payloader) Payload(mtu int, payload []byte) [][]byte {
|
||||
var payloads [][]byte
|
||||
if len(payload) == 0 {
|
||||
return payloads
|
||||
}
|
||||
|
||||
emitNalus(payload, func(nalu []byte) {
|
||||
if len(nalu) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
naluType := nalu[0] & naluTypeBitmask
|
||||
naluRefIdc := nalu[0] & naluRefIdcBitmask
|
||||
|
||||
if naluType == 9 || naluType == 12 {
|
||||
return
|
||||
}
|
||||
|
||||
// Single NALU
|
||||
if len(nalu) <= mtu {
|
||||
out := make([]byte, len(nalu))
|
||||
copy(out, nalu)
|
||||
payloads = append(payloads, out)
|
||||
return
|
||||
}
|
||||
|
||||
// FU-A
|
||||
maxFragmentSize := mtu - fuaHeaderSize
|
||||
|
||||
// The FU payload consists of fragments of the payload of the fragmented
|
||||
// NAL unit so that if the fragmentation unit payloads of consecutive
|
||||
// FUs are sequentially concatenated, the payload of the fragmented NAL
|
||||
// unit can be reconstructed. The NAL unit type octet of the fragmented
|
||||
// NAL unit is not included as such in the fragmentation unit payload,
|
||||
// but rather the information of the NAL unit type octet of the
|
||||
// fragmented NAL unit is conveyed in the F and NRI fields of the FU
|
||||
// indicator octet of the fragmentation unit and in the type field of
|
||||
// the FU header. An FU payload MAY have any number of octets and MAY
|
||||
// be empty.
|
||||
|
||||
naluData := nalu
|
||||
// According to the RFC, the first octet is skipped due to redundant information
|
||||
naluDataIndex := 1
|
||||
naluDataLength := len(nalu) - naluDataIndex
|
||||
naluDataRemaining := naluDataLength
|
||||
|
||||
if min(maxFragmentSize, naluDataRemaining) <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
for naluDataRemaining > 0 {
|
||||
currentFragmentSize := min(maxFragmentSize, naluDataRemaining)
|
||||
out := make([]byte, fuaHeaderSize+currentFragmentSize)
|
||||
|
||||
// +---------------+
|
||||
// |0|1|2|3|4|5|6|7|
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// |F|NRI| Type |
|
||||
// +---------------+
|
||||
out[0] = fuaNALUType
|
||||
out[0] |= naluRefIdc
|
||||
|
||||
// +---------------+
|
||||
// |0|1|2|3|4|5|6|7|
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// |S|E|R| Type |
|
||||
// +---------------+
|
||||
|
||||
out[1] = naluType
|
||||
if naluDataRemaining == naluDataLength {
|
||||
// Set start bit
|
||||
out[1] |= 1 << 7
|
||||
} else if naluDataRemaining-currentFragmentSize == 0 {
|
||||
// Set end bit
|
||||
out[1] |= 1 << 6
|
||||
}
|
||||
|
||||
copy(out[fuaHeaderSize:], naluData[naluDataIndex:naluDataIndex+currentFragmentSize])
|
||||
payloads = append(payloads, out)
|
||||
|
||||
naluDataRemaining -= currentFragmentSize
|
||||
naluDataIndex += currentFragmentSize
|
||||
}
|
||||
})
|
||||
|
||||
return payloads
|
||||
}
|
||||
|
||||
// H264Packet represents the H264 header that is stored in the payload of an RTP Packet
|
||||
type H264Packet struct {
|
||||
}
|
||||
|
||||
// Unmarshal parses the passed byte slice and stores the result in the H264Packet this method is called upon
|
||||
func (p *H264Packet) Unmarshal(payload []byte) ([]byte, error) {
|
||||
if payload == nil {
|
||||
return nil, errNilPacket
|
||||
} else if len(payload) <= 2 {
|
||||
return nil, fmt.Errorf("%w: %d <= 2", errShortPacket, len(payload))
|
||||
}
|
||||
|
||||
// NALU Types
|
||||
// https://tools.ietf.org/html/rfc6184#section-5.4
|
||||
naluType := payload[0] & naluTypeBitmask
|
||||
switch {
|
||||
case naluType > 0 && naluType < 24:
|
||||
return append(annexbNALUStartCode(), payload...), nil
|
||||
|
||||
case naluType == stapaNALUType:
|
||||
currOffset := int(stapaHeaderSize)
|
||||
result := []byte{}
|
||||
for currOffset < len(payload) {
|
||||
naluSize := int(binary.BigEndian.Uint16(payload[currOffset:]))
|
||||
currOffset += stapaNALULengthSize
|
||||
|
||||
if len(payload) < currOffset+naluSize {
|
||||
return nil, fmt.Errorf("%w STAP-A declared size(%d) is larger than buffer(%d)", errShortPacket, naluSize, len(payload)-currOffset)
|
||||
}
|
||||
|
||||
result = append(result, annexbNALUStartCode()...)
|
||||
result = append(result, payload[currOffset:currOffset+naluSize]...)
|
||||
currOffset += naluSize
|
||||
}
|
||||
return result, nil
|
||||
|
||||
case naluType == fuaNALUType:
|
||||
if len(payload) < fuaHeaderSize {
|
||||
return nil, errShortPacket
|
||||
}
|
||||
|
||||
if payload[1]&fuaStartBitmask != 0 {
|
||||
naluRefIdc := payload[0] & naluRefIdcBitmask
|
||||
fragmentedNaluType := payload[1] & naluTypeBitmask
|
||||
|
||||
// Take a copy of payload since we are mutating it.
|
||||
payloadCopy := append([]byte{}, payload...)
|
||||
payloadCopy[fuaHeaderSize-1] = naluRefIdc | fragmentedNaluType
|
||||
return append(annexbNALUStartCode(), payloadCopy[fuaHeaderSize-1:]...), nil
|
||||
}
|
||||
|
||||
return payload[fuaHeaderSize:], nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%w: %d", errUnhandledNALUType, naluType)
|
||||
}
|
44
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/opus_packet.go
generated
vendored
Normal file
44
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/opus_packet.go
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
package codecs
|
||||
|
||||
// OpusPayloader payloads Opus packets
|
||||
type OpusPayloader struct{}
|
||||
|
||||
// Payload fragments an Opus packet across one or more byte arrays
|
||||
func (p *OpusPayloader) Payload(mtu int, payload []byte) [][]byte {
|
||||
if payload == nil {
|
||||
return [][]byte{}
|
||||
}
|
||||
|
||||
out := make([]byte, len(payload))
|
||||
copy(out, payload)
|
||||
return [][]byte{out}
|
||||
}
|
||||
|
||||
// OpusPacket represents the Opus header that is stored in the payload of an RTP Packet
|
||||
type OpusPacket struct {
|
||||
Payload []byte
|
||||
}
|
||||
|
||||
// Unmarshal parses the passed byte slice and stores the result in the OpusPacket this method is called upon
|
||||
func (p *OpusPacket) Unmarshal(packet []byte) ([]byte, error) {
|
||||
if packet == nil {
|
||||
return nil, errNilPacket
|
||||
} else if len(packet) == 0 {
|
||||
return nil, errShortPacket
|
||||
}
|
||||
|
||||
p.Payload = packet
|
||||
return packet, nil
|
||||
}
|
||||
|
||||
// OpusPartitionHeadChecker checks Opus partition head
|
||||
type OpusPartitionHeadChecker struct{}
|
||||
|
||||
// IsPartitionHead checks whether if this is a head of the Opus partition
|
||||
func (*OpusPartitionHeadChecker) IsPartitionHead(packet []byte) bool {
|
||||
p := &OpusPacket{}
|
||||
if _, err := p.Unmarshal(packet); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
143
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/vp8_packet.go
generated
vendored
Normal file
143
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/vp8_packet.go
generated
vendored
Normal file
|
@ -0,0 +1,143 @@
|
|||
package codecs
|
||||
|
||||
// VP8Payloader payloads VP8 packets
|
||||
type VP8Payloader struct{}
|
||||
|
||||
const (
|
||||
vp8HeaderSize = 1
|
||||
)
|
||||
|
||||
// Payload fragments a VP8 packet across one or more byte arrays
|
||||
func (p *VP8Payloader) Payload(mtu int, payload []byte) [][]byte {
|
||||
/*
|
||||
* https://tools.ietf.org/html/rfc7741#section-4.2
|
||||
*
|
||||
* 0 1 2 3 4 5 6 7
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
* |X|R|N|S|R| PID | (REQUIRED)
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
* X: |I|L|T|K| RSV | (OPTIONAL)
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
* I: |M| PictureID | (OPTIONAL)
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
* L: | TL0PICIDX | (OPTIONAL)
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
* T/K: |TID|Y| KEYIDX | (OPTIONAL)
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
* S: Start of VP8 partition. SHOULD be set to 1 when the first payload
|
||||
* octet of the RTP packet is the beginning of a new VP8 partition,
|
||||
* and MUST NOT be 1 otherwise. The S bit MUST be set to 1 for the
|
||||
* first packet of each encoded frame.
|
||||
*/
|
||||
|
||||
maxFragmentSize := mtu - vp8HeaderSize
|
||||
|
||||
payloadData := payload
|
||||
payloadDataRemaining := len(payload)
|
||||
|
||||
payloadDataIndex := 0
|
||||
var payloads [][]byte
|
||||
|
||||
// Make sure the fragment/payload size is correct
|
||||
if min(maxFragmentSize, payloadDataRemaining) <= 0 {
|
||||
return payloads
|
||||
}
|
||||
for payloadDataRemaining > 0 {
|
||||
currentFragmentSize := min(maxFragmentSize, payloadDataRemaining)
|
||||
out := make([]byte, vp8HeaderSize+currentFragmentSize)
|
||||
if payloadDataRemaining == len(payload) {
|
||||
out[0] = 0x10
|
||||
}
|
||||
|
||||
copy(out[vp8HeaderSize:], payloadData[payloadDataIndex:payloadDataIndex+currentFragmentSize])
|
||||
payloads = append(payloads, out)
|
||||
|
||||
payloadDataRemaining -= currentFragmentSize
|
||||
payloadDataIndex += currentFragmentSize
|
||||
}
|
||||
|
||||
return payloads
|
||||
}
|
||||
|
||||
// VP8Packet represents the VP8 header that is stored in the payload of an RTP Packet
|
||||
type VP8Packet struct {
|
||||
// Required Header
|
||||
X uint8 /* extended controlbits present */
|
||||
N uint8 /* (non-reference frame) when set to 1 this frame can be discarded */
|
||||
S uint8 /* start of VP8 partition */
|
||||
PID uint8 /* partition index */
|
||||
|
||||
// Optional Header
|
||||
I uint8 /* 1 if PictureID is present */
|
||||
L uint8 /* 1 if TL0PICIDX is present */
|
||||
T uint8 /* 1 if TID is present */
|
||||
K uint8 /* 1 if KEYIDX is present */
|
||||
PictureID uint16 /* 8 or 16 bits, picture ID */
|
||||
TL0PICIDX uint8 /* 8 bits temporal level zero index */
|
||||
|
||||
Payload []byte
|
||||
}
|
||||
|
||||
// Unmarshal parses the passed byte slice and stores the result in the VP8Packet this method is called upon
|
||||
func (p *VP8Packet) Unmarshal(payload []byte) ([]byte, error) {
|
||||
if payload == nil {
|
||||
return nil, errNilPacket
|
||||
}
|
||||
|
||||
payloadLen := len(payload)
|
||||
|
||||
if payloadLen < 4 {
|
||||
return nil, errShortPacket
|
||||
}
|
||||
|
||||
payloadIndex := 0
|
||||
|
||||
p.X = (payload[payloadIndex] & 0x80) >> 7
|
||||
p.N = (payload[payloadIndex] & 0x20) >> 5
|
||||
p.S = (payload[payloadIndex] & 0x10) >> 4
|
||||
p.PID = payload[payloadIndex] & 0x07
|
||||
|
||||
payloadIndex++
|
||||
|
||||
if p.X == 1 {
|
||||
p.I = (payload[payloadIndex] & 0x80) >> 7
|
||||
p.L = (payload[payloadIndex] & 0x40) >> 6
|
||||
p.T = (payload[payloadIndex] & 0x20) >> 5
|
||||
p.K = (payload[payloadIndex] & 0x10) >> 4
|
||||
payloadIndex++
|
||||
}
|
||||
|
||||
if p.I == 1 { // PID present?
|
||||
if payload[payloadIndex]&0x80 > 0 { // M == 1, PID is 16bit
|
||||
payloadIndex += 2
|
||||
} else {
|
||||
payloadIndex++
|
||||
}
|
||||
}
|
||||
|
||||
if p.L == 1 {
|
||||
payloadIndex++
|
||||
}
|
||||
|
||||
if p.T == 1 || p.K == 1 {
|
||||
payloadIndex++
|
||||
}
|
||||
|
||||
if payloadIndex >= payloadLen {
|
||||
return nil, errShortPacket
|
||||
}
|
||||
p.Payload = payload[payloadIndex:]
|
||||
return p.Payload, nil
|
||||
}
|
||||
|
||||
// VP8PartitionHeadChecker checks VP8 partition head
|
||||
type VP8PartitionHeadChecker struct{}
|
||||
|
||||
// IsPartitionHead checks whether if this is a head of the VP8 partition
|
||||
func (*VP8PartitionHeadChecker) IsPartitionHead(packet []byte) bool {
|
||||
p := &VP8Packet{}
|
||||
if _, err := p.Unmarshal(packet); err != nil {
|
||||
return false
|
||||
}
|
||||
return p.S == 1
|
||||
}
|
385
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/vp9_packet.go
generated
vendored
Normal file
385
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/vp9_packet.go
generated
vendored
Normal file
|
@ -0,0 +1,385 @@
|
|||
package codecs
|
||||
|
||||
import (
|
||||
"github.com/pion/randutil"
|
||||
)
|
||||
|
||||
// Use global random generator to properly seed by crypto grade random.
|
||||
var globalMathRandomGenerator = randutil.NewMathRandomGenerator() // nolint:gochecknoglobals
|
||||
|
||||
// VP9Payloader payloads VP9 packets
|
||||
type VP9Payloader struct {
|
||||
pictureID uint16
|
||||
initialized bool
|
||||
|
||||
// InitialPictureIDFn is a function that returns random initial picture ID.
|
||||
InitialPictureIDFn func() uint16
|
||||
}
|
||||
|
||||
const (
|
||||
vp9HeaderSize = 3 // Flexible mode 15 bit picture ID
|
||||
maxSpatialLayers = 5
|
||||
maxVP9RefPics = 3
|
||||
)
|
||||
|
||||
// Payload fragments an VP9 packet across one or more byte arrays
|
||||
func (p *VP9Payloader) Payload(mtu int, payload []byte) [][]byte {
|
||||
/*
|
||||
* https://www.ietf.org/id/draft-ietf-payload-vp9-10.txt
|
||||
*
|
||||
* Flexible mode (F=1)
|
||||
* 0 1 2 3 4 5 6 7
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
* |I|P|L|F|B|E|V|-| (REQUIRED)
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
* I: |M| PICTURE ID | (REQUIRED)
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
* M: | EXTENDED PID | (RECOMMENDED)
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
* L: | TID |U| SID |D| (CONDITIONALLY RECOMMENDED)
|
||||
* +-+-+-+-+-+-+-+-+ -\
|
||||
* P,F: | P_DIFF |N| (CONDITIONALLY REQUIRED) - up to 3 times
|
||||
* +-+-+-+-+-+-+-+-+ -/
|
||||
* V: | SS |
|
||||
* | .. |
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
*
|
||||
* Non-flexible mode (F=0)
|
||||
* 0 1 2 3 4 5 6 7
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
* |I|P|L|F|B|E|V|-| (REQUIRED)
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
* I: |M| PICTURE ID | (RECOMMENDED)
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
* M: | EXTENDED PID | (RECOMMENDED)
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
* L: | TID |U| SID |D| (CONDITIONALLY RECOMMENDED)
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
* | TL0PICIDX | (CONDITIONALLY REQUIRED)
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
* V: | SS |
|
||||
* | .. |
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
if !p.initialized {
|
||||
if p.InitialPictureIDFn == nil {
|
||||
p.InitialPictureIDFn = func() uint16 {
|
||||
return uint16(globalMathRandomGenerator.Intn(0x7FFF))
|
||||
}
|
||||
}
|
||||
p.pictureID = p.InitialPictureIDFn() & 0x7FFF
|
||||
p.initialized = true
|
||||
}
|
||||
if payload == nil {
|
||||
return [][]byte{}
|
||||
}
|
||||
|
||||
maxFragmentSize := mtu - vp9HeaderSize
|
||||
payloadDataRemaining := len(payload)
|
||||
payloadDataIndex := 0
|
||||
|
||||
if min(maxFragmentSize, payloadDataRemaining) <= 0 {
|
||||
return [][]byte{}
|
||||
}
|
||||
|
||||
var payloads [][]byte
|
||||
for payloadDataRemaining > 0 {
|
||||
currentFragmentSize := min(maxFragmentSize, payloadDataRemaining)
|
||||
out := make([]byte, vp9HeaderSize+currentFragmentSize)
|
||||
|
||||
out[0] = 0x90 // F=1 I=1
|
||||
if payloadDataIndex == 0 {
|
||||
out[0] |= 0x08 // B=1
|
||||
}
|
||||
if payloadDataRemaining == currentFragmentSize {
|
||||
out[0] |= 0x04 // E=1
|
||||
}
|
||||
out[1] = byte(p.pictureID>>8) | 0x80
|
||||
out[2] = byte(p.pictureID)
|
||||
copy(out[vp9HeaderSize:], payload[payloadDataIndex:payloadDataIndex+currentFragmentSize])
|
||||
payloads = append(payloads, out)
|
||||
|
||||
payloadDataRemaining -= currentFragmentSize
|
||||
payloadDataIndex += currentFragmentSize
|
||||
}
|
||||
p.pictureID++
|
||||
if p.pictureID >= 0x8000 {
|
||||
p.pictureID = 0
|
||||
}
|
||||
|
||||
return payloads
|
||||
}
|
||||
|
||||
// VP9Packet represents the VP9 header that is stored in the payload of an RTP Packet
|
||||
type VP9Packet struct {
|
||||
// Required header
|
||||
I bool // PictureID is present
|
||||
P bool // Inter-picture predicted frame
|
||||
L bool // Layer indices is present
|
||||
F bool // Flexible mode
|
||||
B bool // Start of a frame
|
||||
E bool // End of a frame
|
||||
V bool // Scalability structure (SS) data present
|
||||
|
||||
// Recommended headers
|
||||
PictureID uint16 // 7 or 16 bits, picture ID
|
||||
|
||||
// Conditionally recommended headers
|
||||
TID uint8 // Temporal layer ID
|
||||
U bool // Switching up point
|
||||
SID uint8 // Spatial layer ID
|
||||
D bool // Inter-layer dependency used
|
||||
|
||||
// Conditionally required headers
|
||||
PDiff []uint8 // Reference index (F=1)
|
||||
TL0PICIDX uint8 // Temporal layer zero index (F=0)
|
||||
|
||||
// Scalability structure headers
|
||||
NS uint8 // N_S + 1 indicates the number of spatial layers present in the VP9 stream
|
||||
Y bool // Each spatial layer's frame resolution present
|
||||
G bool // PG description present flag.
|
||||
NG uint8 // N_G indicates the number of pictures in a Picture Group (PG)
|
||||
Width []uint16
|
||||
Height []uint16
|
||||
PGTID []uint8 // Temporal layer ID of pictures in a Picture Group
|
||||
PGU []bool // Switching up point of pictures in a Picture Group
|
||||
PGPDiff [][]uint8 // Reference indecies of pictures in a Picture Group
|
||||
|
||||
Payload []byte
|
||||
}
|
||||
|
||||
// Unmarshal parses the passed byte slice and stores the result in the VP9Packet this method is called upon
|
||||
func (p *VP9Packet) Unmarshal(packet []byte) ([]byte, error) {
|
||||
if packet == nil {
|
||||
return nil, errNilPacket
|
||||
}
|
||||
if len(packet) < 1 {
|
||||
return nil, errShortPacket
|
||||
}
|
||||
|
||||
p.I = packet[0]&0x80 != 0
|
||||
p.P = packet[0]&0x40 != 0
|
||||
p.L = packet[0]&0x20 != 0
|
||||
p.F = packet[0]&0x10 != 0
|
||||
p.B = packet[0]&0x08 != 0
|
||||
p.E = packet[0]&0x04 != 0
|
||||
p.V = packet[0]&0x02 != 0
|
||||
|
||||
pos := 1
|
||||
var err error
|
||||
|
||||
if p.I {
|
||||
pos, err = p.parsePictureID(packet, pos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if p.L {
|
||||
pos, err = p.parseLayerInfo(packet, pos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if p.F && p.P {
|
||||
pos, err = p.parseRefIndices(packet, pos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if p.V {
|
||||
pos, err = p.parseSSData(packet, pos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
p.Payload = packet[pos:]
|
||||
return p.Payload, nil
|
||||
}
|
||||
|
||||
// Picture ID:
|
||||
//
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// I: |M| PICTURE ID | M:0 => picture id is 7 bits.
|
||||
// +-+-+-+-+-+-+-+-+ M:1 => picture id is 15 bits.
|
||||
// M: | EXTENDED PID |
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
//
|
||||
func (p *VP9Packet) parsePictureID(packet []byte, pos int) (int, error) {
|
||||
if len(packet) <= pos {
|
||||
return pos, errShortPacket
|
||||
}
|
||||
|
||||
p.PictureID = uint16(packet[pos] & 0x7F)
|
||||
if packet[pos]&0x80 != 0 {
|
||||
pos++
|
||||
if len(packet) <= pos {
|
||||
return pos, errShortPacket
|
||||
}
|
||||
p.PictureID = p.PictureID<<8 | uint16(packet[pos])
|
||||
}
|
||||
pos++
|
||||
return pos, nil
|
||||
}
|
||||
|
||||
func (p *VP9Packet) parseLayerInfo(packet []byte, pos int) (int, error) {
|
||||
pos, err := p.parseLayerInfoCommon(packet, pos)
|
||||
if err != nil {
|
||||
return pos, err
|
||||
}
|
||||
|
||||
if p.F {
|
||||
return pos, nil
|
||||
}
|
||||
|
||||
return p.parseLayerInfoNonFlexibleMode(packet, pos)
|
||||
}
|
||||
|
||||
// Layer indices (flexible mode):
|
||||
//
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// L: | T |U| S |D|
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
//
|
||||
func (p *VP9Packet) parseLayerInfoCommon(packet []byte, pos int) (int, error) {
|
||||
if len(packet) <= pos {
|
||||
return pos, errShortPacket
|
||||
}
|
||||
|
||||
p.TID = packet[pos] >> 5
|
||||
p.U = packet[pos]&0x10 != 0
|
||||
p.SID = (packet[pos] >> 1) & 0x7
|
||||
p.D = packet[pos]&0x01 != 0
|
||||
|
||||
if p.SID >= maxSpatialLayers {
|
||||
return pos, errTooManySpatialLayers
|
||||
}
|
||||
|
||||
pos++
|
||||
return pos, nil
|
||||
}
|
||||
|
||||
// Layer indices (non-flexible mode):
|
||||
//
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// L: | T |U| S |D|
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// | TL0PICIDX |
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
//
|
||||
func (p *VP9Packet) parseLayerInfoNonFlexibleMode(packet []byte, pos int) (int, error) {
|
||||
if len(packet) <= pos {
|
||||
return pos, errShortPacket
|
||||
}
|
||||
|
||||
p.TL0PICIDX = packet[pos]
|
||||
pos++
|
||||
return pos, nil
|
||||
}
|
||||
|
||||
// Reference indices:
|
||||
//
|
||||
// +-+-+-+-+-+-+-+-+ P=1,F=1: At least one reference index
|
||||
// P,F: | P_DIFF |N| up to 3 times has to be specified.
|
||||
// +-+-+-+-+-+-+-+-+ N=1: An additional P_DIFF follows
|
||||
// current P_DIFF.
|
||||
//
|
||||
func (p *VP9Packet) parseRefIndices(packet []byte, pos int) (int, error) {
|
||||
for {
|
||||
if len(packet) <= pos {
|
||||
return pos, errShortPacket
|
||||
}
|
||||
p.PDiff = append(p.PDiff, packet[pos]>>1)
|
||||
if packet[pos]&0x01 == 0 {
|
||||
break
|
||||
}
|
||||
if len(p.PDiff) >= maxVP9RefPics {
|
||||
return pos, errTooManyPDiff
|
||||
}
|
||||
pos++
|
||||
}
|
||||
pos++
|
||||
|
||||
return pos, nil
|
||||
}
|
||||
|
||||
// Scalability structure (SS):
|
||||
//
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// V: | N_S |Y|G|-|-|-|
|
||||
// +-+-+-+-+-+-+-+-+ -|
|
||||
// Y: | WIDTH | (OPTIONAL) .
|
||||
// + + .
|
||||
// | | (OPTIONAL) .
|
||||
// +-+-+-+-+-+-+-+-+ . N_S + 1 times
|
||||
// | HEIGHT | (OPTIONAL) .
|
||||
// + + .
|
||||
// | | (OPTIONAL) .
|
||||
// +-+-+-+-+-+-+-+-+ -|
|
||||
// G: | N_G | (OPTIONAL)
|
||||
// +-+-+-+-+-+-+-+-+ -|
|
||||
// N_G: | T |U| R |-|-| (OPTIONAL) .
|
||||
// +-+-+-+-+-+-+-+-+ -| . N_G times
|
||||
// | P_DIFF | (OPTIONAL) . R times .
|
||||
// +-+-+-+-+-+-+-+-+ -| -|
|
||||
//
|
||||
func (p *VP9Packet) parseSSData(packet []byte, pos int) (int, error) {
|
||||
if len(packet) <= pos {
|
||||
return pos, errShortPacket
|
||||
}
|
||||
|
||||
p.NS = packet[pos] >> 5
|
||||
p.Y = packet[pos]&0x10 != 0
|
||||
p.G = (packet[pos]>>1)&0x7 != 0
|
||||
pos++
|
||||
|
||||
NS := p.NS + 1
|
||||
p.NG = 0
|
||||
|
||||
if p.Y {
|
||||
p.Width = make([]uint16, NS)
|
||||
p.Height = make([]uint16, NS)
|
||||
for i := 0; i < int(NS); i++ {
|
||||
p.Width[i] = uint16(packet[pos])<<8 | uint16(packet[pos+1])
|
||||
pos += 2
|
||||
p.Height[i] = uint16(packet[pos])<<8 | uint16(packet[pos+1])
|
||||
pos += 2
|
||||
}
|
||||
}
|
||||
|
||||
if p.G {
|
||||
p.NG = packet[pos]
|
||||
pos++
|
||||
}
|
||||
|
||||
for i := 0; i < int(p.NG); i++ {
|
||||
p.PGTID = append(p.PGTID, packet[pos]>>5)
|
||||
p.PGU = append(p.PGU, packet[pos]&0x10 != 0)
|
||||
R := (packet[pos] >> 2) & 0x3
|
||||
pos++
|
||||
|
||||
p.PGPDiff = append(p.PGPDiff, []uint8{})
|
||||
for j := 0; j < int(R); j++ {
|
||||
p.PGPDiff[i] = append(p.PGPDiff[i], packet[pos])
|
||||
pos++
|
||||
}
|
||||
}
|
||||
|
||||
return pos, nil
|
||||
}
|
||||
|
||||
// VP9PartitionHeadChecker checks VP9 partition head
|
||||
type VP9PartitionHeadChecker struct{}
|
||||
|
||||
// IsPartitionHead checks whether if this is a head of the VP9 partition
|
||||
func (*VP9PartitionHeadChecker) IsPartitionHead(packet []byte) bool {
|
||||
p := &VP9Packet{}
|
||||
if _, err := p.Unmarshal(packet); err != nil {
|
||||
return false
|
||||
}
|
||||
return p.B
|
||||
}
|
6
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/depacketizer.go
generated
vendored
Normal file
6
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/depacketizer.go
generated
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
package rtp
|
||||
|
||||
// Depacketizer depacketizes a RTP payload, removing any RTP specific data from the payload
|
||||
type Depacketizer interface {
|
||||
Unmarshal(packet []byte) ([]byte, error)
|
||||
}
|
21
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/error.go
generated
vendored
Normal file
21
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/error.go
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
package rtp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
errHeaderSizeInsufficient = errors.New("RTP header size insufficient")
|
||||
errHeaderSizeInsufficientForExtension = errors.New("RTP header size insufficient for extension")
|
||||
errTooSmall = errors.New("buffer too small")
|
||||
errHeaderExtensionsNotEnabled = errors.New("h.Extension not enabled")
|
||||
errHeaderExtensionNotFound = errors.New("extension not found")
|
||||
|
||||
errRFC8285OneByteHeaderIDRange = errors.New("header extension id must be between 1 and 14 for RFC 5285 one byte extensions")
|
||||
errRFC8285OneByteHeaderSize = errors.New("header extension payload must be 16bytes or less for RFC 5285 one byte extensions")
|
||||
|
||||
errRFC8285TwoByteHeaderIDRange = errors.New("header extension id must be between 1 and 255 for RFC 5285 two byte extensions")
|
||||
errRFC8285TwoByteHeaderSize = errors.New("header extension payload must be 255bytes or less for RFC 5285 two byte extensions")
|
||||
|
||||
errRFC3550HeaderIDRange = errors.New("header extension id must be 0 for non-RFC 5285 extensions")
|
||||
)
|
5
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/go.mod
generated
vendored
Normal file
5
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/go.mod
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
module github.com/pion/rtp
|
||||
|
||||
go 1.13
|
||||
|
||||
require github.com/pion/randutil v0.1.0
|
2
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/go.sum
generated
vendored
Normal file
2
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/go.sum
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
|
||||
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
|
490
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/packet.go
generated
vendored
Normal file
490
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/packet.go
generated
vendored
Normal file
|
@ -0,0 +1,490 @@
|
|||
package rtp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Extension RTP Header extension
|
||||
type Extension struct {
|
||||
id uint8
|
||||
payload []byte
|
||||
}
|
||||
|
||||
// Header represents an RTP packet header
|
||||
// NOTE: PayloadOffset is populated by Marshal/Unmarshal and should not be modified
|
||||
type Header struct {
|
||||
Version uint8
|
||||
Padding bool
|
||||
Extension bool
|
||||
Marker bool
|
||||
PayloadOffset int
|
||||
PayloadType uint8
|
||||
SequenceNumber uint16
|
||||
Timestamp uint32
|
||||
SSRC uint32
|
||||
CSRC []uint32
|
||||
ExtensionProfile uint16
|
||||
Extensions []Extension
|
||||
}
|
||||
|
||||
// Packet represents an RTP Packet
|
||||
// NOTE: Raw is populated by Marshal/Unmarshal and should not be modified
|
||||
type Packet struct {
|
||||
Header
|
||||
Raw []byte
|
||||
Payload []byte
|
||||
}
|
||||
|
||||
const (
|
||||
headerLength = 4
|
||||
versionShift = 6
|
||||
versionMask = 0x3
|
||||
paddingShift = 5
|
||||
paddingMask = 0x1
|
||||
extensionShift = 4
|
||||
extensionMask = 0x1
|
||||
extensionProfileOneByte = 0xBEDE
|
||||
extensionProfileTwoByte = 0x1000
|
||||
extensionIDReserved = 0xF
|
||||
ccMask = 0xF
|
||||
markerShift = 7
|
||||
markerMask = 0x1
|
||||
ptMask = 0x7F
|
||||
seqNumOffset = 2
|
||||
seqNumLength = 2
|
||||
timestampOffset = 4
|
||||
timestampLength = 4
|
||||
ssrcOffset = 8
|
||||
ssrcLength = 4
|
||||
csrcOffset = 12
|
||||
csrcLength = 4
|
||||
)
|
||||
|
||||
// String helps with debugging by printing packet information in a readable way
|
||||
func (p Packet) String() string {
|
||||
out := "RTP PACKET:\n"
|
||||
|
||||
out += fmt.Sprintf("\tVersion: %v\n", p.Version)
|
||||
out += fmt.Sprintf("\tMarker: %v\n", p.Marker)
|
||||
out += fmt.Sprintf("\tPayload Type: %d\n", p.PayloadType)
|
||||
out += fmt.Sprintf("\tSequence Number: %d\n", p.SequenceNumber)
|
||||
out += fmt.Sprintf("\tTimestamp: %d\n", p.Timestamp)
|
||||
out += fmt.Sprintf("\tSSRC: %d (%x)\n", p.SSRC, p.SSRC)
|
||||
out += fmt.Sprintf("\tPayload Length: %d\n", len(p.Payload))
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// Unmarshal parses the passed byte slice and stores the result in the Header this method is called upon
|
||||
func (h *Header) Unmarshal(rawPacket []byte) error { //nolint:gocognit
|
||||
if len(rawPacket) < headerLength {
|
||||
return fmt.Errorf("%w: %d < %d", errHeaderSizeInsufficient, len(rawPacket), headerLength)
|
||||
}
|
||||
|
||||
/*
|
||||
* 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|X| CC |M| PT | sequence number |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | timestamp |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | synchronization source (SSRC) identifier |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* | contributing source (CSRC) identifiers |
|
||||
* | .... |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
h.Version = rawPacket[0] >> versionShift & versionMask
|
||||
h.Padding = (rawPacket[0] >> paddingShift & paddingMask) > 0
|
||||
h.Extension = (rawPacket[0] >> extensionShift & extensionMask) > 0
|
||||
nCSRC := int(rawPacket[0] & ccMask)
|
||||
if cap(h.CSRC) < nCSRC || h.CSRC == nil {
|
||||
h.CSRC = make([]uint32, nCSRC)
|
||||
} else {
|
||||
h.CSRC = h.CSRC[:nCSRC]
|
||||
}
|
||||
|
||||
currOffset := csrcOffset + (nCSRC * csrcLength)
|
||||
if len(rawPacket) < currOffset {
|
||||
return fmt.Errorf("size %d < %d: %w", len(rawPacket), currOffset, errHeaderSizeInsufficient)
|
||||
}
|
||||
|
||||
h.Marker = (rawPacket[1] >> markerShift & markerMask) > 0
|
||||
h.PayloadType = rawPacket[1] & ptMask
|
||||
|
||||
h.SequenceNumber = binary.BigEndian.Uint16(rawPacket[seqNumOffset : seqNumOffset+seqNumLength])
|
||||
h.Timestamp = binary.BigEndian.Uint32(rawPacket[timestampOffset : timestampOffset+timestampLength])
|
||||
h.SSRC = binary.BigEndian.Uint32(rawPacket[ssrcOffset : ssrcOffset+ssrcLength])
|
||||
|
||||
for i := range h.CSRC {
|
||||
offset := csrcOffset + (i * csrcLength)
|
||||
h.CSRC[i] = binary.BigEndian.Uint32(rawPacket[offset:])
|
||||
}
|
||||
|
||||
if h.Extensions != nil {
|
||||
h.Extensions = h.Extensions[:0]
|
||||
}
|
||||
|
||||
if h.Extension {
|
||||
if expected := currOffset + 4; len(rawPacket) < expected {
|
||||
return fmt.Errorf("size %d < %d: %w",
|
||||
len(rawPacket), expected,
|
||||
errHeaderSizeInsufficientForExtension,
|
||||
)
|
||||
}
|
||||
|
||||
h.ExtensionProfile = binary.BigEndian.Uint16(rawPacket[currOffset:])
|
||||
currOffset += 2
|
||||
extensionLength := int(binary.BigEndian.Uint16(rawPacket[currOffset:])) * 4
|
||||
currOffset += 2
|
||||
|
||||
if expected := currOffset + extensionLength; len(rawPacket) < expected {
|
||||
return fmt.Errorf("size %d < %d: %w",
|
||||
len(rawPacket), expected,
|
||||
errHeaderSizeInsufficientForExtension,
|
||||
)
|
||||
}
|
||||
|
||||
switch h.ExtensionProfile {
|
||||
// RFC 8285 RTP One Byte Header Extension
|
||||
case extensionProfileOneByte:
|
||||
end := currOffset + extensionLength
|
||||
for currOffset < end {
|
||||
if rawPacket[currOffset] == 0x00 { // padding
|
||||
currOffset++
|
||||
continue
|
||||
}
|
||||
|
||||
extid := rawPacket[currOffset] >> 4
|
||||
len := int(rawPacket[currOffset]&^0xF0 + 1)
|
||||
currOffset++
|
||||
|
||||
if extid == extensionIDReserved {
|
||||
break
|
||||
}
|
||||
|
||||
extension := Extension{id: extid, payload: rawPacket[currOffset : currOffset+len]}
|
||||
h.Extensions = append(h.Extensions, extension)
|
||||
currOffset += len
|
||||
}
|
||||
|
||||
// RFC 8285 RTP Two Byte Header Extension
|
||||
case extensionProfileTwoByte:
|
||||
end := currOffset + extensionLength
|
||||
for currOffset < end {
|
||||
if rawPacket[currOffset] == 0x00 { // padding
|
||||
currOffset++
|
||||
continue
|
||||
}
|
||||
|
||||
extid := rawPacket[currOffset]
|
||||
currOffset++
|
||||
|
||||
len := int(rawPacket[currOffset])
|
||||
currOffset++
|
||||
|
||||
extension := Extension{id: extid, payload: rawPacket[currOffset : currOffset+len]}
|
||||
h.Extensions = append(h.Extensions, extension)
|
||||
currOffset += len
|
||||
}
|
||||
|
||||
default: // RFC3550 Extension
|
||||
if len(rawPacket) < currOffset+extensionLength {
|
||||
return fmt.Errorf("%w: %d < %d", errHeaderSizeInsufficientForExtension, len(rawPacket), currOffset+extensionLength)
|
||||
}
|
||||
|
||||
extension := Extension{id: 0, payload: rawPacket[currOffset : currOffset+extensionLength]}
|
||||
h.Extensions = append(h.Extensions, extension)
|
||||
currOffset += len(h.Extensions[0].payload)
|
||||
}
|
||||
}
|
||||
|
||||
h.PayloadOffset = currOffset
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unmarshal parses the passed byte slice and stores the result in the Packet this method is called upon
|
||||
func (p *Packet) Unmarshal(rawPacket []byte) error {
|
||||
if err := p.Header.Unmarshal(rawPacket); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.Payload = rawPacket[p.PayloadOffset:]
|
||||
p.Raw = rawPacket
|
||||
return nil
|
||||
}
|
||||
|
||||
// Marshal serializes the header into bytes.
|
||||
func (h *Header) Marshal() (buf []byte, err error) {
|
||||
buf = make([]byte, h.MarshalSize())
|
||||
|
||||
n, err := h.MarshalTo(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf[:n], nil
|
||||
}
|
||||
|
||||
// MarshalTo serializes the header and writes to the buffer.
|
||||
func (h *Header) 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|X| CC |M| PT | sequence number |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | timestamp |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | synchronization source (SSRC) identifier |
|
||||
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
* | contributing source (CSRC) identifiers |
|
||||
* | .... |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
size := h.MarshalSize()
|
||||
if size > len(buf) {
|
||||
return 0, io.ErrShortBuffer
|
||||
}
|
||||
|
||||
// The first byte contains the version, padding bit, extension bit, and csrc size
|
||||
buf[0] = (h.Version << versionShift) | uint8(len(h.CSRC))
|
||||
if h.Padding {
|
||||
buf[0] |= 1 << paddingShift
|
||||
}
|
||||
|
||||
if h.Extension {
|
||||
buf[0] |= 1 << extensionShift
|
||||
}
|
||||
|
||||
// The second byte contains the marker bit and payload type.
|
||||
buf[1] = h.PayloadType
|
||||
if h.Marker {
|
||||
buf[1] |= 1 << markerShift
|
||||
}
|
||||
|
||||
binary.BigEndian.PutUint16(buf[2:4], h.SequenceNumber)
|
||||
binary.BigEndian.PutUint32(buf[4:8], h.Timestamp)
|
||||
binary.BigEndian.PutUint32(buf[8:12], h.SSRC)
|
||||
|
||||
n = 12
|
||||
for _, csrc := range h.CSRC {
|
||||
binary.BigEndian.PutUint32(buf[n:n+4], csrc)
|
||||
n += 4
|
||||
}
|
||||
|
||||
if h.Extension {
|
||||
extHeaderPos := n
|
||||
binary.BigEndian.PutUint16(buf[n+0:n+2], h.ExtensionProfile)
|
||||
n += 4
|
||||
startExtensionsPos := n
|
||||
|
||||
switch h.ExtensionProfile {
|
||||
// RFC 8285 RTP One Byte Header Extension
|
||||
case extensionProfileOneByte:
|
||||
for _, extension := range h.Extensions {
|
||||
buf[n] = extension.id<<4 | (uint8(len(extension.payload)) - 1)
|
||||
n++
|
||||
n += copy(buf[n:], extension.payload)
|
||||
}
|
||||
// RFC 8285 RTP Two Byte Header Extension
|
||||
case extensionProfileTwoByte:
|
||||
for _, extension := range h.Extensions {
|
||||
buf[n] = extension.id
|
||||
n++
|
||||
buf[n] = uint8(len(extension.payload))
|
||||
n++
|
||||
n += copy(buf[n:], extension.payload)
|
||||
}
|
||||
default: // RFC3550 Extension
|
||||
extlen := len(h.Extensions[0].payload)
|
||||
if extlen%4 != 0 {
|
||||
// the payload must be in 32-bit words.
|
||||
return 0, io.ErrShortBuffer
|
||||
}
|
||||
n += copy(buf[n:], h.Extensions[0].payload)
|
||||
}
|
||||
|
||||
// calculate extensions size and round to 4 bytes boundaries
|
||||
extSize := n - startExtensionsPos
|
||||
roundedExtSize := ((extSize + 3) / 4) * 4
|
||||
|
||||
binary.BigEndian.PutUint16(buf[extHeaderPos+2:extHeaderPos+4], uint16(roundedExtSize/4))
|
||||
|
||||
// add padding to reach 4 bytes boundaries
|
||||
for i := 0; i < roundedExtSize-extSize; i++ {
|
||||
buf[n] = 0
|
||||
n++
|
||||
}
|
||||
}
|
||||
|
||||
h.PayloadOffset = n
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// MarshalSize returns the size of the header once marshaled.
|
||||
func (h *Header) MarshalSize() int {
|
||||
// NOTE: Be careful to match the MarshalTo() method.
|
||||
size := 12 + (len(h.CSRC) * csrcLength)
|
||||
|
||||
if h.Extension {
|
||||
extSize := 4
|
||||
|
||||
switch h.ExtensionProfile {
|
||||
// RFC 8285 RTP One Byte Header Extension
|
||||
case extensionProfileOneByte:
|
||||
for _, extension := range h.Extensions {
|
||||
extSize += 1 + len(extension.payload)
|
||||
}
|
||||
// RFC 8285 RTP Two Byte Header Extension
|
||||
case extensionProfileTwoByte:
|
||||
for _, extension := range h.Extensions {
|
||||
extSize += 2 + len(extension.payload)
|
||||
}
|
||||
default:
|
||||
extSize += len(h.Extensions[0].payload)
|
||||
}
|
||||
|
||||
// extensions size must have 4 bytes boundaries
|
||||
size += ((extSize + 3) / 4) * 4
|
||||
}
|
||||
|
||||
return size
|
||||
}
|
||||
|
||||
// SetExtension sets an RTP header extension
|
||||
func (h *Header) SetExtension(id uint8, payload []byte) error { //nolint:gocognit
|
||||
if h.Extension {
|
||||
switch h.ExtensionProfile {
|
||||
// RFC 8285 RTP One Byte Header Extension
|
||||
case extensionProfileOneByte:
|
||||
if id < 1 || id > 14 {
|
||||
return fmt.Errorf("%w actual(%d)", errRFC8285OneByteHeaderIDRange, id)
|
||||
}
|
||||
if len(payload) > 16 {
|
||||
return fmt.Errorf("%w actual(%d)", errRFC8285OneByteHeaderSize, len(payload))
|
||||
}
|
||||
// RFC 8285 RTP Two Byte Header Extension
|
||||
case extensionProfileTwoByte:
|
||||
if id < 1 || id > 255 {
|
||||
return fmt.Errorf("%w actual(%d)", errRFC8285TwoByteHeaderIDRange, id)
|
||||
}
|
||||
if len(payload) > 255 {
|
||||
return fmt.Errorf("%w actual(%d)", errRFC8285TwoByteHeaderSize, len(payload))
|
||||
}
|
||||
default: // RFC3550 Extension
|
||||
if id != 0 {
|
||||
return fmt.Errorf("%w actual(%d)", errRFC3550HeaderIDRange, id)
|
||||
}
|
||||
}
|
||||
|
||||
// Update existing if it exists else add new extension
|
||||
for i, extension := range h.Extensions {
|
||||
if extension.id == id {
|
||||
h.Extensions[i].payload = payload
|
||||
return nil
|
||||
}
|
||||
}
|
||||
h.Extensions = append(h.Extensions, Extension{id: id, payload: payload})
|
||||
return nil
|
||||
}
|
||||
|
||||
// No existing header extensions
|
||||
h.Extension = true
|
||||
|
||||
switch len := len(payload); {
|
||||
case len <= 16:
|
||||
h.ExtensionProfile = extensionProfileOneByte
|
||||
case len > 16 && len < 256:
|
||||
h.ExtensionProfile = extensionProfileTwoByte
|
||||
}
|
||||
|
||||
h.Extensions = append(h.Extensions, Extension{id: id, payload: payload})
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetExtensionIDs returns an extension id array
|
||||
func (h *Header) GetExtensionIDs() []uint8 {
|
||||
if !h.Extension {
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(h.Extensions) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
ids := make([]uint8, 0, len(h.Extensions))
|
||||
for _, extension := range h.Extensions {
|
||||
ids = append(ids, extension.id)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
// GetExtension returns an RTP header extension
|
||||
func (h *Header) GetExtension(id uint8) []byte {
|
||||
if !h.Extension {
|
||||
return nil
|
||||
}
|
||||
for _, extension := range h.Extensions {
|
||||
if extension.id == id {
|
||||
return extension.payload
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelExtension Removes an RTP Header extension
|
||||
func (h *Header) DelExtension(id uint8) error {
|
||||
if !h.Extension {
|
||||
return errHeaderExtensionsNotEnabled
|
||||
}
|
||||
for i, extension := range h.Extensions {
|
||||
if extension.id == id {
|
||||
h.Extensions = append(h.Extensions[:i], h.Extensions[i+1:]...)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errHeaderExtensionNotFound
|
||||
}
|
||||
|
||||
// Marshal serializes the packet into bytes.
|
||||
func (p *Packet) Marshal() (buf []byte, err error) {
|
||||
buf = make([]byte, p.MarshalSize())
|
||||
|
||||
n, err := p.MarshalTo(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf[:n], nil
|
||||
}
|
||||
|
||||
// MarshalTo serializes the packet and writes to the buffer.
|
||||
func (p *Packet) MarshalTo(buf []byte) (n int, err error) {
|
||||
n, err = p.Header.MarshalTo(buf)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Make sure the buffer is large enough to hold the packet.
|
||||
if n+len(p.Payload) > len(buf) {
|
||||
return 0, io.ErrShortBuffer
|
||||
}
|
||||
|
||||
m := copy(buf[n:], p.Payload)
|
||||
p.Raw = buf[:n+m]
|
||||
|
||||
return n + m, nil
|
||||
}
|
||||
|
||||
// MarshalSize returns the size of the packet once marshaled.
|
||||
func (p *Packet) MarshalSize() int {
|
||||
return p.Header.MarshalSize() + len(p.Payload)
|
||||
}
|
91
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/packetizer.go
generated
vendored
Normal file
91
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/packetizer.go
generated
vendored
Normal file
|
@ -0,0 +1,91 @@
|
|||
package rtp
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Payloader payloads a byte array for use as rtp.Packet payloads
|
||||
type Payloader interface {
|
||||
Payload(mtu int, payload []byte) [][]byte
|
||||
}
|
||||
|
||||
// Packetizer packetizes a payload
|
||||
type Packetizer interface {
|
||||
Packetize(payload []byte, samples uint32) []*Packet
|
||||
EnableAbsSendTime(value int)
|
||||
}
|
||||
|
||||
type packetizer struct {
|
||||
MTU int
|
||||
PayloadType uint8
|
||||
SSRC uint32
|
||||
Payloader Payloader
|
||||
Sequencer Sequencer
|
||||
Timestamp uint32
|
||||
ClockRate uint32
|
||||
extensionNumbers struct { // put extension numbers in here. If they're 0, the extension is disabled (0 is not a legal extension number)
|
||||
AbsSendTime int // http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
|
||||
}
|
||||
timegen func() time.Time
|
||||
}
|
||||
|
||||
// NewPacketizer returns a new instance of a Packetizer for a specific payloader
|
||||
func NewPacketizer(mtu int, pt uint8, ssrc uint32, payloader Payloader, sequencer Sequencer, clockRate uint32) Packetizer {
|
||||
return &packetizer{
|
||||
MTU: mtu,
|
||||
PayloadType: pt,
|
||||
SSRC: ssrc,
|
||||
Payloader: payloader,
|
||||
Sequencer: sequencer,
|
||||
Timestamp: globalMathRandomGenerator.Uint32(),
|
||||
ClockRate: clockRate,
|
||||
timegen: time.Now,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *packetizer) EnableAbsSendTime(value int) {
|
||||
p.extensionNumbers.AbsSendTime = value
|
||||
}
|
||||
|
||||
// Packetize packetizes the payload of an RTP packet and returns one or more RTP packets
|
||||
func (p *packetizer) Packetize(payload []byte, samples uint32) []*Packet {
|
||||
// Guard against an empty payload
|
||||
if len(payload) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
payloads := p.Payloader.Payload(p.MTU-12, payload)
|
||||
packets := make([]*Packet, len(payloads))
|
||||
|
||||
for i, pp := range payloads {
|
||||
packets[i] = &Packet{
|
||||
Header: Header{
|
||||
Version: 2,
|
||||
Padding: false,
|
||||
Extension: false,
|
||||
Marker: i == len(payloads)-1,
|
||||
PayloadType: p.PayloadType,
|
||||
SequenceNumber: p.Sequencer.NextSequenceNumber(),
|
||||
Timestamp: p.Timestamp, // Figure out how to do timestamps
|
||||
SSRC: p.SSRC,
|
||||
},
|
||||
Payload: pp,
|
||||
}
|
||||
}
|
||||
p.Timestamp += samples
|
||||
|
||||
if len(packets) != 0 && p.extensionNumbers.AbsSendTime != 0 {
|
||||
sendTime := NewAbsSendTimeExtension(p.timegen())
|
||||
// apply http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
|
||||
b, err := sendTime.Marshal()
|
||||
if err != nil {
|
||||
return nil // never happens
|
||||
}
|
||||
err = packets[len(packets)-1].SetExtension(uint8(p.extensionNumbers.AbsSendTime), b)
|
||||
if err != nil {
|
||||
return nil // never happens
|
||||
}
|
||||
}
|
||||
|
||||
return packets
|
||||
}
|
6
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/partitionheadchecker.go
generated
vendored
Normal file
6
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/partitionheadchecker.go
generated
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
package rtp
|
||||
|
||||
// PartitionHeadChecker is the interface that checks whether the packet is keyframe or not
|
||||
type PartitionHeadChecker interface {
|
||||
IsPartitionHead([]byte) bool
|
||||
}
|
8
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/rand.go
generated
vendored
Normal file
8
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/rand.go
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
package rtp
|
||||
|
||||
import (
|
||||
"github.com/pion/randutil"
|
||||
)
|
||||
|
||||
// Use global random generator to properly seed by crypto grade random.
|
||||
var globalMathRandomGenerator = randutil.NewMathRandomGenerator() // nolint:gochecknoglobals
|
15
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/renovate.json
generated
vendored
Normal file
15
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/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"]
|
||||
}
|
||||
]
|
||||
}
|
2
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/rtp.go
generated
vendored
Normal file
2
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/rtp.go
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
// Package rtp provides RTP packetizer and depacketizer
|
||||
package rtp
|
57
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/sequencer.go
generated
vendored
Normal file
57
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/sequencer.go
generated
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
package rtp
|
||||
|
||||
import (
|
||||
"math"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Sequencer generates sequential sequence numbers for building RTP packets
|
||||
type Sequencer interface {
|
||||
NextSequenceNumber() uint16
|
||||
RollOverCount() uint64
|
||||
}
|
||||
|
||||
// NewRandomSequencer returns a new sequencer starting from a random sequence
|
||||
// number
|
||||
func NewRandomSequencer() Sequencer {
|
||||
return &sequencer{
|
||||
sequenceNumber: uint16(globalMathRandomGenerator.Intn(math.MaxUint16)),
|
||||
}
|
||||
}
|
||||
|
||||
// NewFixedSequencer returns a new sequencer starting from a specific
|
||||
// sequence number
|
||||
func NewFixedSequencer(s uint16) Sequencer {
|
||||
return &sequencer{
|
||||
sequenceNumber: s - 1, // -1 because the first sequence number prepends 1
|
||||
}
|
||||
}
|
||||
|
||||
type sequencer struct {
|
||||
sequenceNumber uint16
|
||||
rollOverCount uint64
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
// NextSequenceNumber increment and returns a new sequence number for
|
||||
// building RTP packets
|
||||
func (s *sequencer) NextSequenceNumber() uint16 {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
s.sequenceNumber++
|
||||
if s.sequenceNumber == 0 {
|
||||
s.rollOverCount++
|
||||
}
|
||||
|
||||
return s.sequenceNumber
|
||||
}
|
||||
|
||||
// RollOverCount returns the amount of times the 16bit sequence number
|
||||
// has wrapped
|
||||
func (s *sequencer) RollOverCount() uint64 {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
return s.rollOverCount
|
||||
}
|
39
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/transportccextension.go
generated
vendored
Normal file
39
trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/transportccextension.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
package rtp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
const (
|
||||
// transport-wide sequence
|
||||
transportCCExtensionSize = 2
|
||||
)
|
||||
|
||||
// TransportCCExtension is a extension payload format in
|
||||
// https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01
|
||||
// 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
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | 0xBE | 0xDE | length=1 |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | ID | L=1 |transport-wide sequence number | zero padding |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
type TransportCCExtension struct {
|
||||
TransportSequence uint16
|
||||
}
|
||||
|
||||
// Marshal serializes the members to buffer
|
||||
func (t *TransportCCExtension) Marshal() ([]byte, error) {
|
||||
buf := make([]byte, transportCCExtensionSize)
|
||||
binary.BigEndian.PutUint16(buf[0:2], t.TransportSequence)
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
// Unmarshal parses the passed byte slice and stores the result in the members
|
||||
func (t *TransportCCExtension) Unmarshal(rawData []byte) error {
|
||||
if len(rawData) < transportCCExtensionSize {
|
||||
return errTooSmall
|
||||
}
|
||||
t.TransportSequence = binary.BigEndian.Uint16(rawData[0:2])
|
||||
return nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue