mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
Squash: Merge SRS 4.0, regression test for RTMP.
This commit is contained in:
parent
a81aa2edc5
commit
b874d9c9ba
32 changed files with 9977 additions and 131 deletions
738
trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/amf0/amf0.go
generated
vendored
Normal file
738
trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/amf0/amf0.go
generated
vendored
Normal file
|
@ -0,0 +1,738 @@
|
|||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2013-2017 Oryx(ossrs)
|
||||
//
|
||||
// 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.
|
||||
|
||||
// The oryx amf0 package support AMF0 codec.
|
||||
package amf0
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
oe "github.com/ossrs/go-oryx-lib/errors"
|
||||
"math"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Please read @doc amf0_spec_121207.pdf, @page 4, @section 2.1 Types Overview
|
||||
type marker uint8
|
||||
|
||||
const (
|
||||
markerNumber marker = iota // 0
|
||||
markerBoolean // 1
|
||||
markerString // 2
|
||||
markerObject // 3
|
||||
markerMovieClip // 4
|
||||
markerNull // 5
|
||||
markerUndefined // 6
|
||||
markerReference // 7
|
||||
markerEcmaArray // 8
|
||||
markerObjectEnd // 9
|
||||
markerStrictArray // 10
|
||||
markerDate // 11
|
||||
markerLongString // 12
|
||||
markerUnsupported // 13
|
||||
markerRecordSet // 14
|
||||
markerXmlDocument // 15
|
||||
markerTypedObject // 16
|
||||
markerAvmPlusObject // 17
|
||||
|
||||
markerForbidden marker = 0xff
|
||||
)
|
||||
|
||||
func (v marker) String() string {
|
||||
switch v {
|
||||
case markerNumber:
|
||||
return "Number"
|
||||
case markerBoolean:
|
||||
return "Boolean"
|
||||
case markerString:
|
||||
return "String"
|
||||
case markerObject:
|
||||
return "Object"
|
||||
case markerNull:
|
||||
return "Null"
|
||||
case markerUndefined:
|
||||
return "Undefined"
|
||||
case markerReference:
|
||||
return "Reference"
|
||||
case markerEcmaArray:
|
||||
return "EcmaArray"
|
||||
case markerObjectEnd:
|
||||
return "ObjectEnd"
|
||||
case markerStrictArray:
|
||||
return "StrictArray"
|
||||
case markerDate:
|
||||
return "Date"
|
||||
case markerLongString:
|
||||
return "LongString"
|
||||
case markerUnsupported:
|
||||
return "Unsupported"
|
||||
case markerXmlDocument:
|
||||
return "XmlDocument"
|
||||
case markerTypedObject:
|
||||
return "TypedObject"
|
||||
case markerAvmPlusObject:
|
||||
return "AvmPlusObject"
|
||||
case markerMovieClip:
|
||||
return "MovieClip"
|
||||
case markerRecordSet:
|
||||
return "RecordSet"
|
||||
default:
|
||||
return "Forbidden"
|
||||
}
|
||||
}
|
||||
|
||||
// For utest to mock it.
|
||||
type buffer interface {
|
||||
Bytes() []byte
|
||||
WriteByte(c byte) error
|
||||
Write(p []byte) (n int, err error)
|
||||
}
|
||||
|
||||
var createBuffer = func() buffer {
|
||||
return &bytes.Buffer{}
|
||||
}
|
||||
|
||||
// All AMF0 things.
|
||||
type Amf0 interface {
|
||||
// Binary marshaler and unmarshaler.
|
||||
encoding.BinaryUnmarshaler
|
||||
encoding.BinaryMarshaler
|
||||
// Get the size of bytes to marshal this object.
|
||||
Size() int
|
||||
|
||||
// Get the Marker of any AMF0 stuff.
|
||||
amf0Marker() marker
|
||||
}
|
||||
|
||||
// Discovery the amf0 object from the bytes b.
|
||||
func Discovery(p []byte) (a Amf0, err error) {
|
||||
if len(p) < 1 {
|
||||
return nil, oe.Errorf("require 1 bytes only %v", len(p))
|
||||
}
|
||||
m := marker(p[0])
|
||||
|
||||
switch m {
|
||||
case markerNumber:
|
||||
return NewNumber(0), nil
|
||||
case markerBoolean:
|
||||
return NewBoolean(false), nil
|
||||
case markerString:
|
||||
return NewString(""), nil
|
||||
case markerObject:
|
||||
return NewObject(), nil
|
||||
case markerNull:
|
||||
return NewNull(), nil
|
||||
case markerUndefined:
|
||||
return NewUndefined(), nil
|
||||
case markerReference:
|
||||
case markerEcmaArray:
|
||||
return NewEcmaArray(), nil
|
||||
case markerObjectEnd:
|
||||
return &objectEOF{}, nil
|
||||
case markerStrictArray:
|
||||
return NewStrictArray(), nil
|
||||
case markerDate, markerLongString, markerUnsupported, markerXmlDocument,
|
||||
markerTypedObject, markerAvmPlusObject, markerForbidden, markerMovieClip,
|
||||
markerRecordSet:
|
||||
return nil, oe.Errorf("Marker %v is not supported", m)
|
||||
}
|
||||
return nil, oe.Errorf("Marker %v is invalid", m)
|
||||
}
|
||||
|
||||
// The UTF8 string, please read @doc amf0_spec_121207.pdf, @page 3, @section 1.3.1 Strings and UTF-8
|
||||
type amf0UTF8 string
|
||||
|
||||
func (v *amf0UTF8) Size() int {
|
||||
return 2 + len(string(*v))
|
||||
}
|
||||
|
||||
func (v *amf0UTF8) UnmarshalBinary(data []byte) (err error) {
|
||||
var p []byte
|
||||
if p = data; len(p) < 2 {
|
||||
return oe.Errorf("require 2 bytes only %v", len(p))
|
||||
}
|
||||
size := uint16(p[0])<<8 | uint16(p[1])
|
||||
|
||||
if p = data[2:]; len(p) < int(size) {
|
||||
return oe.Errorf("require %v bytes only %v", int(size), len(p))
|
||||
}
|
||||
*v = amf0UTF8(string(p[:size]))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (v *amf0UTF8) MarshalBinary() (data []byte, err error) {
|
||||
data = make([]byte, v.Size())
|
||||
|
||||
size := uint16(len(string(*v)))
|
||||
data[0] = byte(size >> 8)
|
||||
data[1] = byte(size)
|
||||
|
||||
if size > 0 {
|
||||
copy(data[2:], []byte(*v))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// The number object, please read @doc amf0_spec_121207.pdf, @page 5, @section 2.2 Number Type
|
||||
type Number float64
|
||||
|
||||
func NewNumber(f float64) *Number {
|
||||
v := Number(f)
|
||||
return &v
|
||||
}
|
||||
|
||||
func (v *Number) amf0Marker() marker {
|
||||
return markerNumber
|
||||
}
|
||||
|
||||
func (v *Number) Size() int {
|
||||
return 1 + 8
|
||||
}
|
||||
|
||||
func (v *Number) UnmarshalBinary(data []byte) (err error) {
|
||||
var p []byte
|
||||
if p = data; len(p) < 9 {
|
||||
return oe.Errorf("require 9 bytes only %v", len(p))
|
||||
}
|
||||
if m := marker(p[0]); m != markerNumber {
|
||||
return oe.Errorf("Number marker %v is illegal", m)
|
||||
}
|
||||
|
||||
f := binary.BigEndian.Uint64(p[1:])
|
||||
*v = Number(math.Float64frombits(f))
|
||||
return
|
||||
}
|
||||
|
||||
func (v *Number) MarshalBinary() (data []byte, err error) {
|
||||
data = make([]byte, 9)
|
||||
data[0] = byte(markerNumber)
|
||||
f := math.Float64bits(float64(*v))
|
||||
binary.BigEndian.PutUint64(data[1:], f)
|
||||
return
|
||||
}
|
||||
|
||||
// The string objet, please read @doc amf0_spec_121207.pdf, @page 5, @section 2.4 String Type
|
||||
type String string
|
||||
|
||||
func NewString(s string) *String {
|
||||
v := String(s)
|
||||
return &v
|
||||
}
|
||||
|
||||
func (v *String) amf0Marker() marker {
|
||||
return markerString
|
||||
}
|
||||
|
||||
func (v *String) Size() int {
|
||||
u := amf0UTF8(*v)
|
||||
return 1 + u.Size()
|
||||
}
|
||||
|
||||
func (v *String) UnmarshalBinary(data []byte) (err error) {
|
||||
var p []byte
|
||||
if p = data; len(p) < 1 {
|
||||
return oe.Errorf("require 1 bytes only %v", len(p))
|
||||
}
|
||||
if m := marker(p[0]); m != markerString {
|
||||
return oe.Errorf("String marker %v is illegal", m)
|
||||
}
|
||||
|
||||
var sv amf0UTF8
|
||||
if err = sv.UnmarshalBinary(p[1:]); err != nil {
|
||||
return oe.WithMessage(err, "utf8")
|
||||
}
|
||||
*v = String(string(sv))
|
||||
return
|
||||
}
|
||||
|
||||
func (v *String) MarshalBinary() (data []byte, err error) {
|
||||
u := amf0UTF8(*v)
|
||||
|
||||
var pb []byte
|
||||
if pb, err = u.MarshalBinary(); err != nil {
|
||||
return nil, oe.WithMessage(err, "utf8")
|
||||
}
|
||||
|
||||
data = append([]byte{byte(markerString)}, pb...)
|
||||
return
|
||||
}
|
||||
|
||||
// The AMF0 object end type, please read @doc amf0_spec_121207.pdf, @page 5, @section 2.11 Object End Type
|
||||
type objectEOF struct {
|
||||
}
|
||||
|
||||
func (v *objectEOF) amf0Marker() marker {
|
||||
return markerObjectEnd
|
||||
}
|
||||
|
||||
func (v *objectEOF) Size() int {
|
||||
return 3
|
||||
}
|
||||
|
||||
func (v *objectEOF) UnmarshalBinary(data []byte) (err error) {
|
||||
p := data
|
||||
|
||||
if len(p) < 3 {
|
||||
return oe.Errorf("require 3 bytes only %v", len(p))
|
||||
}
|
||||
|
||||
if p[0] != 0 || p[1] != 0 || p[2] != 9 {
|
||||
return oe.Errorf("EOF marker %v is illegal", p[0:3])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (v *objectEOF) MarshalBinary() (data []byte, err error) {
|
||||
return []byte{0, 0, 9}, nil
|
||||
}
|
||||
|
||||
// Use array for object and ecma array, to keep the original order.
|
||||
type property struct {
|
||||
key amf0UTF8
|
||||
value Amf0
|
||||
}
|
||||
|
||||
// The object-like AMF0 structure, like object and ecma array and strict array.
|
||||
type objectBase struct {
|
||||
properties []*property
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
func (v *objectBase) Size() int {
|
||||
v.lock.Lock()
|
||||
defer v.lock.Unlock()
|
||||
|
||||
var size int
|
||||
|
||||
for _, p := range v.properties {
|
||||
key, value := p.key, p.value
|
||||
size += key.Size() + value.Size()
|
||||
}
|
||||
|
||||
return size
|
||||
}
|
||||
|
||||
func (v *objectBase) Get(key string) Amf0 {
|
||||
v.lock.Lock()
|
||||
defer v.lock.Unlock()
|
||||
|
||||
for _, p := range v.properties {
|
||||
if string(p.key) == key {
|
||||
return p.value
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *objectBase) Set(key string, value Amf0) *objectBase {
|
||||
v.lock.Lock()
|
||||
defer v.lock.Unlock()
|
||||
|
||||
prop := &property{key: amf0UTF8(key), value: value}
|
||||
|
||||
var ok bool
|
||||
for i, p := range v.properties {
|
||||
if string(p.key) == key {
|
||||
v.properties[i] = prop
|
||||
ok = true
|
||||
}
|
||||
}
|
||||
|
||||
if !ok {
|
||||
v.properties = append(v.properties, prop)
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
func (v *objectBase) unmarshal(p []byte, eof bool, maxElems int) (err error) {
|
||||
// if no eof, elems specified by maxElems.
|
||||
if !eof && maxElems < 0 {
|
||||
return oe.Errorf("maxElems=%v without eof", maxElems)
|
||||
}
|
||||
// if eof, maxElems must be -1.
|
||||
if eof && maxElems != -1 {
|
||||
return oe.Errorf("maxElems=%v with eof", maxElems)
|
||||
}
|
||||
|
||||
readOne := func() (amf0UTF8, Amf0, error) {
|
||||
var u amf0UTF8
|
||||
if err = u.UnmarshalBinary(p); err != nil {
|
||||
return "", nil, oe.WithMessage(err, "prop name")
|
||||
}
|
||||
|
||||
p = p[u.Size():]
|
||||
var a Amf0
|
||||
if a, err = Discovery(p); err != nil {
|
||||
return "", nil, oe.WithMessage(err, fmt.Sprintf("discover prop %v", string(u)))
|
||||
}
|
||||
return u, a, nil
|
||||
}
|
||||
|
||||
pushOne := func(u amf0UTF8, a Amf0) error {
|
||||
// For object property, consume the whole bytes.
|
||||
if err = a.UnmarshalBinary(p); err != nil {
|
||||
return oe.WithMessage(err, fmt.Sprintf("unmarshal prop %v", string(u)))
|
||||
}
|
||||
|
||||
v.Set(string(u), a)
|
||||
p = p[a.Size():]
|
||||
return nil
|
||||
}
|
||||
|
||||
for eof {
|
||||
u, a, err := readOne()
|
||||
if err != nil {
|
||||
return oe.WithMessage(err, "read")
|
||||
}
|
||||
|
||||
// For object EOF, we should only consume total 3bytes.
|
||||
if u.Size() == 2 && a.amf0Marker() == markerObjectEnd {
|
||||
// 2 bytes is consumed by u(name), the a(eof) should only consume 1 byte.
|
||||
p = p[1:]
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := pushOne(u, a); err != nil {
|
||||
return oe.WithMessage(err, "push")
|
||||
}
|
||||
}
|
||||
|
||||
for len(v.properties) < maxElems {
|
||||
u, a, err := readOne()
|
||||
if err != nil {
|
||||
return oe.WithMessage(err, "read")
|
||||
}
|
||||
|
||||
if err := pushOne(u, a); err != nil {
|
||||
return oe.WithMessage(err, "push")
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (v *objectBase) marshal(b buffer) (err error) {
|
||||
v.lock.Lock()
|
||||
defer v.lock.Unlock()
|
||||
|
||||
var pb []byte
|
||||
for _, p := range v.properties {
|
||||
key, value := p.key, p.value
|
||||
|
||||
if pb, err = key.MarshalBinary(); err != nil {
|
||||
return oe.WithMessage(err, fmt.Sprintf("marshal %v", string(key)))
|
||||
}
|
||||
if _, err = b.Write(pb); err != nil {
|
||||
return oe.Wrapf(err, "write %v", string(key))
|
||||
}
|
||||
|
||||
if pb, err = value.MarshalBinary(); err != nil {
|
||||
return oe.WithMessage(err, fmt.Sprintf("marshal value for %v", string(key)))
|
||||
}
|
||||
if _, err = b.Write(pb); err != nil {
|
||||
return oe.Wrapf(err, "marshal value for %v", string(key))
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// The AMF0 object, please read @doc amf0_spec_121207.pdf, @page 5, @section 2.5 Object Type
|
||||
type Object struct {
|
||||
objectBase
|
||||
eof objectEOF
|
||||
}
|
||||
|
||||
func NewObject() *Object {
|
||||
v := &Object{}
|
||||
v.properties = []*property{}
|
||||
return v
|
||||
}
|
||||
|
||||
func (v *Object) amf0Marker() marker {
|
||||
return markerObject
|
||||
}
|
||||
|
||||
func (v *Object) Size() int {
|
||||
return int(1) + v.eof.Size() + v.objectBase.Size()
|
||||
}
|
||||
|
||||
func (v *Object) UnmarshalBinary(data []byte) (err error) {
|
||||
var p []byte
|
||||
if p = data; len(p) < 1 {
|
||||
return oe.Errorf("require 1 byte only %v", len(p))
|
||||
}
|
||||
if m := marker(p[0]); m != markerObject {
|
||||
return oe.Errorf("Object marker %v is illegal", m)
|
||||
}
|
||||
p = p[1:]
|
||||
|
||||
if err = v.unmarshal(p, true, -1); err != nil {
|
||||
return oe.WithMessage(err, "unmarshal")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (v *Object) MarshalBinary() (data []byte, err error) {
|
||||
b := createBuffer()
|
||||
|
||||
if err = b.WriteByte(byte(markerObject)); err != nil {
|
||||
return nil, oe.Wrap(err, "marshal")
|
||||
}
|
||||
|
||||
if err = v.marshal(b); err != nil {
|
||||
return nil, oe.WithMessage(err, "marshal")
|
||||
}
|
||||
|
||||
var pb []byte
|
||||
if pb, err = v.eof.MarshalBinary(); err != nil {
|
||||
return nil, oe.WithMessage(err, "marshal")
|
||||
}
|
||||
if _, err = b.Write(pb); err != nil {
|
||||
return nil, oe.Wrap(err, "marshal")
|
||||
}
|
||||
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
// The AMF0 ecma array, please read @doc amf0_spec_121207.pdf, @page 6, @section 2.10 ECMA Array Type
|
||||
type EcmaArray struct {
|
||||
objectBase
|
||||
count uint32
|
||||
eof objectEOF
|
||||
}
|
||||
|
||||
func NewEcmaArray() *EcmaArray {
|
||||
v := &EcmaArray{}
|
||||
v.properties = []*property{}
|
||||
return v
|
||||
}
|
||||
|
||||
func (v *EcmaArray) amf0Marker() marker {
|
||||
return markerEcmaArray
|
||||
}
|
||||
|
||||
func (v *EcmaArray) Size() int {
|
||||
return int(1) + 4 + v.eof.Size() + v.objectBase.Size()
|
||||
}
|
||||
|
||||
func (v *EcmaArray) UnmarshalBinary(data []byte) (err error) {
|
||||
var p []byte
|
||||
if p = data; len(p) < 5 {
|
||||
return oe.Errorf("require 5 bytes only %v", len(p))
|
||||
}
|
||||
if m := marker(p[0]); m != markerEcmaArray {
|
||||
return oe.Errorf("EcmaArray marker %v is illegal", m)
|
||||
}
|
||||
v.count = binary.BigEndian.Uint32(p[1:])
|
||||
p = p[5:]
|
||||
|
||||
if err = v.unmarshal(p, true, -1); err != nil {
|
||||
return oe.WithMessage(err, "unmarshal")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (v *EcmaArray) MarshalBinary() (data []byte, err error) {
|
||||
b := createBuffer()
|
||||
|
||||
if err = b.WriteByte(byte(markerEcmaArray)); err != nil {
|
||||
return nil, oe.Wrap(err, "marshal")
|
||||
}
|
||||
|
||||
if err = binary.Write(b, binary.BigEndian, v.count); err != nil {
|
||||
return nil, oe.Wrap(err, "marshal")
|
||||
}
|
||||
|
||||
if err = v.marshal(b); err != nil {
|
||||
return nil, oe.WithMessage(err, "marshal")
|
||||
}
|
||||
|
||||
var pb []byte
|
||||
if pb, err = v.eof.MarshalBinary(); err != nil {
|
||||
return nil, oe.WithMessage(err, "marshal")
|
||||
}
|
||||
if _, err = b.Write(pb); err != nil {
|
||||
return nil, oe.Wrap(err, "marshal")
|
||||
}
|
||||
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
// The AMF0 strict array, please read @doc amf0_spec_121207.pdf, @page 7, @section 2.12 Strict Array Type
|
||||
type StrictArray struct {
|
||||
objectBase
|
||||
count uint32
|
||||
}
|
||||
|
||||
func NewStrictArray() *StrictArray {
|
||||
v := &StrictArray{}
|
||||
v.properties = []*property{}
|
||||
return v
|
||||
}
|
||||
|
||||
func (v *StrictArray) amf0Marker() marker {
|
||||
return markerStrictArray
|
||||
}
|
||||
|
||||
func (v *StrictArray) Size() int {
|
||||
return int(1) + 4 + v.objectBase.Size()
|
||||
}
|
||||
|
||||
func (v *StrictArray) UnmarshalBinary(data []byte) (err error) {
|
||||
var p []byte
|
||||
if p = data; len(p) < 5 {
|
||||
return oe.Errorf("require 5 bytes only %v", len(p))
|
||||
}
|
||||
if m := marker(p[0]); m != markerStrictArray {
|
||||
return oe.Errorf("StrictArray marker %v is illegal", m)
|
||||
}
|
||||
v.count = binary.BigEndian.Uint32(p[1:])
|
||||
p = p[5:]
|
||||
|
||||
if int(v.count) <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if err = v.unmarshal(p, false, int(v.count)); err != nil {
|
||||
return oe.WithMessage(err, "unmarshal")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (v *StrictArray) MarshalBinary() (data []byte, err error) {
|
||||
b := createBuffer()
|
||||
|
||||
if err = b.WriteByte(byte(markerStrictArray)); err != nil {
|
||||
return nil, oe.Wrap(err, "marshal")
|
||||
}
|
||||
|
||||
if err = binary.Write(b, binary.BigEndian, v.count); err != nil {
|
||||
return nil, oe.Wrap(err, "marshal")
|
||||
}
|
||||
|
||||
if err = v.marshal(b); err != nil {
|
||||
return nil, oe.WithMessage(err, "marshal")
|
||||
}
|
||||
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
// The single marker object, for all AMF0 which only has the marker, like null and undefined.
|
||||
type singleMarkerObject struct {
|
||||
target marker
|
||||
}
|
||||
|
||||
func newSingleMarkerObject(m marker) singleMarkerObject {
|
||||
return singleMarkerObject{target: m}
|
||||
}
|
||||
|
||||
func (v *singleMarkerObject) amf0Marker() marker {
|
||||
return v.target
|
||||
}
|
||||
|
||||
func (v *singleMarkerObject) Size() int {
|
||||
return int(1)
|
||||
}
|
||||
|
||||
func (v *singleMarkerObject) UnmarshalBinary(data []byte) (err error) {
|
||||
var p []byte
|
||||
if p = data; len(p) < 1 {
|
||||
return oe.Errorf("require 1 byte only %v", len(p))
|
||||
}
|
||||
if m := marker(p[0]); m != v.target {
|
||||
return oe.Errorf("%v marker %v is illegal", v.target, m)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (v *singleMarkerObject) MarshalBinary() (data []byte, err error) {
|
||||
return []byte{byte(v.target)}, nil
|
||||
}
|
||||
|
||||
// The AMF0 null, please read @doc amf0_spec_121207.pdf, @page 6, @section 2.7 null Type
|
||||
type null struct {
|
||||
singleMarkerObject
|
||||
}
|
||||
|
||||
func NewNull() *null {
|
||||
v := null{}
|
||||
v.singleMarkerObject = newSingleMarkerObject(markerNull)
|
||||
return &v
|
||||
}
|
||||
|
||||
// The AMF0 undefined, please read @doc amf0_spec_121207.pdf, @page 6, @section 2.8 undefined Type
|
||||
type undefined struct {
|
||||
singleMarkerObject
|
||||
}
|
||||
|
||||
func NewUndefined() Amf0 {
|
||||
v := undefined{}
|
||||
v.singleMarkerObject = newSingleMarkerObject(markerUndefined)
|
||||
return &v
|
||||
}
|
||||
|
||||
// The AMF0 boolean, please read @doc amf0_spec_121207.pdf, @page 5, @section 2.3 Boolean Type
|
||||
type Boolean bool
|
||||
|
||||
func NewBoolean(b bool) Amf0 {
|
||||
v := Boolean(b)
|
||||
return &v
|
||||
}
|
||||
|
||||
func (v *Boolean) amf0Marker() marker {
|
||||
return markerBoolean
|
||||
}
|
||||
|
||||
func (v *Boolean) Size() int {
|
||||
return int(2)
|
||||
}
|
||||
|
||||
func (v *Boolean) UnmarshalBinary(data []byte) (err error) {
|
||||
var p []byte
|
||||
if p = data; len(p) < 2 {
|
||||
return oe.Errorf("require 2 bytes only %v", len(p))
|
||||
}
|
||||
if m := marker(p[0]); m != markerBoolean {
|
||||
return oe.Errorf("BOOL marker %v is illegal", m)
|
||||
}
|
||||
if p[1] == 0 {
|
||||
*v = false
|
||||
} else {
|
||||
*v = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (v *Boolean) MarshalBinary() (data []byte, err error) {
|
||||
var b byte
|
||||
if *v {
|
||||
b = 1
|
||||
}
|
||||
return []byte{byte(markerBoolean), b}, nil
|
||||
}
|
476
trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/avc/avc.go
generated
vendored
Normal file
476
trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/avc/avc.go
generated
vendored
Normal file
|
@ -0,0 +1,476 @@
|
|||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2013-2017 Oryx(ossrs)
|
||||
//
|
||||
// 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.
|
||||
|
||||
// The oryx AVC package includes some utilites.
|
||||
// The NALU(Netowrk Abstraction Layer Unit) is suitable for transmission over network.
|
||||
// We could package NALUs by AnnexB, IBMF or RTP according to different scenarios.
|
||||
// @note AnnexB is designed for bit-oriented stream, such as MPEG-TS/HLS, please
|
||||
// read ISO_IEC_14496-10-AVC-2003.pdf at page 211, AnnexB Byte stream Format.
|
||||
// @note IBMF is designed for file storage, such as MP4/FLV, please read
|
||||
// ISO_IEC_14496-15-AVC-format-2012.pdf at page 16, 5.2.4.1 AVC decoder
|
||||
// configuration record.
|
||||
// @note RTP payload for H.264, defined in RFC6184 https://tools.ietf.org/html/rfc6184
|
||||
// it directly uses and extends the NAL header.
|
||||
package avc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/ossrs/go-oryx-lib/errors"
|
||||
)
|
||||
|
||||
// @doc ISO_IEC_14496-10-AVC-2003.pdf at page 44, 7.3.1 NAL unit syntax
|
||||
type NALRefIDC uint8
|
||||
|
||||
// @doc ISO_IEC_14496-10-AVC-2003.pdf at page 44, 7.3.1 NAL unit syntax
|
||||
type NALUType uint8
|
||||
|
||||
const (
|
||||
NALUTypeNonIDR NALUType = 1 // Coded slice of a non-IDR picture slice_layer_without_partitioning_rbsp( )
|
||||
NALUTypeDataPartitionA NALUType = 2 // Coded slice data partition A slice_data_partition_a_layer_rbsp( )
|
||||
NALUTypeDataPartitionB NALUType = 3 // Coded slice data partition B slice_data_partition_b_layer_rbsp( )
|
||||
NALUTypeDataPartitionC NALUType = 4 // Coded slice data partition C slice_data_partition_c_layer_rbsp( )
|
||||
NALUTypeIDR NALUType = 5 // Coded slice of an IDR picture slice_layer_without_partitioning_rbsp( )
|
||||
NALUTypeSEI NALUType = 6 // Supplemental enhancement information (SEI) sei_rbsp( )
|
||||
NALUTypeSPS NALUType = 7 // Sequence parameter set seq_parameter_set_rbsp( )
|
||||
NALUTypePPS NALUType = 8 // Picture parameter set pic_parameter_set_rbsp( )
|
||||
NALUTypeAccessUnitDelimiter NALUType = 9 // Access unit delimiter access_unit_delimiter_rbsp( )
|
||||
NALUTypeEOSequence NALUType = 10 // End of sequence end_of_seq_rbsp( )
|
||||
NALUTypeEOStream NALUType = 11 // End of stream end_of_stream_rbsp( )
|
||||
NALUTypeFilterData NALUType = 12 // Filler data filler_data_rbsp( )
|
||||
NALUTypeSPSExt NALUType = 13 // Sequence parameter set extension seq_parameter_set_extension_rbsp( )
|
||||
NALUTypePrefixNALU NALUType = 14 // Prefix NAL unit prefix_nal_unit_rbsp( )
|
||||
NALUTypeSubsetSPS NALUType = 15 // Subset sequence parameter set subset_seq_parameter_set_rbsp( )
|
||||
NALUTypeLayerWithoutPartition NALUType = 19 // Coded slice of an auxiliary coded picture without partitioning slice_layer_without_partitioning_rbsp( )
|
||||
NALUTypeCodedSliceExt NALUType = 20 // Coded slice extension slice_layer_extension_rbsp( )
|
||||
)
|
||||
|
||||
func (v NALUType) String() string {
|
||||
switch v {
|
||||
case NALUTypeNonIDR:
|
||||
return "NonIDR"
|
||||
case NALUTypeDataPartitionA:
|
||||
return "DataPartitionA"
|
||||
case NALUTypeDataPartitionB:
|
||||
return "DataPartitionB"
|
||||
case NALUTypeDataPartitionC:
|
||||
return "DataPartitionC"
|
||||
case NALUTypeIDR:
|
||||
return "IDR"
|
||||
case NALUTypeSEI:
|
||||
return "SEI"
|
||||
case NALUTypeSPS:
|
||||
return "SPS"
|
||||
case NALUTypePPS:
|
||||
return "PPS"
|
||||
case NALUTypeAccessUnitDelimiter:
|
||||
return "AccessUnitDelimiter"
|
||||
case NALUTypeEOSequence:
|
||||
return "EOSequence"
|
||||
case NALUTypeEOStream:
|
||||
return "EOStream"
|
||||
case NALUTypeFilterData:
|
||||
return "FilterData"
|
||||
case NALUTypeSPSExt:
|
||||
return "SPSExt"
|
||||
case NALUTypePrefixNALU:
|
||||
return "PrefixNALU"
|
||||
case NALUTypeSubsetSPS:
|
||||
return "SubsetSPS"
|
||||
case NALUTypeLayerWithoutPartition:
|
||||
return "LayerWithoutPartition"
|
||||
case NALUTypeCodedSliceExt:
|
||||
return "CodedSliceExt"
|
||||
default:
|
||||
return "Forbidden"
|
||||
return fmt.Sprintf("NALU/%v", uint8(v))
|
||||
}
|
||||
}
|
||||
|
||||
// @doc ISO_IEC_14496-10-AVC-2003.pdf at page 60, 7.4.1 NAL unit semantics
|
||||
type NALUHeader struct {
|
||||
// The 2-bits nal_ref_idc.
|
||||
NALRefIDC NALRefIDC
|
||||
// The 5-bits nal_unit_type.
|
||||
NALUType NALUType
|
||||
}
|
||||
|
||||
func NewNALUHeader() *NALUHeader {
|
||||
return &NALUHeader{}
|
||||
}
|
||||
|
||||
func (v *NALUHeader) String() string {
|
||||
return fmt.Sprintf("%v, NRI=%v", v.NALUType, v.NALRefIDC)
|
||||
}
|
||||
|
||||
func (v *NALUHeader) Size() int {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (v *NALUHeader) UnmarshalBinary(data []byte) error {
|
||||
if len(data) < 1 {
|
||||
return errors.New("empty NALU")
|
||||
}
|
||||
v.NALRefIDC = NALRefIDC(uint8(data[0]>>5) & 0x03)
|
||||
v.NALUType = NALUType(uint8(data[0]) & 0x1f)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *NALUHeader) MarshalBinary() ([]byte, error) {
|
||||
return []byte{
|
||||
byte(v.NALRefIDC)<<5 | byte(v.NALUType),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// @doc ISO_IEC_14496-10-AVC-2003.pdf at page 60, 7.4.1 NAL unit semantics
|
||||
type NALU struct {
|
||||
*NALUHeader
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func NewNALU() *NALU {
|
||||
return &NALU{NALUHeader: NewNALUHeader()}
|
||||
}
|
||||
|
||||
func (v *NALU) String() string {
|
||||
return fmt.Sprintf("%v, size=%vB", v.NALUHeader, len(v.Data))
|
||||
}
|
||||
|
||||
func (v *NALU) Size() int {
|
||||
return 1 + len(v.Data)
|
||||
}
|
||||
|
||||
func (v *NALU) UnmarshalBinary(data []byte) error {
|
||||
if err := v.NALUHeader.UnmarshalBinary(data); err != nil {
|
||||
return errors.WithMessage(err, "unmarshal")
|
||||
}
|
||||
|
||||
v.Data = data[1:]
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *NALU) MarshalBinary() ([]byte, error) {
|
||||
b, err := v.NALUHeader.MarshalBinary()
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(err, "marshal")
|
||||
}
|
||||
|
||||
if len(v.Data) == 0 {
|
||||
return b, nil
|
||||
}
|
||||
return append(b, v.Data...), nil
|
||||
}
|
||||
|
||||
// @doc Annex A Profiles and levels, ISO_IEC_14496-10-AVC-2003.pdf, page 205.
|
||||
// @note that it's uint8 in IBMF, but extended in other specs, so we use uint16.
|
||||
type AVCProfile uint16
|
||||
|
||||
const (
|
||||
// @see ffmpeg, libavcodec/avcodec.h:2713
|
||||
AVCProfileBaseline AVCProfile = 66
|
||||
AVCProfileConstrainedBaseline AVCProfile = 578
|
||||
AVCProfileMain AVCProfile = 77
|
||||
AVCProfileExtended AVCProfile = 88
|
||||
AVCProfileHigh AVCProfile = 100
|
||||
AVCProfileHigh10 AVCProfile = 110
|
||||
AVCProfileHigh10Intra AVCProfile = 2158
|
||||
AVCProfileHigh422 AVCProfile = 122
|
||||
AVCProfileHigh422Intra AVCProfile = 2170
|
||||
AVCProfileHigh444 AVCProfile = 144
|
||||
AVCProfileHigh444Predictive AVCProfile = 244
|
||||
AVCProfileHigh444Intra AVCProfile = 2192
|
||||
)
|
||||
|
||||
func (v AVCProfile) String() string {
|
||||
switch v {
|
||||
case AVCProfileBaseline:
|
||||
return "Baseline"
|
||||
case AVCProfileConstrainedBaseline:
|
||||
return "ConstrainedBaseline"
|
||||
case AVCProfileMain:
|
||||
return "Main"
|
||||
case AVCProfileExtended:
|
||||
return "Extended"
|
||||
case AVCProfileHigh:
|
||||
return "High"
|
||||
case AVCProfileHigh10:
|
||||
return "High10"
|
||||
case AVCProfileHigh10Intra:
|
||||
return "High10Intra"
|
||||
case AVCProfileHigh422:
|
||||
return "High422"
|
||||
case AVCProfileHigh422Intra:
|
||||
return "High422Intra"
|
||||
case AVCProfileHigh444:
|
||||
return "High444"
|
||||
case AVCProfileHigh444Predictive:
|
||||
return "High444Predictive"
|
||||
case AVCProfileHigh444Intra:
|
||||
return "High444Intra"
|
||||
default:
|
||||
return "Forbidden"
|
||||
}
|
||||
}
|
||||
|
||||
// @doc Annex A Profiles and levels, ISO_IEC_14496-10-AVC-2003.pdf, page 207.
|
||||
type AVCLevel uint8
|
||||
|
||||
const (
|
||||
AVCLevel_1 = 10
|
||||
AVCLevel_11 = 11
|
||||
AVCLevel_12 = 12
|
||||
AVCLevel_13 = 13
|
||||
AVCLevel_2 = 20
|
||||
AVCLevel_21 = 21
|
||||
AVCLevel_22 = 22
|
||||
AVCLevel_3 = 30
|
||||
AVCLevel_31 = 31
|
||||
AVCLevel_32 = 32
|
||||
AVCLevel_4 = 40
|
||||
AVCLevel_41 = 41
|
||||
AVCLevel_5 = 50
|
||||
AVCLevel_51 = 51
|
||||
)
|
||||
|
||||
func (v AVCLevel) String() string {
|
||||
switch v {
|
||||
case AVCLevel_1:
|
||||
return "Level_1"
|
||||
case AVCLevel_11:
|
||||
return "Level_11"
|
||||
case AVCLevel_12:
|
||||
return "Level_12"
|
||||
case AVCLevel_13:
|
||||
return "Level_13"
|
||||
case AVCLevel_2:
|
||||
return "Level_2"
|
||||
case AVCLevel_21:
|
||||
return "Level_21"
|
||||
case AVCLevel_22:
|
||||
return "Level_22"
|
||||
case AVCLevel_3:
|
||||
return "Level_3"
|
||||
case AVCLevel_31:
|
||||
return "Level_31"
|
||||
case AVCLevel_32:
|
||||
return "Level_32"
|
||||
case AVCLevel_4:
|
||||
return "Level_4"
|
||||
case AVCLevel_41:
|
||||
return "Level_41"
|
||||
case AVCLevel_5:
|
||||
return "Level_5"
|
||||
case AVCLevel_51:
|
||||
return "Level_51"
|
||||
default:
|
||||
return "Forbidden"
|
||||
}
|
||||
}
|
||||
|
||||
// @doc ISO_IEC_14496-15-AVC-format-2012.pdf at page 16, 5.2.4.1.1 Syntax
|
||||
type AVCDecoderConfigurationRecord struct {
|
||||
// It contains the profile code as defined in ISO/IEC 14496-10.
|
||||
configurationVersion uint8
|
||||
// It is a byte defined exactly the same as the byte which occurs between the
|
||||
// profile_IDC and level_IDC in a sequence parameter set (SPS), as defined in
|
||||
// ISO/IEC 14496-10.
|
||||
// @remark It's 8 bits.
|
||||
AVCProfileIndication AVCProfile
|
||||
// It contains the level code as defined in ISO/IEC 14496-10.
|
||||
profileCompatibility uint8
|
||||
// It indicates the length in bytes of the NALUnitLength field in an AVC video sample
|
||||
// or AVC parameter set sample of the associated stream minus one.
|
||||
AVCLevelIndication AVCLevel
|
||||
// It indicates the length in bytes of the NALUnitLength field in an AVC video sample
|
||||
// or AVC parameter set sample of the associated stream minus one.
|
||||
LengthSizeMinusOne uint8
|
||||
// It contains a SPS NAL unit, as specified in ISO/IEC 14496-10. SPSs shall occur in
|
||||
// order of ascending parameter set identifier with gaps being allowed.
|
||||
SequenceParameterSetNALUnits []*NALU
|
||||
// It contains a PPS NAL unit, as specified in ISO/IEC 14496-10. PPSs shall occur in
|
||||
// order of ascending parameter set identifier with gaps being allowed.
|
||||
PictureParameterSetNALUnits []*NALU
|
||||
// @remark We ignore the sequenceParameterSetExtNALUnit.
|
||||
}
|
||||
|
||||
func NewAVCDecoderConfigurationRecord() *AVCDecoderConfigurationRecord {
|
||||
v := &AVCDecoderConfigurationRecord{}
|
||||
v.configurationVersion = 0x01
|
||||
return v
|
||||
}
|
||||
|
||||
func (v *AVCDecoderConfigurationRecord) MarshalBinary() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteByte(byte(v.configurationVersion))
|
||||
buf.WriteByte(byte(v.AVCProfileIndication))
|
||||
buf.WriteByte(byte(v.profileCompatibility))
|
||||
buf.WriteByte(byte(v.AVCLevelIndication))
|
||||
buf.WriteByte(byte(v.LengthSizeMinusOne))
|
||||
|
||||
// numOfSequenceParameterSets
|
||||
buf.WriteByte(byte(len(v.SequenceParameterSetNALUnits)))
|
||||
for _, sps := range v.SequenceParameterSetNALUnits {
|
||||
b, err := sps.MarshalBinary()
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(err, "sps")
|
||||
}
|
||||
|
||||
sequenceParameterSetLength := uint16(len(b))
|
||||
buf.WriteByte(byte(sequenceParameterSetLength >> 8))
|
||||
buf.WriteByte(byte(sequenceParameterSetLength))
|
||||
buf.Write(b)
|
||||
}
|
||||
|
||||
// numOfPictureParameterSets
|
||||
buf.WriteByte(byte(len(v.PictureParameterSetNALUnits)))
|
||||
for _, pps := range v.PictureParameterSetNALUnits {
|
||||
b, err := pps.MarshalBinary()
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(err, "pps")
|
||||
}
|
||||
|
||||
pictureParameterSetLength := uint16(len(b))
|
||||
buf.WriteByte(byte(pictureParameterSetLength >> 8))
|
||||
buf.WriteByte(byte(pictureParameterSetLength))
|
||||
buf.Write(b)
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func (v *AVCDecoderConfigurationRecord) UnmarshalBinary(data []byte) error {
|
||||
b := data
|
||||
if len(b) < 6 {
|
||||
return errors.Errorf("requires 6+ only %v bytes", len(b))
|
||||
}
|
||||
|
||||
v.configurationVersion = uint8(b[0])
|
||||
v.AVCProfileIndication = AVCProfile(uint8(b[1]))
|
||||
v.profileCompatibility = uint8(b[2])
|
||||
v.AVCLevelIndication = AVCLevel(uint8(b[3]))
|
||||
v.LengthSizeMinusOne = uint8(b[4]) & 0x03
|
||||
b = b[5:]
|
||||
|
||||
numOfSequenceParameterSets := uint8(b[0]) & 0x1f
|
||||
b = b[1:]
|
||||
for i := 0; i < int(numOfSequenceParameterSets); i++ {
|
||||
if len(b) < 2 {
|
||||
return errors.Errorf("requires 2+ only %v bytes", len(b))
|
||||
}
|
||||
sequenceParameterSetLength := int(uint16(b[0])<<8 | uint16(b[1]))
|
||||
b = b[2:]
|
||||
|
||||
if len(b) < sequenceParameterSetLength {
|
||||
return errors.Errorf("requires %v only %v bytes", sequenceParameterSetLength, len(b))
|
||||
}
|
||||
sps := NewNALU()
|
||||
if err := sps.UnmarshalBinary(b[:sequenceParameterSetLength]); err != nil {
|
||||
return errors.WithMessage(err, "unmarshal")
|
||||
}
|
||||
b = b[sequenceParameterSetLength:]
|
||||
|
||||
v.SequenceParameterSetNALUnits = append(v.SequenceParameterSetNALUnits, sps)
|
||||
}
|
||||
|
||||
if len(b) < 1 {
|
||||
return errors.New("no PPS length")
|
||||
}
|
||||
numOfPictureParameterSets := uint8(b[0])
|
||||
b = b[1:]
|
||||
for i := 0; i < int(numOfPictureParameterSets); i++ {
|
||||
if len(b) < 2 {
|
||||
return errors.Errorf("requiers 2+ only %v bytes", len(b))
|
||||
}
|
||||
|
||||
pictureParameterSetLength := int(uint16(b[0])<<8 | uint16(b[1]))
|
||||
b = b[2:]
|
||||
|
||||
if len(b) < pictureParameterSetLength {
|
||||
return errors.Errorf("requires %v only %v bytes", pictureParameterSetLength, len(b))
|
||||
}
|
||||
pps := NewNALU()
|
||||
if err := pps.UnmarshalBinary(b[:pictureParameterSetLength]); err != nil {
|
||||
return errors.WithMessage(err, "unmarshal")
|
||||
}
|
||||
b = b[pictureParameterSetLength:]
|
||||
|
||||
v.PictureParameterSetNALUnits = append(v.PictureParameterSetNALUnits, pps)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// @doc ISO_IEC_14496-15-AVC-format-2012.pdf at page 20, 5.3.4.2 Sample format
|
||||
type AVCSample struct {
|
||||
lengthSizeMinusOne uint8
|
||||
NALUs []*NALU
|
||||
}
|
||||
|
||||
func NewAVCSample(lengthSizeMinusOne uint8) *AVCSample {
|
||||
return &AVCSample{lengthSizeMinusOne: lengthSizeMinusOne}
|
||||
}
|
||||
|
||||
func (v *AVCSample) MarshalBinary() ([]byte, error) {
|
||||
sizeOfNALU := int(v.lengthSizeMinusOne) + 1
|
||||
|
||||
var buf bytes.Buffer
|
||||
for _, nalu := range v.NALUs {
|
||||
b, err := nalu.MarshalBinary()
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(err, "write")
|
||||
}
|
||||
|
||||
length := uint64(len(b))
|
||||
for i := 0; i < sizeOfNALU; i++ {
|
||||
buf.WriteByte(byte(length >> uint8(8*(sizeOfNALU-1-i))))
|
||||
}
|
||||
buf.Write(b)
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func (v *AVCSample) UnmarshalBinary(data []byte) error {
|
||||
sizeOfNALU := int(v.lengthSizeMinusOne) + 1
|
||||
for b := data; len(b) > 0; {
|
||||
if len(b) < sizeOfNALU {
|
||||
return errors.Errorf("requires %v+ only %v bytes", sizeOfNALU, len(b))
|
||||
}
|
||||
|
||||
var length uint64
|
||||
for i := 0; i < sizeOfNALU; i++ {
|
||||
length |= uint64(b[i]) << uint8(8*(sizeOfNALU-1-i))
|
||||
}
|
||||
b = b[sizeOfNALU:]
|
||||
|
||||
if len(b) < int(length) {
|
||||
return errors.Errorf("requires %v only %v bytes", length, len(b))
|
||||
}
|
||||
|
||||
nalu := NewNALU()
|
||||
if err := nalu.UnmarshalBinary(b[:length]); err != nil {
|
||||
return errors.WithMessage(err, "unmarshal")
|
||||
}
|
||||
b = b[length:]
|
||||
|
||||
v.NALUs = append(v.NALUs, nalu)
|
||||
}
|
||||
return nil
|
||||
}
|
1756
trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/rtmp/rtmp.go
generated
vendored
Normal file
1756
trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/rtmp/rtmp.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue