summaryrefslogtreecommitdiff
path: root/vendor/github.com/pion/rtp
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/pion/rtp')
-rw-r--r--vendor/github.com/pion/rtp/.gitignore24
-rw-r--r--vendor/github.com/pion/rtp/.golangci.yml89
-rw-r--r--vendor/github.com/pion/rtp/LICENSE21
-rw-r--r--vendor/github.com/pion/rtp/README.md53
-rw-r--r--vendor/github.com/pion/rtp/abssendtimeextension.go78
-rw-r--r--vendor/github.com/pion/rtp/audiolevelextension.go60
-rw-r--r--vendor/github.com/pion/rtp/codecov.yml20
-rw-r--r--vendor/github.com/pion/rtp/codecs/codecs.go2
-rw-r--r--vendor/github.com/pion/rtp/codecs/common.go8
-rw-r--r--vendor/github.com/pion/rtp/codecs/error.go11
-rw-r--r--vendor/github.com/pion/rtp/codecs/g711_packet.go22
-rw-r--r--vendor/github.com/pion/rtp/codecs/g722_packet.go22
-rw-r--r--vendor/github.com/pion/rtp/codecs/h264_packet.go205
-rw-r--r--vendor/github.com/pion/rtp/codecs/opus_packet.go44
-rw-r--r--vendor/github.com/pion/rtp/codecs/vp8_packet.go143
-rw-r--r--vendor/github.com/pion/rtp/codecs/vp9_packet.go385
-rw-r--r--vendor/github.com/pion/rtp/depacketizer.go6
-rw-r--r--vendor/github.com/pion/rtp/error.go21
-rw-r--r--vendor/github.com/pion/rtp/go.mod5
-rw-r--r--vendor/github.com/pion/rtp/go.sum2
-rw-r--r--vendor/github.com/pion/rtp/packet.go490
-rw-r--r--vendor/github.com/pion/rtp/packetizer.go91
-rw-r--r--vendor/github.com/pion/rtp/partitionheadchecker.go6
-rw-r--r--vendor/github.com/pion/rtp/rand.go8
-rw-r--r--vendor/github.com/pion/rtp/renovate.json15
-rw-r--r--vendor/github.com/pion/rtp/rtp.go2
-rw-r--r--vendor/github.com/pion/rtp/sequencer.go57
-rw-r--r--vendor/github.com/pion/rtp/transportccextension.go39
28 files changed, 1929 insertions, 0 deletions
diff --git a/vendor/github.com/pion/rtp/.gitignore b/vendor/github.com/pion/rtp/.gitignore
new file mode 100644
index 0000000..83db74b
--- /dev/null
+++ b/vendor/github.com/pion/rtp/.gitignore
@@ -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
diff --git a/vendor/github.com/pion/rtp/.golangci.yml b/vendor/github.com/pion/rtp/.golangci.yml
new file mode 100644
index 0000000..d6162c9
--- /dev/null
+++ b/vendor/github.com/pion/rtp/.golangci.yml
@@ -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
diff --git a/vendor/github.com/pion/rtp/LICENSE b/vendor/github.com/pion/rtp/LICENSE
new file mode 100644
index 0000000..ab60297
--- /dev/null
+++ b/vendor/github.com/pion/rtp/LICENSE
@@ -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.
diff --git a/vendor/github.com/pion/rtp/README.md b/vendor/github.com/pion/rtp/README.md
new file mode 100644
index 0000000..b17709e
--- /dev/null
+++ b/vendor/github.com/pion/rtp/README.md
@@ -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
diff --git a/vendor/github.com/pion/rtp/abssendtimeextension.go b/vendor/github.com/pion/rtp/abssendtimeextension.go
new file mode 100644
index 0000000..fc9731d
--- /dev/null
+++ b/vendor/github.com/pion/rtp/abssendtimeextension.go
@@ -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))
+}
diff --git a/vendor/github.com/pion/rtp/audiolevelextension.go b/vendor/github.com/pion/rtp/audiolevelextension.go
new file mode 100644
index 0000000..f8701e1
--- /dev/null
+++ b/vendor/github.com/pion/rtp/audiolevelextension.go
@@ -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
+}
diff --git a/vendor/github.com/pion/rtp/codecov.yml b/vendor/github.com/pion/rtp/codecov.yml
new file mode 100644
index 0000000..085200a
--- /dev/null
+++ b/vendor/github.com/pion/rtp/codecov.yml
@@ -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/**/*"
diff --git a/vendor/github.com/pion/rtp/codecs/codecs.go b/vendor/github.com/pion/rtp/codecs/codecs.go
new file mode 100644
index 0000000..0e07897
--- /dev/null
+++ b/vendor/github.com/pion/rtp/codecs/codecs.go
@@ -0,0 +1,2 @@
+// Package codecs implements codec specific RTP payloader/depayloaders
+package codecs
diff --git a/vendor/github.com/pion/rtp/codecs/common.go b/vendor/github.com/pion/rtp/codecs/common.go
new file mode 100644
index 0000000..39336d2
--- /dev/null
+++ b/vendor/github.com/pion/rtp/codecs/common.go
@@ -0,0 +1,8 @@
+package codecs
+
+func min(a, b int) int {
+ if a < b {
+ return a
+ }
+ return b
+}
diff --git a/vendor/github.com/pion/rtp/codecs/error.go b/vendor/github.com/pion/rtp/codecs/error.go
new file mode 100644
index 0000000..38ee907
--- /dev/null
+++ b/vendor/github.com/pion/rtp/codecs/error.go
@@ -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")
+)
diff --git a/vendor/github.com/pion/rtp/codecs/g711_packet.go b/vendor/github.com/pion/rtp/codecs/g711_packet.go
new file mode 100644
index 0000000..a74876f
--- /dev/null
+++ b/vendor/github.com/pion/rtp/codecs/g711_packet.go
@@ -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)
+}
diff --git a/vendor/github.com/pion/rtp/codecs/g722_packet.go b/vendor/github.com/pion/rtp/codecs/g722_packet.go
new file mode 100644
index 0000000..70c9883
--- /dev/null
+++ b/vendor/github.com/pion/rtp/codecs/g722_packet.go
@@ -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)
+}
diff --git a/vendor/github.com/pion/rtp/codecs/h264_packet.go b/vendor/github.com/pion/rtp/codecs/h264_packet.go
new file mode 100644
index 0000000..3ee5926
--- /dev/null
+++ b/vendor/github.com/pion/rtp/codecs/h264_packet.go
@@ -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)
+}
diff --git a/vendor/github.com/pion/rtp/codecs/opus_packet.go b/vendor/github.com/pion/rtp/codecs/opus_packet.go
new file mode 100644
index 0000000..504741f
--- /dev/null
+++ b/vendor/github.com/pion/rtp/codecs/opus_packet.go
@@ -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
+}
diff --git a/vendor/github.com/pion/rtp/codecs/vp8_packet.go b/vendor/github.com/pion/rtp/codecs/vp8_packet.go
new file mode 100644
index 0000000..7ade7da
--- /dev/null
+++ b/vendor/github.com/pion/rtp/codecs/vp8_packet.go
@@ -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
+}
diff --git a/vendor/github.com/pion/rtp/codecs/vp9_packet.go b/vendor/github.com/pion/rtp/codecs/vp9_packet.go
new file mode 100644
index 0000000..5cb619b
--- /dev/null
+++ b/vendor/github.com/pion/rtp/codecs/vp9_packet.go
@@ -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
+}
diff --git a/vendor/github.com/pion/rtp/depacketizer.go b/vendor/github.com/pion/rtp/depacketizer.go
new file mode 100644
index 0000000..b8c09da
--- /dev/null
+++ b/vendor/github.com/pion/rtp/depacketizer.go
@@ -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)
+}
diff --git a/vendor/github.com/pion/rtp/error.go b/vendor/github.com/pion/rtp/error.go
new file mode 100644
index 0000000..5458c6f
--- /dev/null
+++ b/vendor/github.com/pion/rtp/error.go
@@ -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")
+)
diff --git a/vendor/github.com/pion/rtp/go.mod b/vendor/github.com/pion/rtp/go.mod
new file mode 100644
index 0000000..412ae63
--- /dev/null
+++ b/vendor/github.com/pion/rtp/go.mod
@@ -0,0 +1,5 @@
+module github.com/pion/rtp
+
+go 1.13
+
+require github.com/pion/randutil v0.1.0
diff --git a/vendor/github.com/pion/rtp/go.sum b/vendor/github.com/pion/rtp/go.sum
new file mode 100644
index 0000000..401b903
--- /dev/null
+++ b/vendor/github.com/pion/rtp/go.sum
@@ -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=
diff --git a/vendor/github.com/pion/rtp/packet.go b/vendor/github.com/pion/rtp/packet.go
new file mode 100644
index 0000000..b237b0a
--- /dev/null
+++ b/vendor/github.com/pion/rtp/packet.go
@@ -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)
+}
diff --git a/vendor/github.com/pion/rtp/packetizer.go b/vendor/github.com/pion/rtp/packetizer.go
new file mode 100644
index 0000000..5a8482f
--- /dev/null
+++ b/vendor/github.com/pion/rtp/packetizer.go
@@ -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
+}
diff --git a/vendor/github.com/pion/rtp/partitionheadchecker.go b/vendor/github.com/pion/rtp/partitionheadchecker.go
new file mode 100644
index 0000000..6ec2a76
--- /dev/null
+++ b/vendor/github.com/pion/rtp/partitionheadchecker.go
@@ -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
+}
diff --git a/vendor/github.com/pion/rtp/rand.go b/vendor/github.com/pion/rtp/rand.go
new file mode 100644
index 0000000..ee85523
--- /dev/null
+++ b/vendor/github.com/pion/rtp/rand.go
@@ -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
diff --git a/vendor/github.com/pion/rtp/renovate.json b/vendor/github.com/pion/rtp/renovate.json
new file mode 100644
index 0000000..4400fd9
--- /dev/null
+++ b/vendor/github.com/pion/rtp/renovate.json
@@ -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"]
+ }
+ ]
+}
diff --git a/vendor/github.com/pion/rtp/rtp.go b/vendor/github.com/pion/rtp/rtp.go
new file mode 100644
index 0000000..b66b2e4
--- /dev/null
+++ b/vendor/github.com/pion/rtp/rtp.go
@@ -0,0 +1,2 @@
+// Package rtp provides RTP packetizer and depacketizer
+package rtp
diff --git a/vendor/github.com/pion/rtp/sequencer.go b/vendor/github.com/pion/rtp/sequencer.go
new file mode 100644
index 0000000..2b4a507
--- /dev/null
+++ b/vendor/github.com/pion/rtp/sequencer.go
@@ -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
+}
diff --git a/vendor/github.com/pion/rtp/transportccextension.go b/vendor/github.com/pion/rtp/transportccextension.go
new file mode 100644
index 0000000..f9ffe4e
--- /dev/null
+++ b/vendor/github.com/pion/rtp/transportccextension.go
@@ -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
+}