This commit is contained in:
Ingo Oppermann 2022-07-28 18:31:52 +02:00
parent 7098ea1efd
commit 01b5cd703f
38 changed files with 717 additions and 725 deletions

View File

@ -1,4 +1,3 @@
// Package av defines basic interfaces and data structures of container demux/mux and audio encode/decode.
package av
@ -11,17 +10,17 @@ import (
type SampleFormat uint8
const (
U8 = SampleFormat(iota + 1) // 8-bit unsigned integer
S16 // signed 16-bit integer
S32 // signed 32-bit integer
FLT // 32-bit float
DBL // 64-bit float
U8P // 8-bit unsigned integer in planar
S16P // signed 16-bit integer in planar
S32P // signed 32-bit integer in planar
FLTP // 32-bit float in planar
DBLP // 64-bit float in planar
U32 // unsigned 32-bit integer
U8 = SampleFormat(iota + 1) // 8-bit unsigned integer
S16 // signed 16-bit integer
S32 // signed 32-bit integer
FLT // 32-bit float
DBL // 64-bit float
U8P // 8-bit unsigned integer in planar
S16P // signed 16-bit integer in planar
S32P // signed 32-bit integer in planar
FLTP // 32-bit float in planar
DBLP // 64-bit float in planar
U32 // unsigned 32-bit integer
)
func (self SampleFormat) BytesPerSample() int {
@ -116,11 +115,11 @@ func (self ChannelLayout) Count() (n int) {
type CodecType uint32
var (
H264 = MakeVideoCodecType(avCodecTypeMagic + 1)
AAC = MakeAudioCodecType(avCodecTypeMagic + 1)
PCM_MULAW = MakeAudioCodecType(avCodecTypeMagic + 2)
PCM_ALAW = MakeAudioCodecType(avCodecTypeMagic + 3)
SPEEX = MakeAudioCodecType(avCodecTypeMagic + 4)
H264 = MakeVideoCodecType(avCodecTypeMagic + 1)
AAC = MakeAudioCodecType(avCodecTypeMagic + 1)
PCM_MULAW = MakeAudioCodecType(avCodecTypeMagic + 2)
PCM_ALAW = MakeAudioCodecType(avCodecTypeMagic + 3)
SPEEX = MakeAudioCodecType(avCodecTypeMagic + 4)
NELLYMOSER = MakeAudioCodecType(avCodecTypeMagic + 5)
)
@ -179,15 +178,15 @@ type CodecData interface {
type VideoCodecData interface {
CodecData
Width() int // Video width
Width() int // Video width
Height() int // Video height
}
type AudioCodecData interface {
CodecData
SampleFormat() SampleFormat // audio sample format
SampleRate() int // audio sample rate
ChannelLayout() ChannelLayout // audio channel layout
SampleFormat() SampleFormat // audio sample format
SampleRate() int // audio sample rate
ChannelLayout() ChannelLayout // audio channel layout
PacketDuration([]byte) (time.Duration, error) // get audio compressed packet duration
}
@ -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.
@ -204,8 +203,8 @@ type PacketReader interface {
// Container formats, rtmp.Conn, and transcode.Muxer implements Muxer interface.
type Muxer interface {
WriteHeader([]CodecData) error // write the file header
PacketWriter // write compressed audio/video packets
WriteTrailer() error // finish writing file, this func can be called only once
PacketWriter // write compressed audio/video packets
WriteTrailer() error // finish writing file, this func can be called only once
}
// Muxer with Close() method
@ -216,7 +215,7 @@ type MuxCloser interface {
// Demuxer can read compressed audio/video packets from container formats like MP4/FLV/MPEG-TS.
type Demuxer interface {
PacketReader // read compressed audio/video packets
PacketReader // read compressed audio/video packets
Streams() ([]CodecData, error) // reads the file header, contains video/audio meta infomations
}
@ -228,20 +227,20 @@ type DemuxCloser interface {
// Packet stores compressed audio/video data.
type Packet struct {
IsKeyFrame bool // video packet is key frame
Idx int8 // stream index in container format
IsKeyFrame bool // video packet is key frame
Idx int8 // stream index in container format
CompositionTime time.Duration // packet presentation time minus decode time for H264 B-Frame
Time time.Duration // packet decode time
Data []byte // packet data
Time time.Duration // packet decode time
Data []byte // packet data
}
// Raw audio frame.
type AudioFrame struct {
SampleFormat SampleFormat // audio sample format, e.g: S16,FLTP,...
SampleFormat SampleFormat // audio sample format, e.g: S16,FLTP,...
ChannelLayout ChannelLayout // audio channel layout, e.g: CH_MONO,CH_STEREO,...
SampleCount int // sample count in this frame
SampleRate int // sample rate
Data [][]byte // data array for planar format len(Data) > 1
SampleCount int // sample count in this frame
SampleRate int // sample rate
Data [][]byte // data array for planar format len(Data) > 1
}
func (self AudioFrame) Duration() time.Duration {
@ -291,26 +290,25 @@ func (self AudioFrame) Concat(in AudioFrame) (out AudioFrame) {
// AudioEncoder can encode raw audio frame into compressed audio packets.
// cgo/ffmpeg inplements AudioEncoder, using ffmpeg.NewAudioEncoder to create it.
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
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
}
// AudioDecoder can decode compressed audio packets into raw audio frame.
// use ffmpeg.NewAudioDecoder to create it.
type AudioDecoder interface {
Decode([]byte) (bool, AudioFrame, error) // decode one compressed audio packet
Close() // close decode, free cgo contexts
Close() // close decode, free cgo contexts
}
// AudioResampler can convert raw audio frames in different sample rate/format/channel layout.
type AudioResampler interface {
Resample(AudioFrame) (AudioFrame, error) // convert raw audio frames
}

View File

@ -2,19 +2,19 @@ package avconv
import (
"fmt"
"io"
"time"
"github.com/datarhei/joy4/av/avutil"
"github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/av/avutil"
"github.com/datarhei/joy4/av/pktque"
"github.com/datarhei/joy4/av/transcode"
"io"
"time"
)
var Debug bool
type Option struct {
Transcode bool
Args []string
Args []string
}
type Options struct {
@ -23,7 +23,7 @@ type Options struct {
type Demuxer struct {
transdemux *transcode.Demuxer
streams []av.CodecData
streams []av.CodecData
Options
Demuxer av.Demuxer
}
@ -56,10 +56,10 @@ func (self *Demuxer) prepare() (err error) {
}
/*
var streams []av.CodecData
if streams, err = self.Demuxer.Streams(); err != nil {
return
}
var streams []av.CodecData
if streams, err = self.Demuxer.Streams(); err != nil {
return
}
*/
supports := self.Options.OutputCodecTypes
@ -83,7 +83,7 @@ func (self *Demuxer) prepare() (err error) {
ok = true
var enctype av.CodecType
for _, typ:= range supports {
for _, typ := range supports {
if typ.IsAudio() {
if enc, _ = avutil.DefaultHandlers.NewAudioEncoder(typ); enc != nil {
enctype = typ
@ -152,7 +152,7 @@ func ConvertCmdline(args []string) (err error) {
flagt = false
var f float64
fmt.Sscanf(arg, "%f", &f)
duration = time.Duration(f*float64(time.Second))
duration = time.Duration(f * float64(time.Second))
default:
output = arg
@ -223,7 +223,7 @@ func ConvertCmdline(args []string) (err error) {
}
filterdemux := &pktque.FilterDemuxer{
Demuxer: convdemux,
Filter: filters,
Filter: filters,
}
for {
@ -252,4 +252,3 @@ func ConvertCmdline(args []string) (err error) {
return
}

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 {
@ -22,7 +23,7 @@ func (self *HandlerDemuxer) Close() error {
type HandlerMuxer struct {
av.Muxer
w io.WriteCloser
w io.WriteCloser
stage int
}
@ -54,18 +55,18 @@ 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)
CodecTypes []av.CodecType
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)
CodecTypes []av.CodecType
}
type Handlers struct {
@ -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
}
@ -167,7 +168,7 @@ func (self *Handlers) Open(uri string) (demuxer av.DemuxCloser, err error) {
}
demuxer = &HandlerDemuxer{
Demuxer: handler.ReaderDemuxer(r),
r: r,
r: r,
}
return
}
@ -196,7 +197,7 @@ func (self *Handlers) Open(uri string) (demuxer av.DemuxCloser, err error) {
}
demuxer = &HandlerDemuxer{
Demuxer: handler.ReaderDemuxer(_r),
r: r,
r: r,
}
return
}
@ -254,7 +255,7 @@ func (self *Handlers) FindCreate(uri string) (handler RegisterHandler, muxer av.
}
muxer = &HandlerMuxer{
Muxer: handler.WriterMuxer(w),
w: w,
w: w,
}
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 {
@ -30,8 +29,8 @@ func (self Filters) ModifyPacket(pkt *av.Packet, streams []av.CodecData, videoid
// Wrap origin Demuxer and Filter into a new Demuxer, when read this Demuxer filters will be called.
type FilterDemuxer struct {
av.Demuxer
Filter Filter
streams []av.CodecData
Filter Filter
streams []av.CodecData
videoidx int
audioidx int
}
@ -81,9 +80,9 @@ func (self *WaitKeyFrame) ModifyPacket(pkt *av.Packet, streams []av.CodecData, v
// Fix incorrect packet timestamps.
type FixTime struct {
zerobase time.Duration
incrbase time.Duration
lasttime time.Duration
zerobase time.Duration
incrbase time.Duration
lasttime time.Duration
StartFromZero bool // make timestamp start from zero
MakeIncrement bool // force timestamp increment
}
@ -114,14 +113,14 @@ func (self *FixTime) ModifyPacket(pkt *av.Packet, streams []av.CodecData, videoi
// Drop incorrect packets to make A/V sync.
type AVSync struct {
MaxTimeDiff time.Duration
time []time.Duration
time []time.Duration
}
func (self *AVSync) ModifyPacket(pkt *av.Packet, streams []av.CodecData, videoidx int, audioidx int) (drop bool, err error) {
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

@ -19,14 +19,14 @@ type tlSeg struct {
}
type Timeline struct {
segs []tlSeg
segs []tlSeg
headtm time.Duration
}
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,22 +1,21 @@
// Package transcoder implements Transcoder based on Muxer/Demuxer and AudioEncoder/AudioDecoder interface.
package transcode
import (
"fmt"
"time"
"github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/av/pktque"
"time"
)
var Debug bool
type tStream struct {
codec av.CodecData
timeline *pktque.Timeline
codec av.CodecData
timeline *pktque.Timeline
aencodec, adecodec av.AudioCodecData
aenc av.AudioEncoder
adec av.AudioDecoder
aenc av.AudioEncoder
adec av.AudioDecoder
}
type Options struct {
@ -27,7 +26,7 @@ type Options struct {
}
type Transcoder struct {
streams []*tStream
streams []*tStream
}
func NewTranscoder(streams []av.CodecData, options Options) (_self *Transcoder, err error) {
@ -150,8 +149,8 @@ func (self *Transcoder) Close() (err error) {
// Wrap transcoder and origin Muxer into new Muxer.
// Write to new Muxer will do transcoding automatically.
type Muxer struct {
av.Muxer // origin Muxer
Options // transcode options
av.Muxer // origin Muxer
Options // transcode options
transcoder *Transcoder
}
@ -195,7 +194,7 @@ type Demuxer struct {
av.Demuxer
Options
transcoder *Transcoder
outpkts []av.Packet
outpkts []av.Packet
}
func (self *Demuxer) prepare() (err error) {

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) {
@ -266,7 +266,7 @@ func WriteMPEG4AudioConfig(w io.Writer, config MPEG4AudioConfig) (err error) {
type CodecData struct {
ConfigBytes []byte
Config MPEG4AudioConfig
Config MPEG4AudioConfig
}
func (self CodecData) Type() av.CodecType {
@ -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

@ -5,9 +5,9 @@ import (
)
type CodecData struct {
CodecType_ av.CodecType
SampleRate_ int
SampleFormat_ av.SampleFormat
CodecType_ av.CodecType
SampleRate_ int
SampleFormat_ av.SampleFormat
ChannelLayout_ av.ChannelLayout
}
@ -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)
@ -499,9 +498,9 @@ func ParseSPS(data []byte) (self SPSInfo, err error) {
}
type CodecData struct {
Record []byte
Record []byte
RecordInfo AVCDecoderConfRecord
SPSInfo SPSInfo
SPSInfo SPSInfo
}
func (self CodecData) Type() av.CodecType {
@ -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,9 +1,8 @@
package h264parser
import (
"testing"
"encoding/hex"
"testing"
)
func TestParser(t *testing.T) {
@ -20,4 +19,3 @@ func TestParser(t *testing.T) {
nalus, ok = SplitNALUs(avccFrame)
t.Log(ok, len(nalus))
}

1
doc.go
View File

@ -1,4 +1,3 @@
// Package joy4 is a Golang audio/video library and streaming server.
// JOY4 is powerful library written in golang, well-designed interface makes a few lines
// of code can do a lot of things such as reading, writing, transcoding among

View File

@ -1,26 +1,25 @@
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 {
w io.Writer
config aacparser.MPEG4AudioConfig
w io.Writer
config aacparser.MPEG4AudioConfig
adtshdr []byte
}
func NewMuxer(w io.Writer) *Muxer {
return &Muxer{
adtshdr: make([]byte, aacparser.ADTSHeaderLength),
w: w,
w: w,
}
}
@ -52,10 +51,10 @@ func (self *Muxer) WriteTrailer() (err error) {
}
type Demuxer struct {
r *bufio.Reader
config aacparser.MPEG4AudioConfig
r *bufio.Reader
config aacparser.MPEG4AudioConfig
codecdata av.CodecData
ts time.Duration
ts time.Duration
}
func NewDemuxer(r io.Reader) *Demuxer {

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,17 +1,17 @@
package flvio
import (
"strings"
"math"
"fmt"
"time"
"github.com/datarhei/joy4/utils/bits/pio"
"math"
"strings"
"time"
)
type AMF0ParseError struct {
Offset int
Offset int
Message string
Next *AMF0ParseError
Next *AMF0ParseError
}
func (self *AMF0ParseError) Error() string {
@ -25,9 +25,9 @@ func (self *AMF0ParseError) Error() string {
func amf0ParseErr(message string, offset int, err error) error {
next, _ := err.(*AMF0ParseError)
return &AMF0ParseError{
Offset: offset,
Offset: offset,
Message: message,
Next: next,
Next: next,
}
}
@ -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

@ -21,7 +21,7 @@ func (self AVC1Desc) Tag() Tag {
return AVC1
}
const URL = Tag(0x75726c20)
const URL = Tag(0x75726c20)
func (self DataReferUrl) Tag() Tag {
return URL
@ -204,16 +204,16 @@ func (self SoundMediaInfo) Tag() Tag {
const MDAT = Tag(0x6d646174)
type Movie struct {
Header *MovieHeader
MovieExtend *MovieExtend
Tracks []*Track
Unknowns []Atom
Header *MovieHeader
MovieExtend *MovieExtend
Tracks []*Track
Unknowns []Atom
AtomPos
}
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
@ -315,28 +315,28 @@ func (self Movie) Children() (r []Atom) {
}
type MovieHeader struct {
Version uint8
Flags uint32
CreateTime time.Time
ModifyTime time.Time
TimeScale int32
Duration int32
PreferredRate float64
PreferredVolume float64
Matrix [9]int32
PreviewTime time.Time
PreviewDuration time.Time
PosterTime time.Time
SelectionTime time.Time
SelectionDuration time.Time
CurrentTime time.Time
NextTrackId int32
Version uint8
Flags uint32
CreateTime time.Time
ModifyTime time.Time
TimeScale int32
Duration int32
PreferredRate float64
PreferredVolume float64
Matrix [9]int32
PreviewTime time.Time
PreviewDuration time.Time
PosterTime time.Time
SelectionTime time.Time
SelectionDuration time.Time
CurrentTime time.Time
NextTrackId int32
AtomPos
}
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
@ -508,15 +508,15 @@ func (self MovieHeader) Children() (r []Atom) {
}
type Track struct {
Header *TrackHeader
Media *Media
Unknowns []Atom
Header *TrackHeader
Media *Media
Unknowns []Atom
AtomPos
}
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
@ -600,24 +600,24 @@ func (self Track) Children() (r []Atom) {
}
type TrackHeader struct {
Version uint8
Flags uint32
CreateTime time.Time
ModifyTime time.Time
TrackId int32
Duration int32
Layer int16
AlternateGroup int16
Volume float64
Matrix [9]int32
TrackWidth float64
TrackHeight float64
Version uint8
Flags uint32
CreateTime time.Time
ModifyTime time.Time
TrackId int32
Duration int32
Layer int16
AlternateGroup int16
Volume float64
Matrix [9]int32
TrackWidth float64
TrackHeight float64
AtomPos
}
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
@ -759,17 +759,17 @@ func (self TrackHeader) Children() (r []Atom) {
}
type HandlerRefer struct {
Version uint8
Flags uint32
Type [4]byte
SubType [4]byte
Name []byte
Version uint8
Flags uint32
Type [4]byte
SubType [4]byte
Name []byte
AtomPos
}
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
}
@ -831,16 +831,16 @@ func (self HandlerRefer) Children() (r []Atom) {
}
type Media struct {
Header *MediaHeader
Handler *HandlerRefer
Info *MediaInfo
Unknowns []Atom
Header *MediaHeader
Handler *HandlerRefer
Info *MediaInfo
Unknowns []Atom
AtomPos
}
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
@ -942,20 +942,20 @@ func (self Media) Children() (r []Atom) {
}
type MediaHeader struct {
Version uint8
Flags uint32
CreateTime time.Time
ModifyTime time.Time
TimeScale int32
Duration int32
Language int16
Quality int16
Version uint8
Flags uint32
CreateTime time.Time
ModifyTime time.Time
TimeScale int32
Duration int32
Language int16
Quality int16
AtomPos
}
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
}
@ -1048,17 +1048,17 @@ func (self MediaHeader) Children() (r []Atom) {
}
type MediaInfo struct {
Sound *SoundMediaInfo
Video *VideoMediaInfo
Data *DataInfo
Sample *SampleTable
Unknowns []Atom
Sound *SoundMediaInfo
Video *VideoMediaInfo
Data *DataInfo
Sample *SampleTable
Unknowns []Atom
AtomPos
}
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
@ -1178,14 +1178,14 @@ func (self MediaInfo) Children() (r []Atom) {
}
type DataInfo struct {
Refer *DataRefer
Unknowns []Atom
Refer *DataRefer
Unknowns []Atom
AtomPos
}
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
@ -1251,15 +1251,15 @@ func (self DataInfo) Children() (r []Atom) {
}
type DataRefer struct {
Version uint8
Flags uint32
Url *DataReferUrl
Version uint8
Flags uint32
Url *DataReferUrl
AtomPos
}
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 {
@ -1335,14 +1335,14 @@ func (self DataRefer) Children() (r []Atom) {
}
type DataReferUrl struct {
Version uint8
Flags uint32
Version uint8
Flags uint32
AtomPos
}
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
}
@ -1381,15 +1381,15 @@ func (self DataReferUrl) Children() (r []Atom) {
}
type SoundMediaInfo struct {
Version uint8
Flags uint32
Balance int16
Version uint8
Flags uint32
Balance int16
AtomPos
}
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
}
@ -1440,16 +1440,16 @@ func (self SoundMediaInfo) Children() (r []Atom) {
}
type VideoMediaInfo struct {
Version uint8
Flags uint32
GraphicsMode int16
Opcolor [3]int16
Version uint8
Flags uint32
GraphicsMode int16
Opcolor [3]int16
AtomPos
}
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) {
@ -1510,19 +1510,19 @@ func (self VideoMediaInfo) Children() (r []Atom) {
}
type SampleTable struct {
SampleDesc *SampleDesc
TimeToSample *TimeToSample
CompositionOffset *CompositionOffset
SampleToChunk *SampleToChunk
SyncSample *SyncSample
ChunkOffset *ChunkOffset
SampleSize *SampleSize
SampleDesc *SampleDesc
TimeToSample *TimeToSample
CompositionOffset *CompositionOffset
SampleToChunk *SampleToChunk
SyncSample *SyncSample
ChunkOffset *ChunkOffset
SampleSize *SampleSize
AtomPos
}
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
}
@ -1680,16 +1680,16 @@ func (self SampleTable) Children() (r []Atom) {
}
type SampleDesc struct {
Version uint8
AVC1Desc *AVC1Desc
MP4ADesc *MP4ADesc
Unknowns []Atom
Version uint8
AVC1Desc *AVC1Desc
MP4ADesc *MP4ADesc
Unknowns []Atom
AtomPos
}
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
@ -1797,22 +1797,22 @@ func (self SampleDesc) Children() (r []Atom) {
}
type MP4ADesc struct {
DataRefIdx int16
Version int16
RevisionLevel int16
Vendor int32
NumberOfChannels int16
SampleSize int16
CompressionId int16
SampleRate float64
Conf *ElemStreamDesc
Unknowns []Atom
DataRefIdx int16
Version int16
RevisionLevel int16
Vendor int32
NumberOfChannels int16
SampleSize int16
CompressionId int16
SampleRate float64
Conf *ElemStreamDesc
Unknowns []Atom
AtomPos
}
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
@ -1956,28 +1956,28 @@ func (self MP4ADesc) Children() (r []Atom) {
}
type AVC1Desc struct {
DataRefIdx int16
Version int16
Revision int16
Vendor int32
TemporalQuality int32
SpatialQuality int32
Width int16
Height int16
HorizontalResolution float64
VorizontalResolution float64
FrameCount int16
CompressorName [32]byte
Depth int16
ColorTableId int16
Conf *AVC1Conf
Unknowns []Atom
DataRefIdx int16
Version int16
Revision int16
Vendor int32
TemporalQuality int32
SpatialQuality int32
Width int16
Height int16
HorizontalResolution float64
VorizontalResolution float64
FrameCount int16
CompressorName [32]byte
Depth int16
ColorTableId int16
Conf *AVC1Conf
Unknowns []Atom
AtomPos
}
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
@ -2175,13 +2175,13 @@ func (self AVC1Desc) Children() (r []Atom) {
}
type AVC1Conf struct {
Data []byte
Data []byte
AtomPos
}
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
}
@ -2207,15 +2207,15 @@ func (self AVC1Conf) Children() (r []Atom) {
}
type TimeToSample struct {
Version uint8
Flags uint32
Entries []TimeToSampleEntry
Version uint8
Flags uint32
Entries []TimeToSampleEntry
AtomPos
}
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) {
@ -2274,8 +2274,8 @@ func (self TimeToSample) Children() (r []Atom) {
}
type TimeToSampleEntry struct {
Count uint32
Duration uint32
Count uint32
Duration uint32
}
func GetTimeToSampleEntry(b []byte) (self TimeToSampleEntry) {
@ -2291,15 +2291,15 @@ func PutTimeToSampleEntry(b []byte, self TimeToSampleEntry) {
const LenTimeToSampleEntry = 8
type SampleToChunk struct {
Version uint8
Flags uint32
Entries []SampleToChunkEntry
Version uint8
Flags uint32
Entries []SampleToChunkEntry
AtomPos
}
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) {
@ -2358,9 +2358,9 @@ func (self SampleToChunk) Children() (r []Atom) {
}
type SampleToChunkEntry struct {
FirstChunk uint32
SamplesPerChunk uint32
SampleDescId uint32
FirstChunk uint32
SamplesPerChunk uint32
SampleDescId uint32
}
func GetSampleToChunkEntry(b []byte) (self SampleToChunkEntry) {
@ -2378,15 +2378,15 @@ func PutSampleToChunkEntry(b []byte, self SampleToChunkEntry) {
const LenSampleToChunkEntry = 12
type CompositionOffset struct {
Version uint8
Flags uint32
Entries []CompositionOffsetEntry
Version uint8
Flags uint32
Entries []CompositionOffsetEntry
AtomPos
}
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) {
@ -2445,8 +2445,8 @@ func (self CompositionOffset) Children() (r []Atom) {
}
type CompositionOffsetEntry struct {
Count uint32
Offset uint32
Count uint32
Offset uint32
}
func GetCompositionOffsetEntry(b []byte) (self CompositionOffsetEntry) {
@ -2462,15 +2462,15 @@ func PutCompositionOffsetEntry(b []byte, self CompositionOffsetEntry) {
const LenCompositionOffsetEntry = 8
type SyncSample struct {
Version uint8
Flags uint32
Entries []uint32
Version uint8
Flags uint32
Entries []uint32
AtomPos
}
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) {
@ -2529,15 +2529,15 @@ func (self SyncSample) Children() (r []Atom) {
}
type ChunkOffset struct {
Version uint8
Flags uint32
Entries []uint32
Version uint8
Flags uint32
Entries []uint32
AtomPos
}
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) {
@ -2596,15 +2596,15 @@ func (self ChunkOffset) Children() (r []Atom) {
}
type MovieFrag struct {
Header *MovieFragHeader
Tracks []*TrackFrag
Unknowns []Atom
Header *MovieFragHeader
Tracks []*TrackFrag
Unknowns []Atom
AtomPos
}
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
@ -2688,15 +2688,15 @@ func (self MovieFrag) Children() (r []Atom) {
}
type MovieFragHeader struct {
Version uint8
Flags uint32
Seqnum uint32
Version uint8
Flags uint32
Seqnum uint32
AtomPos
}
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
}
@ -2744,16 +2744,16 @@ func (self MovieFragHeader) Children() (r []Atom) {
}
type TrackFrag struct {
Header *TrackFragHeader
DecodeTime *TrackFragDecodeTime
Run *TrackFragRun
Unknowns []Atom
Header *TrackFragHeader
DecodeTime *TrackFragDecodeTime
Run *TrackFragRun
Unknowns []Atom
AtomPos
}
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
@ -2855,14 +2855,14 @@ func (self TrackFrag) Children() (r []Atom) {
}
type MovieExtend struct {
Tracks []*TrackExtend
Unknowns []Atom
Tracks []*TrackExtend
Unknowns []Atom
AtomPos
}
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
@ -2928,19 +2928,19 @@ func (self MovieExtend) Children() (r []Atom) {
}
type TrackExtend struct {
Version uint8
Flags uint32
TrackId uint32
DefaultSampleDescIdx uint32
DefaultSampleDuration uint32
DefaultSampleSize uint32
DefaultSampleFlags uint32
Version uint8
Flags uint32
TrackId uint32
DefaultSampleDescIdx uint32
DefaultSampleDuration uint32
DefaultSampleSize uint32
DefaultSampleFlags uint32
AtomPos
}
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
}
@ -3024,16 +3024,16 @@ func (self TrackExtend) Children() (r []Atom) {
}
type SampleSize struct {
Version uint8
Flags uint32
SampleSize uint32
Entries []uint32
Version uint8
Flags uint32
SampleSize uint32
Entries []uint32
AtomPos
}
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) {
@ -3110,17 +3110,17 @@ func (self SampleSize) Children() (r []Atom) {
}
type TrackFragRun struct {
Version uint8
Flags uint32
DataOffset uint32
FirstSampleFlags uint32
Entries []TrackFragRunEntry
Version uint8
Flags uint32
DataOffset uint32
FirstSampleFlags uint32
Entries []TrackFragRunEntry
AtomPos
}
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
}
@ -3280,10 +3280,10 @@ func (self TrackFragRun) Children() (r []Atom) {
}
type TrackFragRunEntry struct {
Duration uint32
Size uint32
Flags uint32
Cts uint32
Duration uint32
Size uint32
Flags uint32
Cts uint32
}
func GetTrackFragRunEntry(b []byte) (self TrackFragRunEntry) {
@ -3303,19 +3303,19 @@ func PutTrackFragRunEntry(b []byte, self TrackFragRunEntry) {
const LenTrackFragRunEntry = 16
type TrackFragHeader struct {
Version uint8
Flags uint32
BaseDataOffset uint64
StsdId uint32
DefaultDuration uint32
DefaultSize uint32
DefaultFlags uint32
Version uint8
Flags uint32
BaseDataOffset uint64
StsdId uint32
DefaultDuration uint32
DefaultSize uint32
DefaultFlags uint32
AtomPos
}
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
}
@ -3459,15 +3459,15 @@ func (self TrackFragHeader) Children() (r []Atom) {
}
type TrackFragDecodeTime struct {
Version uint8
Flags uint32
Time time.Time
Version uint8
Flags uint32
Time time.Time
AtomPos
}
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 main
import (
"strings"
"fmt"
"os"
"go/ast"
"go/parser"
"go/token"
"go/printer"
"go/token"
"os"
"strings"
)
func getexprs(e ast.Expr) string {
@ -37,7 +36,7 @@ func genatomdecl(origfn *ast.FuncDecl, origname, origtag string) (decls []ast.De
if typ == "_unknowns" {
fieldslist.List = append(fieldslist.List, &ast.Field{
Names: []*ast.Ident{ast.NewIdent("Unknowns")},
Type: ast.NewIdent("[]Atom"),
Type: ast.NewIdent("[]Atom"),
})
}
continue
@ -67,24 +66,24 @@ func genatomdecl(origfn *ast.FuncDecl, origname, origtag string) (decls []ast.De
case "bytesleft":
typ = "[]byte"
case "bytes":
typ = "["+name2+"]byte"
typ = "[" + name2 + "]byte"
case "uint24":
typ = "uint32"
case "time64", "time32":
typ = "time.Time"
case "atom":
typ = "*"+name2
typ = "*" + name2
case "atoms":
typ = "[]*"+name2
typ = "[]*" + name2
case "slice":
typ = "[]"+name2
typ = "[]" + name2
case "array":
typ = "["+len3+"]"+name2
typ = "[" + len3 + "]" + name2
}
fieldslist.List = append(fieldslist.List, &ast.Field{
Names: []*ast.Ident{ast.NewIdent(name)},
Type: ast.NewIdent(typ),
Type: ast.NewIdent(typ),
})
}
@ -135,7 +134,7 @@ func typegetlen(typ string) (n int) {
func typegetlens(typ string) string {
n := typegetlen(typ)
if n == 0 {
return "Len"+typ
return "Len" + typ
} else {
return fmt.Sprint(n)
}
@ -187,7 +186,7 @@ func typegetputfn(typ string) (fn string) {
case "fixed16":
fn = "PutFixed16"
default:
fn = "Put"+typ
fn = "Put" + typ
}
return
}
@ -218,7 +217,7 @@ func typegetgetfn(typ string) (fn string) {
case "fixed16":
fn = "GetFixed16"
default:
fn = "Get"+typ
fn = "Get" + typ
}
return
}
@ -237,14 +236,14 @@ func addn(n int) (stmts []ast.Stmt) {
return addns(fmt.Sprint(n))
}
func simplecall(fun string, args... string) *ast.ExprStmt {
func simplecall(fun string, args ...string) *ast.ExprStmt {
_args := []ast.Expr{}
for _, s := range args {
_args = append(_args, ast.NewIdent(s))
}
return &ast.ExprStmt{
X: &ast.CallExpr{
Fun: ast.NewIdent(fun),
Fun: ast.NewIdent(fun),
Args: _args,
},
}
@ -283,7 +282,7 @@ func newdecl(origname, name string, params, res []*ast.Field, stmts []ast.Stmt)
List: []*ast.Field{
&ast.Field{
Names: []*ast.Ident{ast.NewIdent("self")},
Type: ast.NewIdent(origname),
Type: ast.NewIdent(origname),
},
},
},
@ -319,7 +318,7 @@ func getstructputgetlenfn(origfn *ast.FuncDecl, origname string) (decls []ast.De
getstmts = append(getstmts, &ast.ReturnStmt{})
decls = append(decls, &ast.FuncDecl{
Name: ast.NewIdent("Get"+origname),
Name: ast.NewIdent("Get" + origname),
Type: &ast.FuncType{
Params: &ast.FieldList{
List: []*ast.Field{
@ -336,7 +335,7 @@ func getstructputgetlenfn(origfn *ast.FuncDecl, origname string) (decls []ast.De
})
decls = append(decls, &ast.FuncDecl{
Name: ast.NewIdent("Put"+origname),
Name: ast.NewIdent("Put" + origname),
Type: &ast.FuncType{
Params: &ast.FieldList{
List: []*ast.Field{
@ -352,7 +351,7 @@ func getstructputgetlenfn(origfn *ast.FuncDecl, origname string) (decls []ast.De
Tok: token.CONST,
Specs: []ast.Spec{
&ast.ValueSpec{
Names: []*ast.Ident{ast.NewIdent("Len"+origname)},
Names: []*ast.Ident{ast.NewIdent("Len" + origname)},
Values: []ast.Expr{ast.NewIdent(fmt.Sprint(totlen))},
},
},
@ -371,7 +370,7 @@ func cc4decls(name string) (decls []ast.Decl) {
},
Values: []ast.Expr{
&ast.CallExpr{
Fun: ast.NewIdent("Tag"),
Fun: ast.NewIdent("Tag"),
Args: []ast.Expr{&ast.BasicLit{Kind: token.INT, Value: fmt.Sprintf("0x%x", []byte(name))}},
},
},
@ -431,7 +430,7 @@ func getatommarshalfn(origfn *ast.FuncDecl,
callmarshal := func(name string) (stmts []ast.Stmt) {
callexpr := &ast.CallExpr{
Fun: ast.NewIdent(name+".Marshal"),
Fun: ast.NewIdent(name + ".Marshal"),
Args: []ast.Expr{ast.NewIdent("b[n:]")},
}
assign := &ast.AssignStmt{
@ -446,7 +445,7 @@ func getatommarshalfn(origfn *ast.FuncDecl,
callputstruct := func(typ, name string) (stmts []ast.Stmt) {
stmts = append(stmts, &ast.ExprStmt{
X: &ast.CallExpr{
Fun: ast.NewIdent(typegetputfn(typ)),
Fun: ast.NewIdent(typegetputfn(typ)),
Args: []ast.Expr{ast.NewIdent("b[n:]"), ast.NewIdent(name)},
},
})
@ -459,7 +458,7 @@ func getatommarshalfn(origfn *ast.FuncDecl,
}
calllenstruct := func(typ, name string) (stmts []ast.Stmt) {
inc := typegetlens(typ)+"*len("+name+")"
inc := typegetlens(typ) + "*len(" + name + ")"
stmts = append(stmts, &ast.AssignStmt{
Tok: token.ADD_ASSIGN,
Lhs: []ast.Expr{ast.NewIdent("n")},
@ -470,7 +469,7 @@ func getatommarshalfn(origfn *ast.FuncDecl,
calllen := func(name string) (stmts []ast.Stmt) {
callexpr := &ast.CallExpr{
Fun: ast.NewIdent(name+".Len"),
Fun: ast.NewIdent(name + ".Len"),
Args: []ast.Expr{},
}
assign := &ast.AssignStmt{
@ -484,13 +483,13 @@ func getatommarshalfn(origfn *ast.FuncDecl,
foreach := func(name, field string, block []ast.Stmt) (stmts []ast.Stmt) {
rangestmt := &ast.RangeStmt{
Key: ast.NewIdent("_"),
Key: ast.NewIdent("_"),
Value: ast.NewIdent(name),
Body: &ast.BlockStmt{
List: block,
},
Tok: token.DEFINE,
X: ast.NewIdent(field),
X: ast.NewIdent(field),
}
stmts = append(stmts, rangestmt)
return
@ -511,7 +510,7 @@ func getatommarshalfn(origfn *ast.FuncDecl,
List: block,
},
Tok: token.DEFINE,
X: ast.NewIdent(field),
X: ast.NewIdent(field),
}
stmts = append(stmts, rangestmt)
return
@ -574,7 +573,7 @@ func getatommarshalfn(origfn *ast.FuncDecl,
unmarshalatom := func(typ, init string) (stmts []ast.Stmt) {
return []ast.Stmt{
&ast.AssignStmt{Tok: token.DEFINE,
Lhs: []ast.Expr{ast.NewIdent("atom")}, Rhs: []ast.Expr{ast.NewIdent("&"+typ+"{"+init+"}")},
Lhs: []ast.Expr{ast.NewIdent("atom")}, Rhs: []ast.Expr{ast.NewIdent("&" + typ + "{" + init + "}")},
},
&ast.IfStmt{
Init: &ast.AssignStmt{
@ -591,10 +590,10 @@ func getatommarshalfn(origfn *ast.FuncDecl,
unmrashalatoms := func() (stmts []ast.Stmt) {
blocks := []ast.Stmt{}
blocks = append(blocks, &ast.AssignStmt{ Tok: token.DEFINE, Lhs: []ast.Expr{ast.NewIdent("tag")},
blocks = append(blocks, &ast.AssignStmt{Tok: token.DEFINE, Lhs: []ast.Expr{ast.NewIdent("tag")},
Rhs: []ast.Expr{ast.NewIdent("Tag(pio.U32BE(b[n+4:]))")},
})
blocks = append(blocks, &ast.AssignStmt{ Tok: token.DEFINE, Lhs: []ast.Expr{ast.NewIdent("size")},
blocks = append(blocks, &ast.AssignStmt{Tok: token.DEFINE, Lhs: []ast.Expr{ast.NewIdent("size")},
Rhs: []ast.Expr{ast.NewIdent("int(pio.U32BE(b[n:]))")},
})
blocks = append(blocks, &ast.IfStmt{
@ -614,7 +613,7 @@ func getatommarshalfn(origfn *ast.FuncDecl,
}
for i, atom := range atomarrnames {
selfatom := "self."+atom
selfatom := "self." + atom
cases = append(cases, &ast.CaseClause{
List: []ast.Expr{ast.NewIdent(strings.ToUpper(struct2tag(atomarrtypes[i])))},
Body: []ast.Stmt{&ast.BlockStmt{
@ -635,7 +634,7 @@ func getatommarshalfn(origfn *ast.FuncDecl,
}
blocks = append(blocks, &ast.SwitchStmt{
Tag: ast.NewIdent("tag"),
Tag: ast.NewIdent("tag"),
Body: &ast.BlockStmt{List: cases},
})
@ -659,9 +658,9 @@ func getatommarshalfn(origfn *ast.FuncDecl,
ifnotnil := func(name string, block []ast.Stmt) (stmts []ast.Stmt) {
stmts = append(stmts, &ast.IfStmt{
Cond: &ast.BinaryExpr{
X: ast.NewIdent(name),
X: ast.NewIdent(name),
Op: token.NEQ,
Y: ast.NewIdent("nil"),
Y: ast.NewIdent("nil"),
},
Body: &ast.BlockStmt{List: block},
})
@ -693,9 +692,9 @@ func getatommarshalfn(origfn *ast.FuncDecl,
checkcurlen := func(inc, debug string) (stmts []ast.Stmt) {
stmts = append(stmts, &ast.IfStmt{
Cond: &ast.BinaryExpr{
X: ast.NewIdent("len(b)"),
X: ast.NewIdent("len(b)"),
Op: token.LSS,
Y: ast.NewIdent("n+"+inc),
Y: ast.NewIdent("n+" + inc),
},
Body: &ast.BlockStmt{List: parseerrreturn(debug)},
})
@ -710,20 +709,20 @@ func getatommarshalfn(origfn *ast.FuncDecl,
}
checkstructlendo := func(typ, name, debug string,
foreach func(string,[]ast.Stmt)[]ast.Stmt,
foreach func(string, []ast.Stmt) []ast.Stmt,
) (stmts []ast.Stmt) {
inc := typegetlens(typ)+"*len("+name+")"
inc := typegetlens(typ) + "*len(" + name + ")"
stmts = append(stmts, checkcurlen(inc, debug)...)
stmts = append(stmts, foreach(name, append(
[]ast.Stmt{
&ast.AssignStmt{
Tok: token.ASSIGN,
Lhs: []ast.Expr{
ast.NewIdent(name+"[i]"),
ast.NewIdent(name + "[i]"),
},
Rhs: []ast.Expr{
&ast.CallExpr{
Fun: ast.NewIdent(typegetgetfn(typ)),
Fun: ast.NewIdent(typegetgetfn(typ)),
Args: []ast.Expr{ast.NewIdent("b[n:]")},
},
},
@ -1054,4 +1053,3 @@ func main() {
genatoms(os.Args[2], os.Args[3])
}
}

View File

@ -434,4 +434,3 @@ func tfdt_TrackFragDecodeTime() {
}
}))
}

View File

@ -1,20 +1,19 @@
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 {
Debug string
Debug string
Offset int
prev *ParseError
prev *ParseError
}
func (self *ParseError) Error() string {
@ -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,21 +88,21 @@ 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
}
type AtomPos struct {
Offset int
Size int
Size int
}
func (self AtomPos) Pos() (int,int) {
func (self AtomPos) Pos() (int, int) {
return self.Offset, self.Size
}
@ -190,7 +189,7 @@ const (
type ElemStreamDesc struct {
DecConfig []byte
TrackId uint16
TrackId uint16
AtomPos
}
@ -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,27 +1,27 @@
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 {
w io.WriteSeeker
bufw *bufio.Writer
wpos int64
streams []*Stream
w io.WriteSeeker
bufw *bufio.Writer
wpos int64
streams []*Stream
}
func NewMuxer(w io.WriteSeeker) *Muxer {
return &Muxer{
w: w,
w: w,
bufw: bufio.NewWriterSize(w, pio.RecommendBufioSize),
}
}
@ -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

@ -17,7 +17,7 @@ type Stream struct {
timeScale int64
duration int64
muxer *Muxer
muxer *Muxer
demuxer *Demuxer
sample *mp4io.SampleTable
@ -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

@ -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
@ -39,7 +39,7 @@ const (
type Client struct {
DebugRtsp bool
DebugRtp bool
DebugRtp bool
Headers []string
SkipErrRtpBlock bool
@ -52,20 +52,20 @@ type Client struct {
stage int
setupIdx []int
setupMap []int
setupIdx []int
setupMap []int
authHeaders func(method string) []string
url *url.URL
conn *connWithTimeout
url *url.URL
conn *connWithTimeout
brconn *bufio.Reader
requestUri string
cseq uint
streams []*Stream
requestUri string
cseq uint
streams []*Stream
streamsintf []av.CodecData
session string
body io.Reader
session string
body io.Reader
}
type Request struct {
@ -76,7 +76,7 @@ type Request struct {
type Response struct {
StatusCode int
Headers textproto.MIMEHeader
Headers textproto.MIMEHeader
ContentLength int
Body []byte
@ -105,12 +105,12 @@ func DialTimeout(uri string, timeout time.Duration) (self *Client, err error) {
connt := &connWithTimeout{Conn: conn}
self = &Client{
conn: connt,
brconn: bufio.NewReaderSize(connt, 256),
url: URL,
requestUri: u2.String(),
DebugRtp: DebugRtp,
DebugRtsp: DebugRtsp,
conn: connt,
brconn: bufio.NewReaderSize(connt, 256),
url: URL,
requestUri: u2.String(),
DebugRtp: DebugRtp,
DebugRtsp: DebugRtsp,
SkipErrRtpBlock: SkipErrRtpBlock,
}
return
@ -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
@ -830,16 +830,16 @@ func (self *Stream) handleH264Payload(timestamp uint32, packet []byte) (err erro
*/
switch {
case naluType >= 1 && naluType <= 5:
if naluType == 5 {
self.pkt.IsKeyFrame = true
}
self.gotpkt = true
// raw nalu to avcc
b := make([]byte, 4+len(packet))
pio.PutU32BE(b[0:4], uint32(len(packet)))
copy(b[4:], packet)
self.pkt.Data = b
self.timestamp = timestamp
if naluType == 5 {
self.pkt.IsKeyFrame = true
}
self.gotpkt = true
// raw nalu to avcc
b := make([]byte, 4+len(packet))
pio.PutU32BE(b[0:4], uint32(len(packet)))
copy(b[4:], packet)
self.pkt.Data = b
self.timestamp = timestamp
case naluType == 7: // sps
if self.client != nil && self.client.DebugRtp {
@ -940,30 +940,30 @@ func (self *Stream) handleH264Payload(timestamp uint32, packet []byte) (err erro
case naluType == 24: // STAP-A
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RTP Header |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|STAP-A NAL HDR | NALU 1 Size | NALU 1 HDR |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NALU 1 Data |
: :
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | NALU 2 Size | NALU 2 HDR |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NALU 2 Data |
: :
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| :...OPTIONAL RTP padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RTP Header |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|STAP-A NAL HDR | NALU 1 Size | NALU 1 HDR |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NALU 1 Data |
: :
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | NALU 2 Size | NALU 2 HDR |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NALU 2 Data |
: :
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| :...OPTIONAL RTP padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 7. An example of an RTP packet including an STAP-A
containing two single-time aggregation units
Figure 7. An example of an RTP packet including an STAP-A
containing two single-time aggregation units
*/
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
@ -1158,11 +1158,11 @@ func (self *Client) handleBlock(block []byte) (pkt av.Packet, ok bool, err error
if stream.gotpkt {
/*
TODO: sync AV by rtcp NTP timestamp
TODO: handle timestamp overflow
https://tools.ietf.org/html/rfc3550
A receiver can then synchronize presentation of the audio and video packets by relating
their RTP timestamps using the timestamp pairs in RTCP SR packets.
TODO: sync AV by rtcp NTP timestamp
TODO: handle timestamp overflow
https://tools.ietf.org/html/rfc3550
A receiver can then synchronize presentation of the audio and video packets by relating
their RTP timestamps using the timestamp pairs in RTCP SR packets.
*/
if stream.firsttimestamp == 0 {
stream.firsttimestamp = stream.timestamp
@ -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

@ -19,11 +19,10 @@ type Stream struct {
spsChanged bool
ppsChanged bool
gotpkt bool
pkt av.Packet
timestamp uint32
gotpkt bool
pkt av.Packet
timestamp uint32
firsttimestamp uint32
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 {
@ -28,7 +28,7 @@ type Demuxer struct {
func NewDemuxer(r io.Reader) *Demuxer {
return &Demuxer{
tshdr: make([]byte, 188),
r: bufio.NewReaderSize(r, pio.RecommendBufioSize),
r: bufio.NewReaderSize(r, pio.RecommendBufioSize),
}
}
@ -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
}
}
@ -192,13 +192,13 @@ func (self *Stream) addPacket(payload []byte, timedelta time.Duration) {
demuxer := self.demuxer
pkt := av.Packet{
Idx: int8(self.idx),
Idx: int8(self.idx),
IsKeyFrame: self.iskeyframe,
Time: dts+timedelta,
Data: payload,
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 {
@ -12,16 +12,15 @@ type Stream struct {
demuxer *Demuxer
muxer *Muxer
pid uint16
pid uint16
streamId uint8
streamType uint8
tsw *tsio.TSWriter
idx int
tsw *tsio.TSWriter
idx int
iskeyframe bool
pts, dts time.Duration
data []byte
datalen int
pts, dts time.Duration
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)
@ -499,9 +498,9 @@ func FillPESHeader(h []byte, streamid uint8, datalen int, pts, dts time.Duration
}
type TSWriter struct {
w io.Writer
w io.Writer
ContinuityCounter uint
tshdr []byte
tshdr []byte
}
func NewTSWriter(pid uint16) *TSWriter {
@ -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

@ -6,13 +6,13 @@ import (
type Reader struct {
buf [][]byte
R io.ReadSeeker
R io.ReadSeeker
}
func NewReaderSize(r io.ReadSeeker, size int) *Reader {
buf := make([]byte, size*2)
return &Reader{
R: r,
R: r,
buf: [][]byte{buf[0:size], buf[size:]},
}
}
@ -20,4 +20,3 @@ func NewReaderSize(r io.ReadSeeker, size int) *Reader {
func (self *Reader) ReadAt(b []byte, off int64) (n int, err error) {
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
import (
@ -6,7 +5,7 @@ import (
)
func ExampleVec() {
vec := [][]byte{[]byte{1,2,3}, []byte{4,5,6,7,8,9}, []byte{10,11,12,13}}
vec := [][]byte{[]byte{1, 2, 3}, []byte{4, 5, 6, 7, 8, 9}, []byte{10, 11, 12, 13}}
println(VecLen(vec))
vec = VecSlice(vec, 1, -1)

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)
}