This commit is contained in:
Ingo Oppermann
2022-07-28 20:27:27 +02:00
parent f8ac5e22e7
commit 542653d3e2
34 changed files with 730 additions and 702 deletions

2
go.mod
View File

@@ -6,7 +6,7 @@ require (
github.com/99designs/gqlgen v0.17.12
github.com/atrox/haikunatorgo/v2 v2.0.1
github.com/datarhei/gosrt v0.1.2
github.com/datarhei/joy4 v0.0.0-20210125162555-2102a8289cce
github.com/datarhei/joy4 v0.0.0-20220728180719-f752080f4a36
github.com/go-playground/validator/v10 v10.11.0
github.com/golang-jwt/jwt/v4 v4.4.2
github.com/google/uuid v1.3.0

4
go.sum
View File

@@ -76,8 +76,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/datarhei/gosrt v0.1.2 h1:rGOP2Xkbi52z4tLzBwCBw2TKt7BrfTO2LmEVY+yWf1M=
github.com/datarhei/gosrt v0.1.2/go.mod h1:IftDbZGIIC9OvQO5on5ZpU0iB/JX/PFOqGXORbwHYQM=
github.com/datarhei/joy4 v0.0.0-20210125162555-2102a8289cce h1:bg/OE9GfGK6d/XbqiMq8YaGQzw1Ul3Y3qiGMzU1G4HQ=
github.com/datarhei/joy4 v0.0.0-20210125162555-2102a8289cce/go.mod h1:Jcw/6jZDQQmPx8A7INEkXmuEF7E9jjBbSTfVSLwmiQw=
github.com/datarhei/joy4 v0.0.0-20220728180719-f752080f4a36 h1:ppjcv7wazy4d7vANREERXkSAUnhV/nfT2a+13u4ZijQ=
github.com/datarhei/joy4 v0.0.0-20220728180719-f752080f4a36/go.mod h1:Jcw/6jZDQQmPx8A7INEkXmuEF7E9jjBbSTfVSLwmiQw=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=

View File

@@ -1,4 +1,3 @@
// Package av defines basic interfaces and data structures of container demux/mux and audio encode/decode.
package av
@@ -196,7 +195,7 @@ type PacketWriter interface {
}
type PacketReader interface {
ReadPacket() (Packet,error)
ReadPacket() (Packet, error)
}
// Muxer describes the steps of writing compressed audio/video packets into container formats like MP4/FLV/MPEG-TS.
@@ -294,12 +293,12 @@ type AudioEncoder interface {
CodecData() (AudioCodecData, error) // encoder's codec data can put into container
Encode(AudioFrame) ([][]byte, error) // encode raw audio frame into compressed pakcet(s)
Close() // close encoder, free cgo contexts
SetSampleRate(int) (error) // set encoder sample rate
SetChannelLayout(ChannelLayout) (error) // set encoder channel layout
SetSampleFormat(SampleFormat) (error) // set encoder sample format
SetBitrate(int) (error) // set encoder bitrate
SetOption(string,interface{}) (error) // encoder setopt, in ffmpeg is av_opt_set_dict()
GetOption(string,interface{}) (error) // encoder getopt
SetSampleRate(int) error // set encoder sample rate
SetChannelLayout(ChannelLayout) error // set encoder channel layout
SetSampleFormat(SampleFormat) error // set encoder sample format
SetBitrate(int) error // set encoder bitrate
SetOption(string, interface{}) error // encoder setopt, in ffmpeg is av_opt_set_dict()
GetOption(string, interface{}) error // encoder getopt
}
// AudioDecoder can decode compressed audio packets into raw audio frame.
@@ -313,4 +312,3 @@ type AudioDecoder interface {
type AudioResampler interface {
Resample(AudioFrame) (AudioFrame, error) // convert raw audio frames
}

View File

@@ -1,14 +1,15 @@
package avutil
import (
"io"
"strings"
"fmt"
"bytes"
"github.com/datarhei/joy4/av"
"fmt"
"io"
"net/url"
"os"
"path"
"strings"
"github.com/datarhei/joy4/av"
)
type HandlerDemuxer struct {
@@ -55,16 +56,16 @@ func (self *HandlerMuxer) Close() (err error) {
type RegisterHandler struct {
Ext string
ReaderDemuxer func(io.Reader)av.Demuxer
WriterMuxer func(io.Writer)av.Muxer
UrlMuxer func(string)(bool,av.MuxCloser,error)
UrlDemuxer func(string)(bool,av.DemuxCloser,error)
UrlReader func(string)(bool,io.ReadCloser,error)
Probe func([]byte)bool
AudioEncoder func(av.CodecType)(av.AudioEncoder,error)
AudioDecoder func(av.AudioCodecData)(av.AudioDecoder,error)
ServerDemuxer func(string)(bool,av.DemuxCloser,error)
ServerMuxer func(string)(bool,av.MuxCloser,error)
ReaderDemuxer func(io.Reader) av.Demuxer
WriterMuxer func(io.Writer) av.Muxer
UrlMuxer func(string) (bool, av.MuxCloser, error)
UrlDemuxer func(string) (bool, av.DemuxCloser, error)
UrlReader func(string) (bool, io.ReadCloser, error)
Probe func([]byte) bool
AudioEncoder func(av.CodecType) (av.AudioEncoder, error)
AudioDecoder func(av.AudioCodecData) (av.AudioDecoder, error)
ServerDemuxer func(string) (bool, av.DemuxCloser, error)
ServerMuxer func(string) (bool, av.MuxCloser, error)
CodecTypes []av.CodecType
}
@@ -108,7 +109,7 @@ func (self *Handlers) NewAudioEncoder(typ av.CodecType) (enc av.AudioEncoder, er
}
}
}
err = fmt.Errorf("avutil: encoder", typ, "not found")
err = fmt.Errorf("avutil: encoder %s not found", typ)
return
}
@@ -120,7 +121,7 @@ func (self *Handlers) NewAudioDecoder(codec av.AudioCodecData) (dec av.AudioDeco
}
}
}
err = fmt.Errorf("avutil: decoder", codec.Type(), "not found")
err = fmt.Errorf("avutil: decoder %s not found", codec.Type())
return
}

View File

@@ -1,10 +1,9 @@
// Package pktque provides packet Filter interface and structures used by other components.
package pktque
import (
"time"
"github.com/datarhei/joy4/av"
"time"
)
type Filter interface {
@@ -121,7 +120,7 @@ func (self *AVSync) ModifyPacket(pkt *av.Packet, streams []av.CodecData, videoid
if self.time == nil {
self.time = make([]time.Duration, len(streams))
if self.MaxTimeDiff == 0 {
self.MaxTimeDiff = time.Millisecond*500
self.MaxTimeDiff = time.Millisecond * 500
}
}
@@ -188,4 +187,3 @@ func (self *Walltime) ModifyPacket(pkt *av.Packet, streams []av.CodecData, video
}
return
}

View File

@@ -26,7 +26,7 @@ type Timeline struct {
func (self *Timeline) Push(tm time.Duration, dur time.Duration) {
if len(self.segs) > 0 {
tail := self.segs[len(self.segs)-1]
diff := tm-(tail.tm+tail.dur)
diff := tm - (tail.tm + tail.dur)
if diff < 0 {
tm -= diff
}
@@ -58,4 +58,3 @@ func (self *Timeline) Pop(dur time.Duration) (tm time.Duration) {
return
}

View File

@@ -2,11 +2,12 @@
package pubsub
import (
"github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/av/pktque"
"io"
"sync"
"time"
"github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/av/pktque"
)
// time
@@ -97,7 +98,6 @@ func (self *Queue) WritePacket(pkt av.Packet) (err error) {
break
}
}
//println("shrink", self.curgopcount, self.maxgopcount, self.buf.Head, self.buf.Tail, "count", self.buf.Count, "size", self.buf.Size)
self.cond.Broadcast()

View File

@@ -1,12 +1,12 @@
package aacparser
import (
"github.com/datarhei/joy4/utils/bits"
"github.com/datarhei/joy4/av"
"time"
"fmt"
"bytes"
"fmt"
"github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/utils/bits"
"io"
"time"
)
// copied from libavcodec/mpeg4audio.h
@@ -83,12 +83,12 @@ These are the channel configurations:
var chanConfigTable = []av.ChannelLayout{
0,
av.CH_FRONT_CENTER,
av.CH_FRONT_LEFT|av.CH_FRONT_RIGHT,
av.CH_FRONT_CENTER|av.CH_FRONT_LEFT|av.CH_FRONT_RIGHT,
av.CH_FRONT_CENTER|av.CH_FRONT_LEFT|av.CH_FRONT_RIGHT|av.CH_BACK_CENTER,
av.CH_FRONT_CENTER|av.CH_FRONT_LEFT|av.CH_FRONT_RIGHT|av.CH_BACK_LEFT|av.CH_BACK_RIGHT,
av.CH_FRONT_CENTER|av.CH_FRONT_LEFT|av.CH_FRONT_RIGHT|av.CH_BACK_LEFT|av.CH_BACK_RIGHT|av.CH_LOW_FREQ,
av.CH_FRONT_CENTER|av.CH_FRONT_LEFT|av.CH_FRONT_RIGHT|av.CH_SIDE_LEFT|av.CH_SIDE_RIGHT|av.CH_BACK_LEFT|av.CH_BACK_RIGHT|av.CH_LOW_FREQ,
av.CH_FRONT_LEFT | av.CH_FRONT_RIGHT,
av.CH_FRONT_CENTER | av.CH_FRONT_LEFT | av.CH_FRONT_RIGHT,
av.CH_FRONT_CENTER | av.CH_FRONT_LEFT | av.CH_FRONT_RIGHT | av.CH_BACK_CENTER,
av.CH_FRONT_CENTER | av.CH_FRONT_LEFT | av.CH_FRONT_RIGHT | av.CH_BACK_LEFT | av.CH_BACK_RIGHT,
av.CH_FRONT_CENTER | av.CH_FRONT_LEFT | av.CH_FRONT_RIGHT | av.CH_BACK_LEFT | av.CH_BACK_RIGHT | av.CH_LOW_FREQ,
av.CH_FRONT_CENTER | av.CH_FRONT_LEFT | av.CH_FRONT_RIGHT | av.CH_SIDE_LEFT | av.CH_SIDE_RIGHT | av.CH_BACK_LEFT | av.CH_BACK_RIGHT | av.CH_LOW_FREQ,
}
func ParseADTSHeader(frame []byte) (config MPEG4AudioConfig, hdrlen int, framelen int, samples int, err error) {
@@ -308,4 +308,3 @@ func NewCodecDataFromMPEG4AudioConfigBytes(config []byte) (self CodecData, err e
}
return
}

View File

@@ -50,7 +50,7 @@ func (self SpeexCodecData) PacketDuration(data []byte) (time.Duration, error) {
// libavcodec/libspeexdec.c
// samples = samplerate/50
// duration = 0.02s
return time.Millisecond*20, nil
return time.Millisecond * 20, nil
}
func NewSpeexCodecData(sr int, cl av.ChannelLayout) SpeexCodecData {
@@ -61,4 +61,3 @@ func NewSpeexCodecData(sr int, cl av.ChannelLayout) SpeexCodecData {
codec.ChannelLayout_ = cl
return codec
}

View File

@@ -26,4 +26,3 @@ func (self CodecData) ChannelLayout() av.ChannelLayout {
func (self CodecData) SampleRate() int {
return self.SampleRate_
}

View File

@@ -1,12 +1,11 @@
package h264parser
import (
"bytes"
"fmt"
"github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/utils/bits"
"github.com/datarhei/joy4/utils/bits/pio"
"fmt"
"bytes"
)
const (
@@ -199,8 +198,8 @@ Additionally, there is a new variable called NALULengthSizeMinusOne. This confus
An advantage to this format is the ability to configure the decoder at the start and jump into the middle of a stream. This is a common use case where the media is available on a random access medium such as a hard drive, and is therefore used in common container formats such as MP4 and MKV.
*/
var StartCodeBytes = []byte{0,0,1}
var AUDBytes = []byte{0,0,0,1,0x9,0xf0,0,0,0,1} // AUD
var StartCodeBytes = []byte{0, 0, 1}
var AUDBytes = []byte{0, 0, 0, 1, 0x9, 0xf0, 0, 0, 0, 1} // AUD
func CheckNALUsType(b []byte) (typ int) {
_, typ = SplitNALUs(b)
@@ -589,8 +588,8 @@ func (self *AVCDecoderConfRecord) Unmarshal(b []byte) (n int, err error) {
self.AVCProfileIndication = b[1]
self.ProfileCompatibility = b[2]
self.AVCLevelIndication = b[3]
self.LengthSizeMinusOne = b[4]&0x03
spscount := int(b[5]&0x1f)
self.LengthSizeMinusOne = b[4] & 0x03
spscount := int(b[5] & 0x1f)
n += 6
for i := 0; i < spscount; i++ {
@@ -638,10 +637,10 @@ func (self *AVCDecoderConfRecord) Unmarshal(b []byte) (n int, err error) {
func (self AVCDecoderConfRecord) Len() (n int) {
n = 7
for _, sps := range self.SPS {
n += 2+len(sps)
n += 2 + len(sps)
}
for _, pps := range self.PPS {
n += 2+len(pps)
n += 2 + len(pps)
}
return
}
@@ -651,8 +650,8 @@ func (self AVCDecoderConfRecord) Marshal(b []byte) (n int) {
b[1] = self.AVCProfileIndication
b[2] = self.ProfileCompatibility
b[3] = self.AVCLevelIndication
b[4] = self.LengthSizeMinusOne|0xfc
b[5] = uint8(len(self.SPS))|0xe0
b[4] = self.LengthSizeMinusOne | 0xfc
b[5] = uint8(len(self.SPS)) | 0xe0
n += 6
for _, sps := range self.SPS {
@@ -690,7 +689,7 @@ func (self SliceType) String() string {
}
const (
SLICE_P = iota+1
SLICE_P = iota + 1
SLICE_B
SLICE_I
)
@@ -702,9 +701,9 @@ func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, err error) {
return
}
nal_unit_type := packet[0]&0x1f
nal_unit_type := packet[0] & 0x1f
switch nal_unit_type {
case 1,2,5,19:
case 1, 2, 5, 19:
// slice_layer_without_partitioning_rbsp
// slice_data_partition_a_layer_rbsp
@@ -727,11 +726,11 @@ func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, err error) {
}
switch u {
case 0,3,5,8:
case 0, 3, 5, 8:
sliceType = SLICE_P
case 1,6:
case 1, 6:
sliceType = SLICE_B
case 2,4,7,9:
case 2, 4, 7, 9:
sliceType = SLICE_I
default:
err = fmt.Errorf("h264parser: slice_type=%d invalid", u)
@@ -740,4 +739,3 @@ func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, err error) {
return
}

View File

@@ -1,14 +1,13 @@
package aac
import (
"github.com/datarhei/joy4/av/avutil"
"github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/codec/aacparser"
"time"
"fmt"
"io"
"bufio"
"fmt"
"github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/av/avutil"
"github.com/datarhei/joy4/codec/aacparser"
"io"
"time"
)
type Muxer struct {

View File

@@ -3,7 +3,6 @@ package flv
import (
"bufio"
"fmt"
"github.com/datarhei/joy4/utils/bits/pio"
"github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/av/avutil"
"github.com/datarhei/joy4/codec"
@@ -11,6 +10,7 @@ import (
"github.com/datarhei/joy4/codec/fake"
"github.com/datarhei/joy4/codec/h264parser"
"github.com/datarhei/joy4/format/flv/flvio"
"github.com/datarhei/joy4/utils/bits/pio"
"io"
)

View File

@@ -1,11 +1,11 @@
package flvio
import (
"strings"
"math"
"fmt"
"time"
"github.com/datarhei/joy4/utils/bits/pio"
"math"
"strings"
"time"
)
type AMF0ParseError struct {
@@ -133,7 +133,7 @@ func LenAMF0Val(_val interface{}) (n int) {
case AMFECMAArray:
n += 5
for k, v := range val {
n += 2+len(k)
n += 2 + len(k)
n += LenAMF0Val(v)
}
n += 3
@@ -142,7 +142,7 @@ func LenAMF0Val(_val interface{}) (n int) {
n++
for k, v := range val {
if len(k) > 0 {
n += 2+len(k)
n += 2 + len(k)
n += LenAMF0Val(v)
}
}
@@ -155,7 +155,7 @@ func LenAMF0Val(_val interface{}) (n int) {
}
case time.Time:
n += 1+8+2
n += 1 + 8 + 2
case bool:
n += 2
@@ -253,7 +253,7 @@ func FillAMF0Val(b []byte, _val interface{}) (n int) {
b[n] = datemarker
n++
u := val.UnixNano()
f := float64(u/1000000)
f := float64(u / 1000000)
n += fillBEFloat64(b[n:], f)
pio.PutU16BE(b[n:], uint16(0))
n += 2
@@ -278,7 +278,6 @@ func FillAMF0Val(b []byte, _val interface{}) (n int) {
return
}
func ParseAMF0Val(b []byte) (val interface{}, n int, err error) {
return parseAMF0Val(b, 0)
}
@@ -320,7 +319,7 @@ func parseAMF0Val(b []byte, offset int) (val interface{}, n int, err error) {
err = amf0ParseErr("string.body", offset+n, err)
return
}
val = string(b[n:n+length])
val = string(b[n : n+length])
n += length
case objectmarker:
@@ -340,7 +339,7 @@ func parseAMF0Val(b []byte, offset int) (val interface{}, n int, err error) {
err = amf0ParseErr("object.key.body", offset+n, err)
return
}
okey := string(b[n:n+length])
okey := string(b[n : n+length])
n += length
var nval int
@@ -387,7 +386,7 @@ func parseAMF0Val(b []byte, offset int) (val interface{}, n int, err error) {
err = amf0ParseErr("array.key.body", offset+n, err)
return
}
okey := string(b[n:n+length])
okey := string(b[n : n+length])
n += length
var nval int
@@ -439,7 +438,7 @@ func parseAMF0Val(b []byte, offset int) (val interface{}, n int, err error) {
return
}
ts := parseBEFloat64(b[n:])
n += 8+2
n += 8 + 2
val = time.Unix(int64(ts/1000), (int64(ts)%1000)*1000000)
@@ -455,7 +454,7 @@ func parseAMF0Val(b []byte, offset int) (val interface{}, n int, err error) {
err = amf0ParseErr("longstring.body", offset+n, err)
return
}
val = string(b[n:n+length])
val = string(b[n : n+length])
n += length
default:
@@ -465,4 +464,3 @@ func parseAMF0Val(b []byte, offset int) (val interface{}, n int, err error) {
return
}

View File

@@ -2,8 +2,8 @@ package flvio
import (
"fmt"
"github.com/datarhei/joy4/utils/bits/pio"
"github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/utils/bits/pio"
"io"
"time"
)

View File

@@ -1,13 +1,13 @@
package format
import (
"github.com/datarhei/joy4/av/avutil"
"github.com/datarhei/joy4/format/aac"
"github.com/datarhei/joy4/format/flv"
"github.com/datarhei/joy4/format/mp4"
"github.com/datarhei/joy4/format/ts"
"github.com/datarhei/joy4/format/rtmp"
"github.com/datarhei/joy4/format/rtsp"
"github.com/datarhei/joy4/format/flv"
"github.com/datarhei/joy4/format/aac"
"github.com/datarhei/joy4/av/avutil"
"github.com/datarhei/joy4/format/ts"
)
func RegisterAll() {
@@ -18,4 +18,3 @@ func RegisterAll() {
avutil.DefaultHandlers.Add(flv.Handler)
avutil.DefaultHandlers.Add(aac.Handler)
}

View File

@@ -1,9 +1,9 @@
package mp4
import (
"io"
"github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/av/avutil"
"io"
)
var CodecTypes = []av.CodecType{av.H264, av.AAC}
@@ -13,7 +13,7 @@ func Handler(h *avutil.RegisterHandler) {
h.Probe = func(b []byte) bool {
switch string(b[4:8]) {
case "moov","ftyp","free","mdat","moof":
case "moov", "ftyp", "free", "mdat", "moof":
return true
}
return false
@@ -29,4 +29,3 @@ func Handler(h *avutil.RegisterHandler) {
h.CodecTypes = CodecTypes
}

View File

@@ -213,7 +213,7 @@ type Movie struct {
func (self Movie) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(MOOV))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -288,7 +288,7 @@ func (self *Movie) Unmarshal(b []byte, offset int) (n int, err error) {
}
default:
{
atom := &Dummy{Tag_: tag, Data: b[n:n+size]}
atom := &Dummy{Tag_: tag, Data: b[n : n+size]}
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err)
return
@@ -336,7 +336,7 @@ type MovieHeader struct {
func (self MovieHeader) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(MVHD))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -389,7 +389,7 @@ func (self MovieHeader) Len() (n int) {
n += 4
n += 2
n += 10
n += 4*len(self.Matrix[:])
n += 4 * len(self.Matrix[:])
n += 4
n += 4
n += 4
@@ -516,7 +516,7 @@ type Track struct {
func (self Track) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(TRAK))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -576,7 +576,7 @@ func (self *Track) Unmarshal(b []byte, offset int) (n int, err error) {
}
default:
{
atom := &Dummy{Tag_: tag, Data: b[n:n+size]}
atom := &Dummy{Tag_: tag, Data: b[n : n+size]}
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err)
return
@@ -617,7 +617,7 @@ type TrackHeader struct {
func (self TrackHeader) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(TKHD))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -667,7 +667,7 @@ func (self TrackHeader) Len() (n int) {
n += 2
n += 2
n += 2
n += 4*len(self.Matrix[:])
n += 4 * len(self.Matrix[:])
n += 4
n += 4
return
@@ -769,7 +769,7 @@ type HandlerRefer struct {
func (self HandlerRefer) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(HDLR))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -840,7 +840,7 @@ type Media struct {
func (self Media) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(MDIA))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -915,7 +915,7 @@ func (self *Media) Unmarshal(b []byte, offset int) (n int, err error) {
}
default:
{
atom := &Dummy{Tag_: tag, Data: b[n:n+size]}
atom := &Dummy{Tag_: tag, Data: b[n : n+size]}
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err)
return
@@ -955,7 +955,7 @@ type MediaHeader struct {
func (self MediaHeader) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(MDHD))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -1058,7 +1058,7 @@ type MediaInfo struct {
func (self MediaInfo) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(MINF))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -1148,7 +1148,7 @@ func (self *MediaInfo) Unmarshal(b []byte, offset int) (n int, err error) {
}
default:
{
atom := &Dummy{Tag_: tag, Data: b[n:n+size]}
atom := &Dummy{Tag_: tag, Data: b[n : n+size]}
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err)
return
@@ -1185,7 +1185,7 @@ type DataInfo struct {
func (self DataInfo) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(DINF))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -1230,7 +1230,7 @@ func (self *DataInfo) Unmarshal(b []byte, offset int) (n int, err error) {
}
default:
{
atom := &Dummy{Tag_: tag, Data: b[n:n+size]}
atom := &Dummy{Tag_: tag, Data: b[n : n+size]}
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err)
return
@@ -1259,7 +1259,7 @@ type DataRefer struct {
func (self DataRefer) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(DREF))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -1313,7 +1313,7 @@ func (self *DataRefer) Unmarshal(b []byte, offset int) (n int, err error) {
return
}
switch tag {
case URL :
case URL:
{
atom := &DataReferUrl{}
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
@@ -1341,8 +1341,8 @@ type DataReferUrl struct {
}
func (self DataReferUrl) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(URL ))
n += self.marshal(b[8:])+8
pio.PutU32BE(b[4:], uint32(URL))
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -1389,7 +1389,7 @@ type SoundMediaInfo struct {
func (self SoundMediaInfo) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(SMHD))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -1449,7 +1449,7 @@ type VideoMediaInfo struct {
func (self VideoMediaInfo) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(VMHD))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -1471,7 +1471,7 @@ func (self VideoMediaInfo) Len() (n int) {
n += 1
n += 3
n += 2
n += 2*len(self.Opcolor[:])
n += 2 * len(self.Opcolor[:])
return
}
func (self *VideoMediaInfo) Unmarshal(b []byte, offset int) (n int, err error) {
@@ -1522,7 +1522,7 @@ type SampleTable struct {
func (self SampleTable) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(STBL))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -1689,7 +1689,7 @@ type SampleDesc struct {
func (self SampleDesc) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(STSD))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -1773,7 +1773,7 @@ func (self *SampleDesc) Unmarshal(b []byte, offset int) (n int, err error) {
}
default:
{
atom := &Dummy{Tag_: tag, Data: b[n:n+size]}
atom := &Dummy{Tag_: tag, Data: b[n : n+size]}
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err)
return
@@ -1812,7 +1812,7 @@ type MP4ADesc struct {
func (self MP4ADesc) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(MP4A))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -1935,7 +1935,7 @@ func (self *MP4ADesc) Unmarshal(b []byte, offset int) (n int, err error) {
}
default:
{
atom := &Dummy{Tag_: tag, Data: b[n:n+size]}
atom := &Dummy{Tag_: tag, Data: b[n : n+size]}
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err)
return
@@ -1977,7 +1977,7 @@ type AVC1Desc struct {
func (self AVC1Desc) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(AVC1))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -2154,7 +2154,7 @@ func (self *AVC1Desc) Unmarshal(b []byte, offset int) (n int, err error) {
}
default:
{
atom := &Dummy{Tag_: tag, Data: b[n:n+size]}
atom := &Dummy{Tag_: tag, Data: b[n : n+size]}
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err)
return
@@ -2181,7 +2181,7 @@ type AVC1Conf struct {
func (self AVC1Conf) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(AVCC))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -2215,7 +2215,7 @@ type TimeToSample struct {
func (self TimeToSample) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(STTS))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -2237,7 +2237,7 @@ func (self TimeToSample) Len() (n int) {
n += 1
n += 3
n += 4
n += LenTimeToSampleEntry*len(self.Entries)
n += LenTimeToSampleEntry * len(self.Entries)
return
}
func (self *TimeToSample) Unmarshal(b []byte, offset int) (n int, err error) {
@@ -2299,7 +2299,7 @@ type SampleToChunk struct {
func (self SampleToChunk) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(STSC))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -2321,7 +2321,7 @@ func (self SampleToChunk) Len() (n int) {
n += 1
n += 3
n += 4
n += LenSampleToChunkEntry*len(self.Entries)
n += LenSampleToChunkEntry * len(self.Entries)
return
}
func (self *SampleToChunk) Unmarshal(b []byte, offset int) (n int, err error) {
@@ -2386,7 +2386,7 @@ type CompositionOffset struct {
func (self CompositionOffset) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(CTTS))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -2408,7 +2408,7 @@ func (self CompositionOffset) Len() (n int) {
n += 1
n += 3
n += 4
n += LenCompositionOffsetEntry*len(self.Entries)
n += LenCompositionOffsetEntry * len(self.Entries)
return
}
func (self *CompositionOffset) Unmarshal(b []byte, offset int) (n int, err error) {
@@ -2470,7 +2470,7 @@ type SyncSample struct {
func (self SyncSample) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(STSS))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -2492,7 +2492,7 @@ func (self SyncSample) Len() (n int) {
n += 1
n += 3
n += 4
n += 4*len(self.Entries)
n += 4 * len(self.Entries)
return
}
func (self *SyncSample) Unmarshal(b []byte, offset int) (n int, err error) {
@@ -2537,7 +2537,7 @@ type ChunkOffset struct {
func (self ChunkOffset) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(STCO))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -2559,7 +2559,7 @@ func (self ChunkOffset) Len() (n int) {
n += 1
n += 3
n += 4
n += 4*len(self.Entries)
n += 4 * len(self.Entries)
return
}
func (self *ChunkOffset) Unmarshal(b []byte, offset int) (n int, err error) {
@@ -2604,7 +2604,7 @@ type MovieFrag struct {
func (self MovieFrag) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(MOOF))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -2664,7 +2664,7 @@ func (self *MovieFrag) Unmarshal(b []byte, offset int) (n int, err error) {
}
default:
{
atom := &Dummy{Tag_: tag, Data: b[n:n+size]}
atom := &Dummy{Tag_: tag, Data: b[n : n+size]}
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err)
return
@@ -2696,7 +2696,7 @@ type MovieFragHeader struct {
func (self MovieFragHeader) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(MFHD))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -2753,7 +2753,7 @@ type TrackFrag struct {
func (self TrackFrag) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(TRAF))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -2828,7 +2828,7 @@ func (self *TrackFrag) Unmarshal(b []byte, offset int) (n int, err error) {
}
default:
{
atom := &Dummy{Tag_: tag, Data: b[n:n+size]}
atom := &Dummy{Tag_: tag, Data: b[n : n+size]}
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err)
return
@@ -2862,7 +2862,7 @@ type MovieExtend struct {
func (self MovieExtend) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(MVEX))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -2907,7 +2907,7 @@ func (self *MovieExtend) Unmarshal(b []byte, offset int) (n int, err error) {
}
default:
{
atom := &Dummy{Tag_: tag, Data: b[n:n+size]}
atom := &Dummy{Tag_: tag, Data: b[n : n+size]}
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err)
return
@@ -2940,7 +2940,7 @@ type TrackExtend struct {
func (self TrackExtend) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(TREX))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -3033,7 +3033,7 @@ type SampleSize struct {
func (self SampleSize) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(STSZ))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -3064,7 +3064,7 @@ func (self SampleSize) Len() (n int) {
return
}
n += 4
n += 4*len(self.Entries)
n += 4 * len(self.Entries)
return
}
func (self *SampleSize) Unmarshal(b []byte, offset int) (n int, err error) {
@@ -3120,7 +3120,7 @@ type TrackFragRun struct {
func (self TrackFragRun) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(TRUN))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -3315,7 +3315,7 @@ type TrackFragHeader struct {
func (self TrackFragHeader) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(TFHD))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}
@@ -3467,7 +3467,7 @@ type TrackFragDecodeTime struct {
func (self TrackFragDecodeTime) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(TFDT))
n += self.marshal(b[8:])+8
n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n))
return
}

View File

@@ -1,14 +1,13 @@
package mp4io
import (
"github.com/datarhei/joy4/utils/bits/pio"
"os"
"io"
"fmt"
"time"
"github.com/datarhei/joy4/utils/bits/pio"
"io"
"math"
"os"
"strings"
"time"
)
type ParseError struct {
@@ -22,7 +21,7 @@ func (self *ParseError) Error() string {
for p := self; p != nil; p = p.prev {
s = append(s, fmt.Sprintf("%s:%d", p.Debug, p.Offset))
}
return "mp4io: parse error: "+strings.Join(s, ",")
return "mp4io: parse error: " + strings.Join(s, ",")
}
func parseErr(debug string, offset int, prev error) (err error) {
@@ -33,37 +32,37 @@ func parseErr(debug string, offset int, prev error) (err error) {
func GetTime32(b []byte) (t time.Time) {
sec := pio.U32BE(b)
t = time.Date(1904, time.January, 1, 0, 0, 0, 0, time.UTC)
t = t.Add(time.Second*time.Duration(sec))
t = t.Add(time.Second * time.Duration(sec))
return
}
func PutTime32(b []byte, t time.Time) {
dur := t.Sub(time.Date(1904, time.January, 1, 0, 0, 0, 0, time.UTC))
sec := uint32(dur/time.Second)
sec := uint32(dur / time.Second)
pio.PutU32BE(b, sec)
}
func GetTime64(b []byte) (t time.Time) {
sec := pio.U64BE(b)
t = time.Date(1904, time.January, 1, 0, 0, 0, 0, time.UTC)
t = t.Add(time.Second*time.Duration(sec))
t = t.Add(time.Second * time.Duration(sec))
return
}
func PutTime64(b []byte, t time.Time) {
dur := t.Sub(time.Date(1904, time.January, 1, 0, 0, 0, 0, time.UTC))
sec := uint64(dur/time.Second)
sec := uint64(dur / time.Second)
pio.PutU64BE(b, sec)
}
func PutFixed16(b []byte, f float64) {
intpart, fracpart := math.Modf(f)
b[0] = uint8(intpart)
b[1] = uint8(fracpart*256.0)
b[1] = uint8(fracpart * 256.0)
}
func GetFixed16(b []byte) float64 {
return float64(b[0])+float64(b[1])/256.0
return float64(b[0]) + float64(b[1])/256.0
}
func PutFixed32(b []byte, f float64) {
@@ -73,7 +72,7 @@ func PutFixed32(b []byte, f float64) {
}
func GetFixed32(b []byte) float64 {
return float64(pio.U16BE(b[0:2]))+float64(pio.U16BE(b[2:4]))/65536.0
return float64(pio.U16BE(b[0:2])) + float64(pio.U16BE(b[2:4]))/65536.0
}
type Tag uint32
@@ -89,11 +88,11 @@ func (self Tag) String() string {
return string(b[:])
}
type Atom interface{
Pos() (int,int)
type Atom interface {
Pos() (int, int)
Tag() Tag
Marshal([]byte) int
Unmarshal([]byte, int) (int,error)
Unmarshal([]byte, int) (int, error)
Len() int
Children() []Atom
}
@@ -103,7 +102,7 @@ type AtomPos struct {
Size int
}
func (self AtomPos) Pos() (int,int) {
func (self AtomPos) Pos() (int, int) {
return self.Offset, self.Size
}
@@ -200,10 +199,10 @@ func (self ElemStreamDesc) Children() []Atom {
func (self ElemStreamDesc) fillLength(b []byte, length int) (n int) {
for i := 3; i > 0; i-- {
b[n] = uint8(length>>uint(7*i))&0x7f|0x80
b[n] = uint8(length>>uint(7*i))&0x7f | 0x80
n++
}
b[n] = uint8(length&0x7f)
b[n] = uint8(length & 0x7f)
n++
return
}
@@ -220,7 +219,7 @@ func (self ElemStreamDesc) fillDescHdr(b []byte, tag uint8, datalen int) (n int)
}
func (self ElemStreamDesc) lenESDescHdr() (n int) {
return self.lenDescHdr()+3
return self.lenDescHdr() + 3
}
func (self ElemStreamDesc) fillESDescHdr(b []byte, datalen int) (n int) {
@@ -233,7 +232,7 @@ func (self ElemStreamDesc) fillESDescHdr(b []byte, datalen int) (n int) {
}
func (self ElemStreamDesc) lenDecConfigDescHdr() (n int) {
return self.lenDescHdr()+2+3+4+4+self.lenDescHdr()
return self.lenDescHdr() + 2 + 3 + 4 + 4 + self.lenDescHdr()
}
func (self ElemStreamDesc) fillDecConfigDescHdr(b []byte, datalen int) (n int) {
@@ -256,7 +255,7 @@ func (self ElemStreamDesc) fillDecConfigDescHdr(b []byte, datalen int) (n int) {
}
func (self ElemStreamDesc) Len() (n int) {
return 8+4+self.lenESDescHdr()+self.lenDecConfigDescHdr()+len(self.DecConfig)+self.lenDescHdr()+1
return 8 + 4 + self.lenESDescHdr() + self.lenDecConfigDescHdr() + len(self.DecConfig) + self.lenDescHdr() + 1
}
// Version(4)
@@ -328,7 +327,7 @@ func (self *ElemStreamDesc) parseDesc(b []byte, offset int) (n int, err error) {
}
case MP4DecConfigDescrTag:
const size = 2+3+4+4
const size = 2 + 3 + 4 + 4
if len(b) < n+size {
err = parseErr("MP4DecSpecificDescrTag", offset+n, err)
return
@@ -353,7 +352,7 @@ func (self *ElemStreamDesc) parseLength(b []byte, offset int) (n int, length int
}
c := b[n]
n++
length = (length<<7)|(int(c)&0x7f)
length = (length << 7) | (int(c) & 0x7f)
if c&0x80 == 0 {
break
}
@@ -500,4 +499,3 @@ func (self *Track) GetElemStreamDesc() (esds *ElemStreamDesc) {
esds, _ = atom.(*ElemStreamDesc)
return
}

View File

@@ -1,15 +1,15 @@
package mp4
import (
"bufio"
"fmt"
"time"
"github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/codec/aacparser"
"github.com/datarhei/joy4/codec/h264parser"
"github.com/datarhei/joy4/format/mp4/mp4io"
"github.com/datarhei/joy4/utils/bits/pio"
"io"
"bufio"
"time"
)
type Muxer struct {
@@ -54,7 +54,7 @@ func (self *Muxer) newStream(codec av.CodecData) (err error) {
stream.trackAtom = &mp4io.Track{
Header: &mp4io.TrackHeader{
TrackId: int32(len(self.streams)+1),
TrackId: int32(len(self.streams) + 1),
Flags: 0x0003, // Track enabled | Track in movie
Duration: 0, // fill later
Matrix: [9]int32{0x10000, 0, 0, 0, 0x10000, 0, 0, 0, 0x40000000},
@@ -109,7 +109,7 @@ func (self *Stream) fillTrackAtom() (err error) {
Conf: &mp4io.AVC1Conf{Data: codec.AVCDecoderConfRecordBytes()},
}
self.trackAtom.Media.Handler = &mp4io.HandlerRefer{
SubType: [4]byte{'v','i','d','e'},
SubType: [4]byte{'v', 'i', 'd', 'e'},
Name: []byte("Video Media Handler"),
}
self.trackAtom.Media.Info.Video = &mp4io.VideoMediaInfo{
@@ -132,7 +132,7 @@ func (self *Stream) fillTrackAtom() (err error) {
self.trackAtom.Header.Volume = 1
self.trackAtom.Header.AlternateGroup = 1
self.trackAtom.Media.Handler = &mp4io.HandlerRefer{
SubType: [4]byte{'s','o','u','n'},
SubType: [4]byte{'s', 'o', 'u', 'n'},
Name: []byte("Sound Handler"),
}
self.trackAtom.Media.Info.Sound = &mp4io.SoundMediaInfo{}

View File

@@ -42,17 +42,17 @@ type Stream struct {
}
func timeToTs(tm time.Duration, timeScale int64) int64 {
return int64(tm*time.Duration(timeScale) / time.Second)
return int64(tm * time.Duration(timeScale) / time.Second)
}
func tsToTime(ts int64, timeScale int64) time.Duration {
return time.Duration(ts)*time.Second / time.Duration(timeScale)
return time.Duration(ts) * time.Second / time.Duration(timeScale)
}
func (self *Stream) timeToTs(tm time.Duration) int64 {
return int64(tm*time.Duration(self.timeScale) / time.Second)
return int64(tm * time.Duration(self.timeScale) / time.Second)
}
func (self *Stream) tsToTime(ts int64) time.Duration {
return time.Duration(ts)*time.Second / time.Duration(self.timeScale)
return time.Duration(ts) * time.Second / time.Duration(self.timeScale)
}

View File

@@ -10,16 +10,17 @@ import (
"encoding/hex"
"errors"
"fmt"
"github.com/datarhei/joy4/utils/bits/pio"
"github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/av/avutil"
"github.com/datarhei/joy4/format/flv"
"github.com/datarhei/joy4/format/flv/flvio"
"io"
"net"
"net/url"
"strings"
"time"
"github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/av/avutil"
"github.com/datarhei/joy4/format/flv"
"github.com/datarhei/joy4/format/flv/flvio"
"github.com/datarhei/joy4/utils/bits/pio"
)
var Debug bool
@@ -55,7 +56,7 @@ func DialTimeout(uri string, timeout time.Duration) (conn *Conn, err error) {
return
}
var ErrServerClosed = errors.New("rtmp: Server closed")
var ErrServerClosed = errors.New("server closed")
type Server struct {
Addr string
@@ -98,7 +99,7 @@ func (self *Server) ListenAndServe() error {
listener, err := net.Listen("tcp", addr)
if err != nil {
return fmt.Errorf("rtmp: %w", err)
return err
}
return self.Serve(listener)
@@ -112,7 +113,7 @@ func (self *Server) ListenAndServeTLS(certFile, keyFile string) error {
listener, err := net.Listen("tcp", addr)
if err != nil {
return fmt.Errorf("rtmp: %w", err)
return err
}
return self.ServeTLS(listener, certFile, keyFile)
@@ -135,7 +136,7 @@ func (self *Server) ServeTLS(listener net.Listener, certFile, keyFile string) er
var err error
config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
return fmt.Errorf("rtmp: %w", err)
return err
}
}
@@ -179,8 +180,6 @@ func (self *Server) Serve(listener net.Listener) error {
}
}()
}
return nil
}
func (self *Server) Close() {
@@ -322,6 +321,8 @@ const (
eventtypeStreamBegin = 0
eventtypeSetBufferLength = 3
eventtypeStreamIsRecorded = 4
eventtypePingRequest = 6
eventtypePingResponse = 7
)
func (self *Conn) NetConn() net.Conn {
@@ -429,11 +430,11 @@ func (self *Conn) writeBasicConf() (err error) {
return
}
// > WindowAckSize
if err = self.writeWindowAckSize(5000000); err != nil {
if err = self.writeWindowAckSize(1024 * 1024 * 3); err != nil {
return
}
// > SetPeerBandwidth
if err = self.writeSetPeerBandwidth(5000000, 2); err != nil {
if err = self.writeSetPeerBandwidth(1024*1024*3, 0); err != nil {
return
}
return
@@ -447,18 +448,18 @@ func (self *Conn) readConnect() (err error) {
return
}
if self.commandname != "connect" {
err = fmt.Errorf("rtmp: first command is not connect")
err = fmt.Errorf("first command is not connect")
return
}
if self.commandobj == nil {
err = fmt.Errorf("rtmp: connect command params invalid")
err = fmt.Errorf("connect command params invalid")
return
}
var ok bool
var _app, _tcurl interface{}
if _app, ok = self.commandobj["app"]; !ok {
err = fmt.Errorf("rtmp: `connect` params missing `app`")
err = fmt.Errorf("the `connect` params missing `app`")
return
}
connectpath, _ = _app.(string)
@@ -521,7 +522,7 @@ func (self *Conn) readConnect() (err error) {
}
if len(self.commandparams) < 1 {
err = fmt.Errorf("rtmp: publish params invalid")
err = fmt.Errorf("publish params invalid")
return
}
publishpath, _ := self.commandparams[0].(string)
@@ -547,7 +548,7 @@ func (self *Conn) readConnect() (err error) {
}
if cberr != nil {
err = fmt.Errorf("rtmp: OnPlayOrPublish check failed")
err = fmt.Errorf("OnPlayOrPublish check failed")
return
}
@@ -564,7 +565,7 @@ func (self *Conn) readConnect() (err error) {
}
if len(self.commandparams) < 1 {
err = fmt.Errorf("rtmp: command play params invalid")
err = fmt.Errorf("command play params invalid")
return
}
playpath, _ := self.commandparams[0].(string)
@@ -606,8 +607,6 @@ func (self *Conn) readConnect() (err error) {
}
}
return
}
func (self *Conn) checkConnectResult() (ok bool, errmsg string) {
@@ -657,7 +656,7 @@ func (self *Conn) probe() (err error) {
}
if err = self.prober.PushTag(tag, int32(self.timestamp)); err != nil {
if Debug {
fmt.Printf("error probing tag: %s\n", err.Error())
fmt.Printf("rtmp: error probing tag: %s\n", err.Error())
}
}
}
@@ -705,7 +704,7 @@ func (self *Conn) writeConnect(path string) (err error) {
var ok bool
var errmsg string
if ok, errmsg = self.checkConnectResult(); !ok {
err = fmt.Errorf("rtmp: command connect failed: %s", errmsg)
err = fmt.Errorf("command connect failed: %s", errmsg)
return
}
if Debug {
@@ -718,9 +717,9 @@ func (self *Conn) writeConnect(path string) (err error) {
if len(self.msgdata) == 4 {
self.readAckSize = pio.U32BE(self.msgdata)
}
if err = self.writeWindowAckSize(0xffffffff); err != nil {
return
}
//if err = self.writeWindowAckSize(0xffffffff); err != nil {
// return
//}
}
}
}
@@ -759,7 +758,7 @@ func (self *Conn) connectPublish() (err error) {
if self.commandname == "_result" {
var ok bool
if ok, self.avmsgsid = self.checkCreateStreamResult(); !ok {
err = fmt.Errorf("rtmp: createStream command failed")
err = fmt.Errorf("createStream command failed")
return
}
break
@@ -819,7 +818,7 @@ func (self *Conn) connectPlay() (err error) {
if self.commandname == "_result" {
var ok bool
if ok, self.avmsgsid = self.checkCreateStreamResult(); !ok {
err = fmt.Errorf("rtmp: createStream command failed")
err = fmt.Errorf("createStream command failed")
return
}
break
@@ -862,11 +861,9 @@ func (self *Conn) ReadPacket() (pkt av.Packet, err error) {
var ok bool
if pkt, ok = self.prober.TagToPacket(tag, int32(self.timestamp)); ok {
return
return pkt, nil
}
}
return
}
func (self *Conn) Prepare() (err error) {
@@ -910,7 +907,7 @@ func (self *Conn) prepare(stage int, flags int) (err error) {
return
}
} else {
err = fmt.Errorf("rtmp: call WriteHeader() before WritePacket()")
err = fmt.Errorf("call WriteHeader() before WritePacket()")
return
}
}
@@ -1135,6 +1132,17 @@ func (self *Conn) writeSetBufferLength(msgsid uint32, timestamp uint32) (err err
return
}
func (self *Conn) writePingResponse(timestamp uint32) (err error) {
b := self.tmpwbuf(chunkHeaderLength + 10)
n := self.fillChunkHeader(b, 2, 0, msgtypeidUserControl, 0, 6)
pio.PutU16BE(b[n:], eventtypePingResponse)
n += 2
pio.PutU32BE(b[n:], timestamp)
n += 4
_, err = self.bufw.Write(b[:n])
return
}
const chunkHeaderLength = 12
const FlvTimestampMax = 0xFFFFFF
@@ -1203,13 +1211,13 @@ func (self *Conn) readChunk() (err error) {
default: // Chunk basic header 1
case 0: // Chunk basic header 2
if _, err = io.ReadFull(self.bufr, b[:1]); err != nil {
return
return fmt.Errorf("chunk basic header 2: %w", err)
}
n += 1
csid = uint32(b[0]) + 64
case 1: // Chunk basic header 3
if _, err = io.ReadFull(self.bufr, b[:2]); err != nil {
return
return fmt.Errorf("chunk basic header 3: %w", err)
}
n += 2
csid = uint32(pio.U16BE(b)) + 64
@@ -1237,7 +1245,7 @@ func (self *Conn) readChunk() (err error) {
//
// Figure 9 Chunk Message Header Type 0
if cs.msgdataleft != 0 {
err = fmt.Errorf("rtmp: chunk msgdataleft=%d invalid", cs.msgdataleft)
err = fmt.Errorf("chunk msgdataleft=%d invalid", cs.msgdataleft)
return
}
h := b[:11]
@@ -1274,7 +1282,7 @@ func (self *Conn) readChunk() (err error) {
//
// Figure 10 Chunk Message Header Type 1
if cs.msgdataleft != 0 {
err = fmt.Errorf("rtmp: chunk msgdataleft=%d invalid", cs.msgdataleft)
err = fmt.Errorf("chunk msgdataleft=%d invalid", cs.msgdataleft)
return
}
h := b[:7]
@@ -1309,7 +1317,7 @@ func (self *Conn) readChunk() (err error) {
//
// Figure 11 Chunk Message Header Type 2
if cs.msgdataleft != 0 {
err = fmt.Errorf("rtmp: chunk msgdataleft=%d invalid", cs.msgdataleft)
err = fmt.Errorf("chunk msgdataleft=%d invalid", cs.msgdataleft)
return
}
h := b[:3]
@@ -1361,7 +1369,7 @@ func (self *Conn) readChunk() (err error) {
}
default:
err = fmt.Errorf("rtmp: invalid chunk msg header type=%d", msghdrtype)
err = fmt.Errorf("invalid chunk msg header type=%d", msghdrtype)
return
}
@@ -1389,15 +1397,17 @@ func (self *Conn) readChunk() (err error) {
}
if err = self.handleMsg(cs.timenow, cs.msgsid, cs.msgtypeid, cs.msgdata); err != nil {
return
return fmt.Errorf("handleMsg: %w", err)
}
}
self.ackn += uint32(n)
if self.readAckSize != 0 && self.ackn > self.readAckSize {
if err = self.writeAck(self.ackn); err != nil {
return
return fmt.Errorf("writeACK: %w", err)
}
self.flushWrite()
self.ackn = 0
}
@@ -1423,7 +1433,7 @@ func (self *Conn) handleCommandMsgAMF0(b []byte) (n int, err error) {
var ok bool
if self.commandname, ok = name.(string); !ok {
err = fmt.Errorf("rtmp: CommandMsgAMF0 command is not string")
err = fmt.Errorf("CommandMsgAMF0 command is not string")
return
}
self.commandtransid, _ = transid.(float64)
@@ -1438,7 +1448,7 @@ func (self *Conn) handleCommandMsgAMF0(b []byte) (n int, err error) {
self.commandparams = append(self.commandparams, obj)
}
if n < len(b) {
err = fmt.Errorf("rtmp: CommandMsgAMF0 left bytes=%d", len(b)-n)
err = fmt.Errorf("CommandMsgAMF0 left bytes=%d", len(b)-n)
return
}
@@ -1459,7 +1469,7 @@ func (self *Conn) handleMsg(timestamp uint32, msgsid uint32, msgtypeid uint8, ms
case msgtypeidCommandMsgAMF3:
if len(msgdata) < 1 {
err = fmt.Errorf("rtmp: short packet of CommandMsgAMF3")
err = fmt.Errorf("short packet of CommandMsgAMF3")
return
}
// skip first byte
@@ -1469,11 +1479,21 @@ func (self *Conn) handleMsg(timestamp uint32, msgsid uint32, msgtypeid uint8, ms
case msgtypeidUserControl:
if len(msgdata) < 2 {
err = fmt.Errorf("rtmp: short packet of UserControl")
err = fmt.Errorf("short packet of UserControl")
return
}
self.eventtype = pio.U16BE(msgdata)
if self.eventtype == eventtypePingRequest {
if len(msgdata) != 6 {
err = fmt.Errorf("wrong length for UserControl.PingRequest")
return
}
pingtimestamp := pio.U32BE(msgdata[2:])
self.writePingResponse(pingtimestamp)
self.flushWrite()
}
case msgtypeidDataMsgAMF0:
b := msgdata
n := 0
@@ -1487,7 +1507,7 @@ func (self *Conn) handleMsg(timestamp uint32, msgsid uint32, msgtypeid uint8, ms
self.datamsgvals = append(self.datamsgvals, obj)
}
if n < len(b) {
err = fmt.Errorf("rtmp: DataMsgAMF0 left bytes=%d", len(b)-n)
err = fmt.Errorf("DataMsgAMF0 left bytes=%d", len(b)-n)
return
}
@@ -1499,7 +1519,7 @@ func (self *Conn) handleMsg(timestamp uint32, msgsid uint32, msgtypeid uint8, ms
switch x.(type) {
case string:
if x.(string) == "onMetaData" {
metaindex = i+1
metaindex = i + 1
}
}
}
@@ -1537,11 +1557,17 @@ func (self *Conn) handleMsg(timestamp uint32, msgsid uint32, msgtypeid uint8, ms
case msgtypeidSetChunkSize:
if len(msgdata) < 4 {
err = fmt.Errorf("rtmp: short packet of SetChunkSize")
err = fmt.Errorf("short packet of SetChunkSize")
return
}
self.readMaxChunkSize = int(pio.U32BE(msgdata))
return
case msgtypeidWindowAckSize:
if len(self.msgdata) != 4 {
return fmt.Errorf("invalid packet of WindowAckSize")
}
self.readAckSize = pio.U32BE(self.msgdata)
return
}
self.gotmsg = true
@@ -1660,7 +1686,7 @@ func (self *Conn) handshakeClient() (err error) {
}
if Debug {
fmt.Println("rtmp: handshakeClient: server version", S1[4], S1[5], S1[6], S1[7])
fmt.Println("handshakeClient: server version", S1[4], S1[5], S1[6], S1[7])
}
if ver := pio.U32BE(S1[4:8]); ver != 0 {
@@ -1698,7 +1724,7 @@ func (self *Conn) handshakeServer() (err error) {
return
}
if C0[0] != 3 {
err = fmt.Errorf("rtmp: handshake version=%d invalid", C0[0])
err = fmt.Errorf("handshake version=%d invalid", C0[0])
return
}
@@ -1713,7 +1739,7 @@ func (self *Conn) handshakeServer() (err error) {
var ok bool
var digest []byte
if ok, digest = hsParse1(C1, hsClientPartialKey, hsServerFullKey); !ok {
err = fmt.Errorf("rtmp: handshake server: C1 invalid")
err = fmt.Errorf("handshake server: C1 invalid")
return
}
hsCreate01(S0S1, srvtime, srvver, hsServerPartialKey)

View File

@@ -8,13 +8,13 @@ import (
"encoding/binary"
"encoding/hex"
"fmt"
"github.com/datarhei/joy4/utils/bits/pio"
"github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/av/avutil"
"github.com/datarhei/joy4/codec"
"github.com/datarhei/joy4/codec/aacparser"
"github.com/datarhei/joy4/codec/h264parser"
"github.com/datarhei/joy4/format/rtsp/sdp"
"github.com/datarhei/joy4/utils/bits/pio"
"io"
"net"
"net/textproto"
@@ -31,7 +31,7 @@ var DebugRtsp = false
var SkipErrRtpBlock = false
const (
stageDescribeDone = iota+1
stageDescribeDone = iota + 1
stageSetupDone
stageWaitCodecData
stageCodecDataDone
@@ -121,7 +121,7 @@ func Dial(uri string) (self *Client, err error) {
}
func (self *Client) allCodecDataReady() bool {
for _, si:= range self.setupIdx {
for _, si := range self.setupIdx {
stream := self.streams[si]
if stream.CodecData == nil {
return false
@@ -268,7 +268,7 @@ func (self *Client) parseBlockHeader(h []byte) (length int, no int, valid bool)
timestamp -= stream.firsttimestamp
if timestamp < stream.timestamp {
return
} else if timestamp - stream.timestamp > uint32(stream.timeScale()*60*60) {
} else if timestamp-stream.timestamp > uint32(stream.timeScale()*60*60) {
return
}
}
@@ -373,7 +373,7 @@ func (self *Client) handle401(res *Response) (err error) {
func (self *Client) findRTSP() (block []byte, data []byte, err error) {
const (
R = iota+1
R = iota + 1
T
S
Header
@@ -383,7 +383,7 @@ func (self *Client) findRTSP() (block []byte, data []byte, err error) {
peek := _peek[0:0]
stat := 0
for i := 0;; i++ {
for i := 0; ; i++ {
var b byte
if b, err = self.brconn.ReadByte(); err != nil {
return
@@ -434,7 +434,7 @@ func (self *Client) findRTSP() (block []byte, data []byte, err error) {
fmt.Println("rtsp: dollar at", i, len(peek))
}
if blocklen, _, ok := self.parseBlockHeader(peek); ok {
left := blocklen+4-len(peek)
left := blocklen + 4 - len(peek)
block = append(peek, make([]byte, left)...)
if _, err = io.ReadFull(self.brconn, block[len(peek):]); err != nil {
return
@@ -451,7 +451,7 @@ func (self *Client) findRTSP() (block []byte, data []byte, err error) {
func (self *Client) readLFLF() (block []byte, data []byte, err error) {
const (
LF = iota+1
LF = iota + 1
LFLF
)
peek := []byte{}
@@ -471,7 +471,7 @@ func (self *Client) readLFLF() (block []byte, data []byte, err error) {
stat = LF
lpos = pos
} else if stat == LF {
if pos - lpos <= 2 {
if pos-lpos <= 2 {
stat = LFLF
} else {
lpos = pos
@@ -485,9 +485,9 @@ func (self *Client) readLFLF() (block []byte, data []byte, err error) {
if stat == LFLF {
data = peek
return
} else if dollarpos != -1 && dollarpos - pos >= 12 {
hdrlen := dollarpos-pos
start := len(peek)-hdrlen
} else if dollarpos != -1 && dollarpos-pos >= 12 {
hdrlen := dollarpos - pos
start := len(peek) - hdrlen
if blocklen, _, ok := self.parseBlockHeader(peek[start:]); ok {
block = append(peek[start:], make([]byte, blocklen+4-hdrlen)...)
if _, err = io.ReadFull(self.brconn, block[hdrlen:]); err != nil {
@@ -810,7 +810,7 @@ func (self *Stream) handleH264Payload(timestamp uint32, packet []byte) (err erro
return
}
naluType := packet[0]&0x1f
naluType := packet[0] & 0x1f
/*
Table 7-1 NAL unit type codes
@@ -963,7 +963,7 @@ func (self *Stream) handleH264Payload(timestamp uint32, packet []byte) (err erro
*/
packet = packet[1:]
for len(packet) >= 2 {
size := int(packet[0])<<8|int(packet[1])
size := int(packet[0])<<8 | int(packet[1])
if size+2 > len(packet) {
break
}
@@ -1141,7 +1141,7 @@ func (self *Client) handleBlock(block []byte) (pkt av.Packet, ok bool, err error
return
}
i := blockno/2
i := blockno / 2
if i >= len(self.streams) {
err = fmt.Errorf("rtsp: block no=%d invalid", blockno)
return
@@ -1171,10 +1171,10 @@ func (self *Client) handleBlock(block []byte) (pkt av.Packet, ok bool, err error
ok = true
pkt = stream.pkt
pkt.Time = time.Duration(stream.timestamp)*time.Second / time.Duration(stream.timeScale())
pkt.Time = time.Duration(stream.timestamp) * time.Second / time.Duration(stream.timeScale())
pkt.Idx = int8(self.setupMap[i])
if pkt.Time < stream.lasttime || pkt.Time - stream.lasttime > time.Minute*30 {
if pkt.Time < stream.lasttime || pkt.Time-stream.lasttime > time.Minute*30 {
err = fmt.Errorf("rtp: time invalid stream#%d time=%v lasttime=%v", pkt.Idx, pkt.Time, stream.lasttime)
return
}
@@ -1236,4 +1236,3 @@ func Handler(h *avutil.RegisterHandler) {
return
}
}

View File

@@ -26,4 +26,3 @@ type Stream struct {
lasttime time.Duration
}

View File

@@ -3,13 +3,13 @@ package ts
import (
"bufio"
"fmt"
"time"
"github.com/datarhei/joy4/utils/bits/pio"
"github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/format/ts/tsio"
"github.com/datarhei/joy4/codec/aacparser"
"github.com/datarhei/joy4/codec/h264parser"
"github.com/datarhei/joy4/format/ts/tsio"
"github.com/datarhei/joy4/utils/bits/pio"
"io"
"time"
)
type Demuxer struct {
@@ -101,7 +101,7 @@ func (self *Demuxer) initPMT(payload []byte) (err error) {
return
}
self.pmt = &tsio.PMT{}
if _, err = self.pmt.Unmarshal(payload[psihdrlen:psihdrlen+datalen]); err != nil {
if _, err = self.pmt.Unmarshal(payload[psihdrlen : psihdrlen+datalen]); err != nil {
return
}
@@ -156,7 +156,7 @@ func (self *Demuxer) readTSPacket() (err error) {
return
}
self.pat = &tsio.PAT{}
if _, err = self.pat.Unmarshal(payload[psihdrlen:psihdrlen+datalen]); err != nil {
if _, err = self.pat.Unmarshal(payload[psihdrlen : psihdrlen+datalen]); err != nil {
return
}
}
@@ -194,11 +194,11 @@ func (self *Stream) addPacket(payload []byte, timedelta time.Duration) {
pkt := av.Packet{
Idx: int8(self.idx),
IsKeyFrame: self.iskeyframe,
Time: dts+timedelta,
Time: dts + timedelta,
Data: payload,
}
if pts != dts {
pkt.CompositionTime = pts-dts
pkt.CompositionTime = pts - dts
}
demuxer.pkts = append(demuxer.pkts, pkt)
}

View File

@@ -1,9 +1,9 @@
package ts
import (
"io"
"github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/av/avutil"
"io"
)
func Handler(h *avutil.RegisterHandler) {
@@ -23,4 +23,3 @@ func Handler(h *avutil.RegisterHandler) {
h.CodecTypes = CodecTypes
}

View File

@@ -1,9 +1,9 @@
package ts
import (
"time"
"github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/format/ts/tsio"
"time"
)
type Stream struct {
@@ -24,4 +24,3 @@ type Stream struct {
data []byte
datalen int
}

View File

@@ -52,4 +52,3 @@ func calcCRC32(crc uint32, data []byte) uint32 {
}
return crc
}

View File

@@ -1,11 +1,10 @@
package tsio
import (
"io"
"time"
"fmt"
"github.com/datarhei/joy4/utils/bits/pio"
"io"
"time"
)
const (
@@ -48,7 +47,7 @@ type PAT struct {
}
func (self PAT) Len() (n int) {
return len(self.Entries)*4
return len(self.Entries) * 4
}
func (self PAT) Marshal(b []byte) (n int) {
@@ -73,10 +72,10 @@ func (self *PAT) Unmarshal(b []byte) (n int, err error) {
entry.ProgramNumber = pio.U16BE(b[n:])
n += 2
if entry.ProgramNumber == 0 {
entry.NetworkPID = pio.U16BE(b[n:])&0x1fff
entry.NetworkPID = pio.U16BE(b[n:]) & 0x1fff
n += 2
} else {
entry.ProgramMapPID = pio.U16BE(b[n:])&0x1fff
entry.ProgramMapPID = pio.U16BE(b[n:]) & 0x1fff
n += 2
}
self.Entries = append(self.Entries, entry)
@@ -117,7 +116,7 @@ func (self PMT) Len() (n int) {
n += 2
for _, desc := range self.ProgramDescriptors {
n += 2+len(desc.Data)
n += 2 + len(desc.Data)
}
for _, info := range self.ElementaryStreamInfos {
@@ -133,7 +132,7 @@ func (self PMT) Len() (n int) {
n += 2
for _, desc := range info.Descriptors {
n += 2+len(desc.Data)
n += 2 + len(desc.Data)
}
}
@@ -162,7 +161,7 @@ func (self PMT) Marshal(b []byte) (n int) {
n += 2
pos := n
n += self.fillDescs(b[n:], self.ProgramDescriptors)
desclen := n-pos
desclen := n - pos
pio.PutU16BE(b[hold:], uint16(desclen)|0xf<<12)
for _, info := range self.ElementaryStreamInfos {
@@ -178,7 +177,7 @@ func (self PMT) Marshal(b []byte) (n int) {
n += 2
pos := n
n += self.fillDescs(b[n:], info.Descriptors)
desclen := n-pos
desclen := n - pos
pio.PutU16BE(b[hold:], uint16(desclen)|0x3c<<10)
}
@@ -219,13 +218,13 @@ func (self *PMT) Unmarshal(b []byte) (n int, err error) {
// 111(3)
// PCRPID(13)
self.PCRPID = pio.U16BE(b[0:2])&0x1fff
self.PCRPID = pio.U16BE(b[0:2]) & 0x1fff
n += 2
// Reserved(4)=0xf
// Reserved(2)=0x0
// Program info length(10)
desclen := int(pio.U16BE(b[2:4])&0x3ff)
desclen := int(pio.U16BE(b[2:4]) & 0x3ff)
n += 2
if desclen > 0 {
@@ -233,7 +232,7 @@ func (self *PMT) Unmarshal(b []byte) (n int, err error) {
err = ErrParsePMT
return
}
if self.ProgramDescriptors, err = self.parseDescs(b[n:n+desclen]); err != nil {
if self.ProgramDescriptors, err = self.parseDescs(b[n : n+desclen]); err != nil {
return
}
n += desclen
@@ -251,12 +250,12 @@ func (self *PMT) Unmarshal(b []byte) (n int, err error) {
// Reserved(3)
// Elementary PID(13)
info.ElementaryPID = pio.U16BE(b[n:])&0x1fff
info.ElementaryPID = pio.U16BE(b[n:]) & 0x1fff
n += 2
// Reserved(6)
// ES Info length(10)
desclen := int(pio.U16BE(b[n:])&0x3ff)
desclen := int(pio.U16BE(b[n:]) & 0x3ff)
n += 2
if desclen > 0 {
@@ -264,7 +263,7 @@ func (self *PMT) Unmarshal(b []byte) (n int, err error) {
err = ErrParsePMT
return
}
if info.Descriptors, err = self.parseDescs(b[n:n+desclen]); err != nil {
if info.Descriptors, err = self.parseDescs(b[n : n+desclen]); err != nil {
return
}
n += desclen
@@ -345,7 +344,7 @@ func FillPSI(h []byte, tableid uint8, tableext uint16, datalen int) (n int) {
n++
// section_syntax_indicator(1)=1,private_bit(1)=0,reserved(2)=3,unused(2)=0,section_length(10)
pio.PutU16BE(h[n:], uint16(0xa<<12 | 2+3+4+datalen))
pio.PutU16BE(h[n:], uint16(0xa<<12|2+3+4+datalen))
n += 2
// Table ID extension(16)
@@ -375,7 +374,7 @@ func FillPSI(h []byte, tableid uint8, tableext uint16, datalen int) (n int) {
func TimeToPCR(tm time.Duration) (pcr uint64) {
// base(33)+resverd(6)+ext(9)
ts := uint64(tm*PCR_HZ/time.Second)
ts := uint64(tm * PCR_HZ / time.Second)
base := ts / 300
ext := ts % 300
pcr = base<<15 | 0x3f<<9 | ext
@@ -386,12 +385,12 @@ func PCRToTime(pcr uint64) (tm time.Duration) {
base := pcr >> 15
ext := pcr & 0x1ff
ts := base*300 + ext
tm = time.Duration(ts)*time.Second/time.Duration(PCR_HZ)
tm = time.Duration(ts) * time.Second / time.Duration(PCR_HZ)
return
}
func TimeToTs(tm time.Duration) (v uint64) {
ts := uint64(tm*PTS_HZ/time.Second)
ts := uint64(tm * PTS_HZ / time.Second)
// 0010 PTS 32..30 1 PTS 29..15 1 PTS 14..00 1
v = ((ts>>30)&0x7)<<33 | ((ts>>15)&0x7fff)<<17 | (ts&0x7fff)<<1 | 0x100010001
return
@@ -399,8 +398,8 @@ func TimeToTs(tm time.Duration) (v uint64) {
func TsToTime(v uint64) (tm time.Duration) {
// 0010 PTS 32..30 1 PTS 29..15 1 PTS 14..00 1
ts := (((v>>33)&0x7)<<30) | (((v>>17)&0x7fff) << 15) | ((v>>1)&0x7fff)
tm = time.Duration(ts)*time.Second/time.Duration(PTS_HZ)
ts := (((v >> 33) & 0x7) << 30) | (((v >> 17) & 0x7fff) << 15) | ((v >> 1) & 0x7fff)
tm = time.Duration(ts) * time.Second / time.Duration(PTS_HZ)
return
}
@@ -417,11 +416,11 @@ func ParsePESHeader(h []byte) (hdrlen int, streamid uint8, datalen int, pts, dts
streamid = h[3]
flags := h[7]
hdrlen = int(h[8])+9
hdrlen = int(h[8]) + 9
datalen = int(pio.U16BE(h[4:6]))
if datalen > 0 {
datalen -= int(h[8])+3
datalen -= int(h[8]) + 3
}
const PTS = 1 << 7
@@ -479,7 +478,7 @@ func FillPESHeader(h []byte, streamid uint8, datalen int, pts, dts time.Duration
}
pio.PutU16BE(h[4:6], pktlen)
h[6] = 2<<6|1 // resverd(6,2)=2,original_or_copy(0,1)=1
h[6] = 2<<6 | 1 // resverd(6,2)=2,original_or_copy(0,1)=1
h[7] = flags
h[8] = uint8(n)
@@ -521,21 +520,21 @@ func (self *TSWriter) WritePackets(w io.Writer, datav [][]byte, pcr time.Duratio
writepos := 0
for writepos < datavlen {
self.tshdr[1] = self.tshdr[1]&0x1f
self.tshdr[3] = byte(self.ContinuityCounter)&0xf|0x30
self.tshdr[1] = self.tshdr[1] & 0x1f
self.tshdr[3] = byte(self.ContinuityCounter)&0xf | 0x30
self.tshdr[5] = 0 // flags
hdrlen := 6
self.ContinuityCounter++
if writepos == 0 {
self.tshdr[1] = 0x40|self.tshdr[1] // Payload Unit Start Indicator
self.tshdr[1] = 0x40 | self.tshdr[1] // Payload Unit Start Indicator
if pcr != 0 {
hdrlen += 6
self.tshdr[5] = 0x10|self.tshdr[5] // PCR flag (Discontinuity indicator 0x80)
self.tshdr[5] = 0x10 | self.tshdr[5] // PCR flag (Discontinuity indicator 0x80)
pio.PutU48BE(self.tshdr[6:12], TimeToPCR(pcr))
}
if sync {
self.tshdr[5] = 0x40|self.tshdr[5] // Random Access indicator
self.tshdr[5] = 0x40 | self.tshdr[5] // Random Access indicator
}
}
@@ -551,7 +550,7 @@ func (self *TSWriter) WritePackets(w io.Writer, datav [][]byte, pcr time.Duratio
}
n := pio.VecSliceTo(datav, writev, writepos, end)
self.tshdr[4] = byte(hdrlen)-5 // length
self.tshdr[4] = byte(hdrlen) - 5 // length
if _, err = w.Write(self.tshdr[:hdrlen]); err != nil {
return
}
@@ -561,7 +560,7 @@ func (self *TSWriter) WritePackets(w io.Writer, datav [][]byte, pcr time.Duratio
}
}
if padtail > 0 {
if _, err = w.Write(self.tshdr[188-padtail:188]); err != nil {
if _, err = w.Write(self.tshdr[188-padtail : 188]); err != nil {
return
}
}
@@ -578,13 +577,12 @@ func ParseTSHeader(tshdr []byte) (pid uint16, start bool, iskeyframe bool, hdrle
err = fmt.Errorf("tshdr sync invalid")
return
}
pid = uint16((tshdr[1]&0x1f))<<8|uint16(tshdr[2])
pid = uint16((tshdr[1]&0x1f))<<8 | uint16(tshdr[2])
start = tshdr[1]&0x40 != 0
hdrlen += 4
if tshdr[3]&0x20 != 0 {
hdrlen += int(tshdr[4])+1
hdrlen += int(tshdr[4]) + 1
iskeyframe = tshdr[5]&0x40 != 0
}
return
}

View File

@@ -1,5 +1,3 @@
package pio
var RecommendBufioSize = 1024*64
var RecommendBufioSize = 1024 * 64

View File

@@ -1,4 +1,3 @@
package pio
func U8(b []byte) (i uint8) {
@@ -7,85 +6,116 @@ func U8(b []byte) (i uint8) {
func U16BE(b []byte) (i uint16) {
i = uint16(b[0])
i <<= 8; i |= uint16(b[1])
i <<= 8
i |= uint16(b[1])
return
}
func I16BE(b []byte) (i int16) {
i = int16(b[0])
i <<= 8; i |= int16(b[1])
i <<= 8
i |= int16(b[1])
return
}
func I24BE(b []byte) (i int32) {
i = int32(int8(b[0]))
i <<= 8; i |= int32(b[1])
i <<= 8; i |= int32(b[2])
i <<= 8
i |= int32(b[1])
i <<= 8
i |= int32(b[2])
return
}
func U24BE(b []byte) (i uint32) {
i = uint32(b[0])
i <<= 8; i |= uint32(b[1])
i <<= 8; i |= uint32(b[2])
i <<= 8
i |= uint32(b[1])
i <<= 8
i |= uint32(b[2])
return
}
func I32BE(b []byte) (i int32) {
i = int32(int8(b[0]))
i <<= 8; i |= int32(b[1])
i <<= 8; i |= int32(b[2])
i <<= 8; i |= int32(b[3])
i <<= 8
i |= int32(b[1])
i <<= 8
i |= int32(b[2])
i <<= 8
i |= int32(b[3])
return
}
func U32LE(b []byte) (i uint32) {
i = uint32(b[3])
i <<= 8; i |= uint32(b[2])
i <<= 8; i |= uint32(b[1])
i <<= 8; i |= uint32(b[0])
i <<= 8
i |= uint32(b[2])
i <<= 8
i |= uint32(b[1])
i <<= 8
i |= uint32(b[0])
return
}
func U32BE(b []byte) (i uint32) {
i = uint32(b[0])
i <<= 8; i |= uint32(b[1])
i <<= 8; i |= uint32(b[2])
i <<= 8; i |= uint32(b[3])
i <<= 8
i |= uint32(b[1])
i <<= 8
i |= uint32(b[2])
i <<= 8
i |= uint32(b[3])
return
}
func U40BE(b []byte) (i uint64) {
i = uint64(b[0])
i <<= 8; i |= uint64(b[1])
i <<= 8; i |= uint64(b[2])
i <<= 8; i |= uint64(b[3])
i <<= 8; i |= uint64(b[4])
i <<= 8
i |= uint64(b[1])
i <<= 8
i |= uint64(b[2])
i <<= 8
i |= uint64(b[3])
i <<= 8
i |= uint64(b[4])
return
}
func U64BE(b []byte) (i uint64) {
i = uint64(b[0])
i <<= 8; i |= uint64(b[1])
i <<= 8; i |= uint64(b[2])
i <<= 8; i |= uint64(b[3])
i <<= 8; i |= uint64(b[4])
i <<= 8; i |= uint64(b[5])
i <<= 8; i |= uint64(b[6])
i <<= 8; i |= uint64(b[7])
i <<= 8
i |= uint64(b[1])
i <<= 8
i |= uint64(b[2])
i <<= 8
i |= uint64(b[3])
i <<= 8
i |= uint64(b[4])
i <<= 8
i |= uint64(b[5])
i <<= 8
i |= uint64(b[6])
i <<= 8
i |= uint64(b[7])
return
}
func I64BE(b []byte) (i int64) {
i = int64(int8(b[0]))
i <<= 8; i |= int64(b[1])
i <<= 8; i |= int64(b[2])
i <<= 8; i |= int64(b[3])
i <<= 8; i |= int64(b[4])
i <<= 8; i |= int64(b[5])
i <<= 8; i |= int64(b[6])
i <<= 8; i |= int64(b[7])
i <<= 8
i |= int64(b[1])
i <<= 8
i |= int64(b[2])
i <<= 8
i |= int64(b[3])
i <<= 8
i |= int64(b[4])
i <<= 8
i |= int64(b[5])
i <<= 8
i |= int64(b[6])
i <<= 8
i |= int64(b[7])
return
}

View File

@@ -38,12 +38,12 @@ func VecSliceTo(in [][]byte, out [][]byte, s int, e int) (n int) {
}
for e != 0 && i < len(in) {
left := len(in[i])-off
left := len(in[i]) - off
read := left
if e > 0 && e < read {
read = e
}
out[n] = in[i][off:off+read]
out[n] = in[i][off : off+read]
n++
left -= read
e -= read
@@ -66,4 +66,3 @@ func VecSlice(in [][]byte, s int, e int) (out [][]byte) {
out = out[:n]
return
}

View File

@@ -1,4 +1,3 @@
package pio
func PutU8(b []byte, v uint8) {
@@ -6,84 +5,83 @@ func PutU8(b []byte, v uint8) {
}
func PutI16BE(b []byte, v int16) {
b[0] = byte(v>>8)
b[0] = byte(v >> 8)
b[1] = byte(v)
}
func PutU16BE(b []byte, v uint16) {
b[0] = byte(v>>8)
b[0] = byte(v >> 8)
b[1] = byte(v)
}
func PutI24BE(b []byte, v int32) {
b[0] = byte(v>>16)
b[1] = byte(v>>8)
b[0] = byte(v >> 16)
b[1] = byte(v >> 8)
b[2] = byte(v)
}
func PutU24BE(b []byte, v uint32) {
b[0] = byte(v>>16)
b[1] = byte(v>>8)
b[0] = byte(v >> 16)
b[1] = byte(v >> 8)
b[2] = byte(v)
}
func PutI32BE(b []byte, v int32) {
b[0] = byte(v>>24)
b[1] = byte(v>>16)
b[2] = byte(v>>8)
b[0] = byte(v >> 24)
b[1] = byte(v >> 16)
b[2] = byte(v >> 8)
b[3] = byte(v)
}
func PutU32BE(b []byte, v uint32) {
b[0] = byte(v>>24)
b[1] = byte(v>>16)
b[2] = byte(v>>8)
b[0] = byte(v >> 24)
b[1] = byte(v >> 16)
b[2] = byte(v >> 8)
b[3] = byte(v)
}
func PutU32LE(b []byte, v uint32) {
b[3] = byte(v>>24)
b[2] = byte(v>>16)
b[1] = byte(v>>8)
b[3] = byte(v >> 24)
b[2] = byte(v >> 16)
b[1] = byte(v >> 8)
b[0] = byte(v)
}
func PutU40BE(b []byte, v uint64) {
b[0] = byte(v>>32)
b[1] = byte(v>>24)
b[2] = byte(v>>16)
b[3] = byte(v>>8)
b[0] = byte(v >> 32)
b[1] = byte(v >> 24)
b[2] = byte(v >> 16)
b[3] = byte(v >> 8)
b[4] = byte(v)
}
func PutU48BE(b []byte, v uint64) {
b[0] = byte(v>>40)
b[1] = byte(v>>32)
b[2] = byte(v>>24)
b[3] = byte(v>>16)
b[4] = byte(v>>8)
b[0] = byte(v >> 40)
b[1] = byte(v >> 32)
b[2] = byte(v >> 24)
b[3] = byte(v >> 16)
b[4] = byte(v >> 8)
b[5] = byte(v)
}
func PutU64BE(b []byte, v uint64) {
b[0] = byte(v>>56)
b[1] = byte(v>>48)
b[2] = byte(v>>40)
b[3] = byte(v>>32)
b[4] = byte(v>>24)
b[5] = byte(v>>16)
b[6] = byte(v>>8)
b[0] = byte(v >> 56)
b[1] = byte(v >> 48)
b[2] = byte(v >> 40)
b[3] = byte(v >> 32)
b[4] = byte(v >> 24)
b[5] = byte(v >> 16)
b[6] = byte(v >> 8)
b[7] = byte(v)
}
func PutI64BE(b []byte, v int64) {
b[0] = byte(v>>56)
b[1] = byte(v>>48)
b[2] = byte(v>>40)
b[3] = byte(v>>32)
b[4] = byte(v>>24)
b[5] = byte(v>>16)
b[6] = byte(v>>8)
b[0] = byte(v >> 56)
b[1] = byte(v >> 48)
b[2] = byte(v >> 40)
b[3] = byte(v >> 32)
b[4] = byte(v >> 24)
b[5] = byte(v >> 16)
b[6] = byte(v >> 8)
b[7] = byte(v)
}

2
vendor/modules.txt vendored
View File

@@ -53,7 +53,7 @@ github.com/datarhei/gosrt/internal/congestion
github.com/datarhei/gosrt/internal/crypto
github.com/datarhei/gosrt/internal/net
github.com/datarhei/gosrt/internal/packet
# github.com/datarhei/joy4 v0.0.0-20210125162555-2102a8289cce
# github.com/datarhei/joy4 v0.0.0-20220728180719-f752080f4a36
## explicit; go 1.14
github.com/datarhei/joy4/av
github.com/datarhei/joy4/av/avutil