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

View File

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

View File

@ -1,14 +1,15 @@
package avutil package avutil
import ( import (
"io"
"strings"
"fmt"
"bytes" "bytes"
"github.com/datarhei/joy4/av" "fmt"
"io"
"net/url" "net/url"
"os" "os"
"path" "path"
"strings"
"github.com/datarhei/joy4/av"
) )
type HandlerDemuxer struct { type HandlerDemuxer struct {
@ -22,7 +23,7 @@ func (self *HandlerDemuxer) Close() error {
type HandlerMuxer struct { type HandlerMuxer struct {
av.Muxer av.Muxer
w io.WriteCloser w io.WriteCloser
stage int stage int
} }
@ -54,18 +55,18 @@ func (self *HandlerMuxer) Close() (err error) {
} }
type RegisterHandler struct { type RegisterHandler struct {
Ext string Ext string
ReaderDemuxer func(io.Reader)av.Demuxer ReaderDemuxer func(io.Reader) av.Demuxer
WriterMuxer func(io.Writer)av.Muxer WriterMuxer func(io.Writer) av.Muxer
UrlMuxer func(string)(bool,av.MuxCloser,error) UrlMuxer func(string) (bool, av.MuxCloser, error)
UrlDemuxer func(string)(bool,av.DemuxCloser,error) UrlDemuxer func(string) (bool, av.DemuxCloser, error)
UrlReader func(string)(bool,io.ReadCloser,error) UrlReader func(string) (bool, io.ReadCloser, error)
Probe func([]byte)bool Probe func([]byte) bool
AudioEncoder func(av.CodecType)(av.AudioEncoder,error) AudioEncoder func(av.CodecType) (av.AudioEncoder, error)
AudioDecoder func(av.AudioCodecData)(av.AudioDecoder,error) AudioDecoder func(av.AudioCodecData) (av.AudioDecoder, error)
ServerDemuxer func(string)(bool,av.DemuxCloser,error) ServerDemuxer func(string) (bool, av.DemuxCloser, error)
ServerMuxer func(string)(bool,av.MuxCloser,error) ServerMuxer func(string) (bool, av.MuxCloser, error)
CodecTypes []av.CodecType CodecTypes []av.CodecType
} }
type Handlers struct { 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 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 return
} }
@ -167,7 +168,7 @@ func (self *Handlers) Open(uri string) (demuxer av.DemuxCloser, err error) {
} }
demuxer = &HandlerDemuxer{ demuxer = &HandlerDemuxer{
Demuxer: handler.ReaderDemuxer(r), Demuxer: handler.ReaderDemuxer(r),
r: r, r: r,
} }
return return
} }
@ -196,7 +197,7 @@ func (self *Handlers) Open(uri string) (demuxer av.DemuxCloser, err error) {
} }
demuxer = &HandlerDemuxer{ demuxer = &HandlerDemuxer{
Demuxer: handler.ReaderDemuxer(_r), Demuxer: handler.ReaderDemuxer(_r),
r: r, r: r,
} }
return return
} }
@ -254,7 +255,7 @@ func (self *Handlers) FindCreate(uri string) (handler RegisterHandler, muxer av.
} }
muxer = &HandlerMuxer{ muxer = &HandlerMuxer{
Muxer: handler.WriterMuxer(w), Muxer: handler.WriterMuxer(w),
w: w, w: w,
} }
return return
} }

View File

@ -1,10 +1,9 @@
// Package pktque provides packet Filter interface and structures used by other components. // Package pktque provides packet Filter interface and structures used by other components.
package pktque package pktque
import ( import (
"time"
"github.com/datarhei/joy4/av" "github.com/datarhei/joy4/av"
"time"
) )
type Filter interface { 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. // Wrap origin Demuxer and Filter into a new Demuxer, when read this Demuxer filters will be called.
type FilterDemuxer struct { type FilterDemuxer struct {
av.Demuxer av.Demuxer
Filter Filter Filter Filter
streams []av.CodecData streams []av.CodecData
videoidx int videoidx int
audioidx int audioidx int
} }
@ -81,9 +80,9 @@ func (self *WaitKeyFrame) ModifyPacket(pkt *av.Packet, streams []av.CodecData, v
// Fix incorrect packet timestamps. // Fix incorrect packet timestamps.
type FixTime struct { type FixTime struct {
zerobase time.Duration zerobase time.Duration
incrbase time.Duration incrbase time.Duration
lasttime time.Duration lasttime time.Duration
StartFromZero bool // make timestamp start from zero StartFromZero bool // make timestamp start from zero
MakeIncrement bool // force timestamp increment 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. // Drop incorrect packets to make A/V sync.
type AVSync struct { type AVSync struct {
MaxTimeDiff time.Duration 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) { func (self *AVSync) ModifyPacket(pkt *av.Packet, streams []av.CodecData, videoidx int, audioidx int) (drop bool, err error) {
if self.time == nil { if self.time == nil {
self.time = make([]time.Duration, len(streams)) self.time = make([]time.Duration, len(streams))
if self.MaxTimeDiff == 0 { 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 return
} }

View File

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

View File

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

View File

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

View File

@ -1,12 +1,12 @@
package aacparser package aacparser
import ( import (
"github.com/datarhei/joy4/utils/bits"
"github.com/datarhei/joy4/av"
"time"
"fmt"
"bytes" "bytes"
"fmt"
"github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/utils/bits"
"io" "io"
"time"
) )
// copied from libavcodec/mpeg4audio.h // copied from libavcodec/mpeg4audio.h
@ -83,12 +83,12 @@ These are the channel configurations:
var chanConfigTable = []av.ChannelLayout{ var chanConfigTable = []av.ChannelLayout{
0, 0,
av.CH_FRONT_CENTER, av.CH_FRONT_CENTER,
av.CH_FRONT_LEFT|av.CH_FRONT_RIGHT, 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_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_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_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_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_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) { 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 { type CodecData struct {
ConfigBytes []byte ConfigBytes []byte
Config MPEG4AudioConfig Config MPEG4AudioConfig
} }
func (self CodecData) Type() av.CodecType { func (self CodecData) Type() av.CodecType {
@ -308,4 +308,3 @@ func NewCodecDataFromMPEG4AudioConfigBytes(config []byte) (self CodecData, err e
} }
return return
} }

View File

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

View File

@ -5,9 +5,9 @@ import (
) )
type CodecData struct { type CodecData struct {
CodecType_ av.CodecType CodecType_ av.CodecType
SampleRate_ int SampleRate_ int
SampleFormat_ av.SampleFormat SampleFormat_ av.SampleFormat
ChannelLayout_ av.ChannelLayout ChannelLayout_ av.ChannelLayout
} }
@ -26,4 +26,3 @@ func (self CodecData) ChannelLayout() av.ChannelLayout {
func (self CodecData) SampleRate() int { func (self CodecData) SampleRate() int {
return self.SampleRate_ return self.SampleRate_
} }

View File

@ -1,12 +1,11 @@
package h264parser package h264parser
import ( import (
"bytes"
"fmt"
"github.com/datarhei/joy4/av" "github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/utils/bits" "github.com/datarhei/joy4/utils/bits"
"github.com/datarhei/joy4/utils/bits/pio" "github.com/datarhei/joy4/utils/bits/pio"
"fmt"
"bytes"
) )
const ( 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. 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 StartCodeBytes = []byte{0, 0, 1}
var AUDBytes = []byte{0,0,0,1,0x9,0xf0,0,0,0,1} // AUD var AUDBytes = []byte{0, 0, 0, 1, 0x9, 0xf0, 0, 0, 0, 1} // AUD
func CheckNALUsType(b []byte) (typ int) { func CheckNALUsType(b []byte) (typ int) {
_, typ = SplitNALUs(b) _, typ = SplitNALUs(b)
@ -499,9 +498,9 @@ func ParseSPS(data []byte) (self SPSInfo, err error) {
} }
type CodecData struct { type CodecData struct {
Record []byte Record []byte
RecordInfo AVCDecoderConfRecord RecordInfo AVCDecoderConfRecord
SPSInfo SPSInfo SPSInfo SPSInfo
} }
func (self CodecData) Type() av.CodecType { 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.AVCProfileIndication = b[1]
self.ProfileCompatibility = b[2] self.ProfileCompatibility = b[2]
self.AVCLevelIndication = b[3] self.AVCLevelIndication = b[3]
self.LengthSizeMinusOne = b[4]&0x03 self.LengthSizeMinusOne = b[4] & 0x03
spscount := int(b[5]&0x1f) spscount := int(b[5] & 0x1f)
n += 6 n += 6
for i := 0; i < spscount; i++ { 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) { func (self AVCDecoderConfRecord) Len() (n int) {
n = 7 n = 7
for _, sps := range self.SPS { for _, sps := range self.SPS {
n += 2+len(sps) n += 2 + len(sps)
} }
for _, pps := range self.PPS { for _, pps := range self.PPS {
n += 2+len(pps) n += 2 + len(pps)
} }
return return
} }
@ -651,8 +650,8 @@ func (self AVCDecoderConfRecord) Marshal(b []byte) (n int) {
b[1] = self.AVCProfileIndication b[1] = self.AVCProfileIndication
b[2] = self.ProfileCompatibility b[2] = self.ProfileCompatibility
b[3] = self.AVCLevelIndication b[3] = self.AVCLevelIndication
b[4] = self.LengthSizeMinusOne|0xfc b[4] = self.LengthSizeMinusOne | 0xfc
b[5] = uint8(len(self.SPS))|0xe0 b[5] = uint8(len(self.SPS)) | 0xe0
n += 6 n += 6
for _, sps := range self.SPS { for _, sps := range self.SPS {
@ -690,7 +689,7 @@ func (self SliceType) String() string {
} }
const ( const (
SLICE_P = iota+1 SLICE_P = iota + 1
SLICE_B SLICE_B
SLICE_I SLICE_I
) )
@ -702,9 +701,9 @@ func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, err error) {
return return
} }
nal_unit_type := packet[0]&0x1f nal_unit_type := packet[0] & 0x1f
switch nal_unit_type { switch nal_unit_type {
case 1,2,5,19: case 1, 2, 5, 19:
// slice_layer_without_partitioning_rbsp // slice_layer_without_partitioning_rbsp
// slice_data_partition_a_layer_rbsp // slice_data_partition_a_layer_rbsp
@ -727,11 +726,11 @@ func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, err error) {
} }
switch u { switch u {
case 0,3,5,8: case 0, 3, 5, 8:
sliceType = SLICE_P sliceType = SLICE_P
case 1,6: case 1, 6:
sliceType = SLICE_B sliceType = SLICE_B
case 2,4,7,9: case 2, 4, 7, 9:
sliceType = SLICE_I sliceType = SLICE_I
default: default:
err = fmt.Errorf("h264parser: slice_type=%d invalid", u) err = fmt.Errorf("h264parser: slice_type=%d invalid", u)
@ -740,4 +739,3 @@ func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, err error) {
return return
} }

View File

@ -1,9 +1,8 @@
package h264parser package h264parser
import ( import (
"testing"
"encoding/hex" "encoding/hex"
"testing"
) )
func TestParser(t *testing.T) { func TestParser(t *testing.T) {
@ -20,4 +19,3 @@ func TestParser(t *testing.T) {
nalus, ok = SplitNALUs(avccFrame) nalus, ok = SplitNALUs(avccFrame)
t.Log(ok, len(nalus)) 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. // 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 // 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 // of code can do a lot of things such as reading, writing, transcoding among

View File

@ -1,26 +1,25 @@
package aac package aac
import ( import (
"github.com/datarhei/joy4/av/avutil"
"github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/codec/aacparser"
"time"
"fmt"
"io"
"bufio" "bufio"
"fmt"
"github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/av/avutil"
"github.com/datarhei/joy4/codec/aacparser"
"io"
"time"
) )
type Muxer struct { type Muxer struct {
w io.Writer w io.Writer
config aacparser.MPEG4AudioConfig config aacparser.MPEG4AudioConfig
adtshdr []byte adtshdr []byte
} }
func NewMuxer(w io.Writer) *Muxer { func NewMuxer(w io.Writer) *Muxer {
return &Muxer{ return &Muxer{
adtshdr: make([]byte, aacparser.ADTSHeaderLength), adtshdr: make([]byte, aacparser.ADTSHeaderLength),
w: w, w: w,
} }
} }
@ -52,10 +51,10 @@ func (self *Muxer) WriteTrailer() (err error) {
} }
type Demuxer struct { type Demuxer struct {
r *bufio.Reader r *bufio.Reader
config aacparser.MPEG4AudioConfig config aacparser.MPEG4AudioConfig
codecdata av.CodecData codecdata av.CodecData
ts time.Duration ts time.Duration
} }
func NewDemuxer(r io.Reader) *Demuxer { func NewDemuxer(r io.Reader) *Demuxer {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -21,7 +21,7 @@ func (self AVC1Desc) Tag() Tag {
return AVC1 return AVC1
} }
const URL = Tag(0x75726c20) const URL = Tag(0x75726c20)
func (self DataReferUrl) Tag() Tag { func (self DataReferUrl) Tag() Tag {
return URL return URL
@ -204,16 +204,16 @@ func (self SoundMediaInfo) Tag() Tag {
const MDAT = Tag(0x6d646174) const MDAT = Tag(0x6d646174)
type Movie struct { type Movie struct {
Header *MovieHeader Header *MovieHeader
MovieExtend *MovieExtend MovieExtend *MovieExtend
Tracks []*Track Tracks []*Track
Unknowns []Atom Unknowns []Atom
AtomPos AtomPos
} }
func (self Movie) Marshal(b []byte) (n int) { func (self Movie) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(MOOV)) pio.PutU32BE(b[4:], uint32(MOOV))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -288,7 +288,7 @@ func (self *Movie) Unmarshal(b []byte, offset int) (n int, err error) {
} }
default: 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 { if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err) err = parseErr("", n+offset, err)
return return
@ -315,28 +315,28 @@ func (self Movie) Children() (r []Atom) {
} }
type MovieHeader struct { type MovieHeader struct {
Version uint8 Version uint8
Flags uint32 Flags uint32
CreateTime time.Time CreateTime time.Time
ModifyTime time.Time ModifyTime time.Time
TimeScale int32 TimeScale int32
Duration int32 Duration int32
PreferredRate float64 PreferredRate float64
PreferredVolume float64 PreferredVolume float64
Matrix [9]int32 Matrix [9]int32
PreviewTime time.Time PreviewTime time.Time
PreviewDuration time.Time PreviewDuration time.Time
PosterTime time.Time PosterTime time.Time
SelectionTime time.Time SelectionTime time.Time
SelectionDuration time.Time SelectionDuration time.Time
CurrentTime time.Time CurrentTime time.Time
NextTrackId int32 NextTrackId int32
AtomPos AtomPos
} }
func (self MovieHeader) Marshal(b []byte) (n int) { func (self MovieHeader) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(MVHD)) pio.PutU32BE(b[4:], uint32(MVHD))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -389,7 +389,7 @@ func (self MovieHeader) Len() (n int) {
n += 4 n += 4
n += 2 n += 2
n += 10 n += 10
n += 4*len(self.Matrix[:]) n += 4 * len(self.Matrix[:])
n += 4 n += 4
n += 4 n += 4
n += 4 n += 4
@ -508,15 +508,15 @@ func (self MovieHeader) Children() (r []Atom) {
} }
type Track struct { type Track struct {
Header *TrackHeader Header *TrackHeader
Media *Media Media *Media
Unknowns []Atom Unknowns []Atom
AtomPos AtomPos
} }
func (self Track) Marshal(b []byte) (n int) { func (self Track) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(TRAK)) pio.PutU32BE(b[4:], uint32(TRAK))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -576,7 +576,7 @@ func (self *Track) Unmarshal(b []byte, offset int) (n int, err error) {
} }
default: 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 { if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err) err = parseErr("", n+offset, err)
return return
@ -600,24 +600,24 @@ func (self Track) Children() (r []Atom) {
} }
type TrackHeader struct { type TrackHeader struct {
Version uint8 Version uint8
Flags uint32 Flags uint32
CreateTime time.Time CreateTime time.Time
ModifyTime time.Time ModifyTime time.Time
TrackId int32 TrackId int32
Duration int32 Duration int32
Layer int16 Layer int16
AlternateGroup int16 AlternateGroup int16
Volume float64 Volume float64
Matrix [9]int32 Matrix [9]int32
TrackWidth float64 TrackWidth float64
TrackHeight float64 TrackHeight float64
AtomPos AtomPos
} }
func (self TrackHeader) Marshal(b []byte) (n int) { func (self TrackHeader) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(TKHD)) pio.PutU32BE(b[4:], uint32(TKHD))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -667,7 +667,7 @@ func (self TrackHeader) Len() (n int) {
n += 2 n += 2
n += 2 n += 2
n += 2 n += 2
n += 4*len(self.Matrix[:]) n += 4 * len(self.Matrix[:])
n += 4 n += 4
n += 4 n += 4
return return
@ -759,17 +759,17 @@ func (self TrackHeader) Children() (r []Atom) {
} }
type HandlerRefer struct { type HandlerRefer struct {
Version uint8 Version uint8
Flags uint32 Flags uint32
Type [4]byte Type [4]byte
SubType [4]byte SubType [4]byte
Name []byte Name []byte
AtomPos AtomPos
} }
func (self HandlerRefer) Marshal(b []byte) (n int) { func (self HandlerRefer) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(HDLR)) pio.PutU32BE(b[4:], uint32(HDLR))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -831,16 +831,16 @@ func (self HandlerRefer) Children() (r []Atom) {
} }
type Media struct { type Media struct {
Header *MediaHeader Header *MediaHeader
Handler *HandlerRefer Handler *HandlerRefer
Info *MediaInfo Info *MediaInfo
Unknowns []Atom Unknowns []Atom
AtomPos AtomPos
} }
func (self Media) Marshal(b []byte) (n int) { func (self Media) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(MDIA)) pio.PutU32BE(b[4:], uint32(MDIA))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -915,7 +915,7 @@ func (self *Media) Unmarshal(b []byte, offset int) (n int, err error) {
} }
default: 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 { if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err) err = parseErr("", n+offset, err)
return return
@ -942,20 +942,20 @@ func (self Media) Children() (r []Atom) {
} }
type MediaHeader struct { type MediaHeader struct {
Version uint8 Version uint8
Flags uint32 Flags uint32
CreateTime time.Time CreateTime time.Time
ModifyTime time.Time ModifyTime time.Time
TimeScale int32 TimeScale int32
Duration int32 Duration int32
Language int16 Language int16
Quality int16 Quality int16
AtomPos AtomPos
} }
func (self MediaHeader) Marshal(b []byte) (n int) { func (self MediaHeader) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(MDHD)) pio.PutU32BE(b[4:], uint32(MDHD))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -1048,17 +1048,17 @@ func (self MediaHeader) Children() (r []Atom) {
} }
type MediaInfo struct { type MediaInfo struct {
Sound *SoundMediaInfo Sound *SoundMediaInfo
Video *VideoMediaInfo Video *VideoMediaInfo
Data *DataInfo Data *DataInfo
Sample *SampleTable Sample *SampleTable
Unknowns []Atom Unknowns []Atom
AtomPos AtomPos
} }
func (self MediaInfo) Marshal(b []byte) (n int) { func (self MediaInfo) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(MINF)) pio.PutU32BE(b[4:], uint32(MINF))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -1148,7 +1148,7 @@ func (self *MediaInfo) Unmarshal(b []byte, offset int) (n int, err error) {
} }
default: 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 { if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err) err = parseErr("", n+offset, err)
return return
@ -1178,14 +1178,14 @@ func (self MediaInfo) Children() (r []Atom) {
} }
type DataInfo struct { type DataInfo struct {
Refer *DataRefer Refer *DataRefer
Unknowns []Atom Unknowns []Atom
AtomPos AtomPos
} }
func (self DataInfo) Marshal(b []byte) (n int) { func (self DataInfo) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(DINF)) pio.PutU32BE(b[4:], uint32(DINF))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -1230,7 +1230,7 @@ func (self *DataInfo) Unmarshal(b []byte, offset int) (n int, err error) {
} }
default: 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 { if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err) err = parseErr("", n+offset, err)
return return
@ -1251,15 +1251,15 @@ func (self DataInfo) Children() (r []Atom) {
} }
type DataRefer struct { type DataRefer struct {
Version uint8 Version uint8
Flags uint32 Flags uint32
Url *DataReferUrl Url *DataReferUrl
AtomPos AtomPos
} }
func (self DataRefer) Marshal(b []byte) (n int) { func (self DataRefer) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(DREF)) pio.PutU32BE(b[4:], uint32(DREF))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -1313,7 +1313,7 @@ func (self *DataRefer) Unmarshal(b []byte, offset int) (n int, err error) {
return return
} }
switch tag { switch tag {
case URL : case URL:
{ {
atom := &DataReferUrl{} atom := &DataReferUrl{}
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { 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 { type DataReferUrl struct {
Version uint8 Version uint8
Flags uint32 Flags uint32
AtomPos AtomPos
} }
func (self DataReferUrl) Marshal(b []byte) (n int) { func (self DataReferUrl) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(URL )) pio.PutU32BE(b[4:], uint32(URL))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -1381,15 +1381,15 @@ func (self DataReferUrl) Children() (r []Atom) {
} }
type SoundMediaInfo struct { type SoundMediaInfo struct {
Version uint8 Version uint8
Flags uint32 Flags uint32
Balance int16 Balance int16
AtomPos AtomPos
} }
func (self SoundMediaInfo) Marshal(b []byte) (n int) { func (self SoundMediaInfo) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(SMHD)) pio.PutU32BE(b[4:], uint32(SMHD))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -1440,16 +1440,16 @@ func (self SoundMediaInfo) Children() (r []Atom) {
} }
type VideoMediaInfo struct { type VideoMediaInfo struct {
Version uint8 Version uint8
Flags uint32 Flags uint32
GraphicsMode int16 GraphicsMode int16
Opcolor [3]int16 Opcolor [3]int16
AtomPos AtomPos
} }
func (self VideoMediaInfo) Marshal(b []byte) (n int) { func (self VideoMediaInfo) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(VMHD)) pio.PutU32BE(b[4:], uint32(VMHD))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -1471,7 +1471,7 @@ func (self VideoMediaInfo) Len() (n int) {
n += 1 n += 1
n += 3 n += 3
n += 2 n += 2
n += 2*len(self.Opcolor[:]) n += 2 * len(self.Opcolor[:])
return return
} }
func (self *VideoMediaInfo) Unmarshal(b []byte, offset int) (n int, err error) { 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 { type SampleTable struct {
SampleDesc *SampleDesc SampleDesc *SampleDesc
TimeToSample *TimeToSample TimeToSample *TimeToSample
CompositionOffset *CompositionOffset CompositionOffset *CompositionOffset
SampleToChunk *SampleToChunk SampleToChunk *SampleToChunk
SyncSample *SyncSample SyncSample *SyncSample
ChunkOffset *ChunkOffset ChunkOffset *ChunkOffset
SampleSize *SampleSize SampleSize *SampleSize
AtomPos AtomPos
} }
func (self SampleTable) Marshal(b []byte) (n int) { func (self SampleTable) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(STBL)) pio.PutU32BE(b[4:], uint32(STBL))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -1680,16 +1680,16 @@ func (self SampleTable) Children() (r []Atom) {
} }
type SampleDesc struct { type SampleDesc struct {
Version uint8 Version uint8
AVC1Desc *AVC1Desc AVC1Desc *AVC1Desc
MP4ADesc *MP4ADesc MP4ADesc *MP4ADesc
Unknowns []Atom Unknowns []Atom
AtomPos AtomPos
} }
func (self SampleDesc) Marshal(b []byte) (n int) { func (self SampleDesc) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(STSD)) pio.PutU32BE(b[4:], uint32(STSD))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -1773,7 +1773,7 @@ func (self *SampleDesc) Unmarshal(b []byte, offset int) (n int, err error) {
} }
default: 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 { if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err) err = parseErr("", n+offset, err)
return return
@ -1797,22 +1797,22 @@ func (self SampleDesc) Children() (r []Atom) {
} }
type MP4ADesc struct { type MP4ADesc struct {
DataRefIdx int16 DataRefIdx int16
Version int16 Version int16
RevisionLevel int16 RevisionLevel int16
Vendor int32 Vendor int32
NumberOfChannels int16 NumberOfChannels int16
SampleSize int16 SampleSize int16
CompressionId int16 CompressionId int16
SampleRate float64 SampleRate float64
Conf *ElemStreamDesc Conf *ElemStreamDesc
Unknowns []Atom Unknowns []Atom
AtomPos AtomPos
} }
func (self MP4ADesc) Marshal(b []byte) (n int) { func (self MP4ADesc) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(MP4A)) pio.PutU32BE(b[4:], uint32(MP4A))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -1935,7 +1935,7 @@ func (self *MP4ADesc) Unmarshal(b []byte, offset int) (n int, err error) {
} }
default: 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 { if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err) err = parseErr("", n+offset, err)
return return
@ -1956,28 +1956,28 @@ func (self MP4ADesc) Children() (r []Atom) {
} }
type AVC1Desc struct { type AVC1Desc struct {
DataRefIdx int16 DataRefIdx int16
Version int16 Version int16
Revision int16 Revision int16
Vendor int32 Vendor int32
TemporalQuality int32 TemporalQuality int32
SpatialQuality int32 SpatialQuality int32
Width int16 Width int16
Height int16 Height int16
HorizontalResolution float64 HorizontalResolution float64
VorizontalResolution float64 VorizontalResolution float64
FrameCount int16 FrameCount int16
CompressorName [32]byte CompressorName [32]byte
Depth int16 Depth int16
ColorTableId int16 ColorTableId int16
Conf *AVC1Conf Conf *AVC1Conf
Unknowns []Atom Unknowns []Atom
AtomPos AtomPos
} }
func (self AVC1Desc) Marshal(b []byte) (n int) { func (self AVC1Desc) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(AVC1)) pio.PutU32BE(b[4:], uint32(AVC1))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -2154,7 +2154,7 @@ func (self *AVC1Desc) Unmarshal(b []byte, offset int) (n int, err error) {
} }
default: 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 { if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err) err = parseErr("", n+offset, err)
return return
@ -2175,13 +2175,13 @@ func (self AVC1Desc) Children() (r []Atom) {
} }
type AVC1Conf struct { type AVC1Conf struct {
Data []byte Data []byte
AtomPos AtomPos
} }
func (self AVC1Conf) Marshal(b []byte) (n int) { func (self AVC1Conf) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(AVCC)) pio.PutU32BE(b[4:], uint32(AVCC))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -2207,15 +2207,15 @@ func (self AVC1Conf) Children() (r []Atom) {
} }
type TimeToSample struct { type TimeToSample struct {
Version uint8 Version uint8
Flags uint32 Flags uint32
Entries []TimeToSampleEntry Entries []TimeToSampleEntry
AtomPos AtomPos
} }
func (self TimeToSample) Marshal(b []byte) (n int) { func (self TimeToSample) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(STTS)) pio.PutU32BE(b[4:], uint32(STTS))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -2237,7 +2237,7 @@ func (self TimeToSample) Len() (n int) {
n += 1 n += 1
n += 3 n += 3
n += 4 n += 4
n += LenTimeToSampleEntry*len(self.Entries) n += LenTimeToSampleEntry * len(self.Entries)
return return
} }
func (self *TimeToSample) Unmarshal(b []byte, offset int) (n int, err error) { 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 { type TimeToSampleEntry struct {
Count uint32 Count uint32
Duration uint32 Duration uint32
} }
func GetTimeToSampleEntry(b []byte) (self TimeToSampleEntry) { func GetTimeToSampleEntry(b []byte) (self TimeToSampleEntry) {
@ -2291,15 +2291,15 @@ func PutTimeToSampleEntry(b []byte, self TimeToSampleEntry) {
const LenTimeToSampleEntry = 8 const LenTimeToSampleEntry = 8
type SampleToChunk struct { type SampleToChunk struct {
Version uint8 Version uint8
Flags uint32 Flags uint32
Entries []SampleToChunkEntry Entries []SampleToChunkEntry
AtomPos AtomPos
} }
func (self SampleToChunk) Marshal(b []byte) (n int) { func (self SampleToChunk) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(STSC)) pio.PutU32BE(b[4:], uint32(STSC))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -2321,7 +2321,7 @@ func (self SampleToChunk) Len() (n int) {
n += 1 n += 1
n += 3 n += 3
n += 4 n += 4
n += LenSampleToChunkEntry*len(self.Entries) n += LenSampleToChunkEntry * len(self.Entries)
return return
} }
func (self *SampleToChunk) Unmarshal(b []byte, offset int) (n int, err error) { 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 { type SampleToChunkEntry struct {
FirstChunk uint32 FirstChunk uint32
SamplesPerChunk uint32 SamplesPerChunk uint32
SampleDescId uint32 SampleDescId uint32
} }
func GetSampleToChunkEntry(b []byte) (self SampleToChunkEntry) { func GetSampleToChunkEntry(b []byte) (self SampleToChunkEntry) {
@ -2378,15 +2378,15 @@ func PutSampleToChunkEntry(b []byte, self SampleToChunkEntry) {
const LenSampleToChunkEntry = 12 const LenSampleToChunkEntry = 12
type CompositionOffset struct { type CompositionOffset struct {
Version uint8 Version uint8
Flags uint32 Flags uint32
Entries []CompositionOffsetEntry Entries []CompositionOffsetEntry
AtomPos AtomPos
} }
func (self CompositionOffset) Marshal(b []byte) (n int) { func (self CompositionOffset) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(CTTS)) pio.PutU32BE(b[4:], uint32(CTTS))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -2408,7 +2408,7 @@ func (self CompositionOffset) Len() (n int) {
n += 1 n += 1
n += 3 n += 3
n += 4 n += 4
n += LenCompositionOffsetEntry*len(self.Entries) n += LenCompositionOffsetEntry * len(self.Entries)
return return
} }
func (self *CompositionOffset) Unmarshal(b []byte, offset int) (n int, err error) { 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 { type CompositionOffsetEntry struct {
Count uint32 Count uint32
Offset uint32 Offset uint32
} }
func GetCompositionOffsetEntry(b []byte) (self CompositionOffsetEntry) { func GetCompositionOffsetEntry(b []byte) (self CompositionOffsetEntry) {
@ -2462,15 +2462,15 @@ func PutCompositionOffsetEntry(b []byte, self CompositionOffsetEntry) {
const LenCompositionOffsetEntry = 8 const LenCompositionOffsetEntry = 8
type SyncSample struct { type SyncSample struct {
Version uint8 Version uint8
Flags uint32 Flags uint32
Entries []uint32 Entries []uint32
AtomPos AtomPos
} }
func (self SyncSample) Marshal(b []byte) (n int) { func (self SyncSample) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(STSS)) pio.PutU32BE(b[4:], uint32(STSS))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -2492,7 +2492,7 @@ func (self SyncSample) Len() (n int) {
n += 1 n += 1
n += 3 n += 3
n += 4 n += 4
n += 4*len(self.Entries) n += 4 * len(self.Entries)
return return
} }
func (self *SyncSample) Unmarshal(b []byte, offset int) (n int, err error) { 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 { type ChunkOffset struct {
Version uint8 Version uint8
Flags uint32 Flags uint32
Entries []uint32 Entries []uint32
AtomPos AtomPos
} }
func (self ChunkOffset) Marshal(b []byte) (n int) { func (self ChunkOffset) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(STCO)) pio.PutU32BE(b[4:], uint32(STCO))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -2559,7 +2559,7 @@ func (self ChunkOffset) Len() (n int) {
n += 1 n += 1
n += 3 n += 3
n += 4 n += 4
n += 4*len(self.Entries) n += 4 * len(self.Entries)
return return
} }
func (self *ChunkOffset) Unmarshal(b []byte, offset int) (n int, err error) { 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 { type MovieFrag struct {
Header *MovieFragHeader Header *MovieFragHeader
Tracks []*TrackFrag Tracks []*TrackFrag
Unknowns []Atom Unknowns []Atom
AtomPos AtomPos
} }
func (self MovieFrag) Marshal(b []byte) (n int) { func (self MovieFrag) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(MOOF)) pio.PutU32BE(b[4:], uint32(MOOF))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -2664,7 +2664,7 @@ func (self *MovieFrag) Unmarshal(b []byte, offset int) (n int, err error) {
} }
default: 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 { if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err) err = parseErr("", n+offset, err)
return return
@ -2688,15 +2688,15 @@ func (self MovieFrag) Children() (r []Atom) {
} }
type MovieFragHeader struct { type MovieFragHeader struct {
Version uint8 Version uint8
Flags uint32 Flags uint32
Seqnum uint32 Seqnum uint32
AtomPos AtomPos
} }
func (self MovieFragHeader) Marshal(b []byte) (n int) { func (self MovieFragHeader) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(MFHD)) pio.PutU32BE(b[4:], uint32(MFHD))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -2744,16 +2744,16 @@ func (self MovieFragHeader) Children() (r []Atom) {
} }
type TrackFrag struct { type TrackFrag struct {
Header *TrackFragHeader Header *TrackFragHeader
DecodeTime *TrackFragDecodeTime DecodeTime *TrackFragDecodeTime
Run *TrackFragRun Run *TrackFragRun
Unknowns []Atom Unknowns []Atom
AtomPos AtomPos
} }
func (self TrackFrag) Marshal(b []byte) (n int) { func (self TrackFrag) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(TRAF)) pio.PutU32BE(b[4:], uint32(TRAF))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -2828,7 +2828,7 @@ func (self *TrackFrag) Unmarshal(b []byte, offset int) (n int, err error) {
} }
default: 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 { if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err) err = parseErr("", n+offset, err)
return return
@ -2855,14 +2855,14 @@ func (self TrackFrag) Children() (r []Atom) {
} }
type MovieExtend struct { type MovieExtend struct {
Tracks []*TrackExtend Tracks []*TrackExtend
Unknowns []Atom Unknowns []Atom
AtomPos AtomPos
} }
func (self MovieExtend) Marshal(b []byte) (n int) { func (self MovieExtend) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(MVEX)) pio.PutU32BE(b[4:], uint32(MVEX))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -2907,7 +2907,7 @@ func (self *MovieExtend) Unmarshal(b []byte, offset int) (n int, err error) {
} }
default: 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 { if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
err = parseErr("", n+offset, err) err = parseErr("", n+offset, err)
return return
@ -2928,19 +2928,19 @@ func (self MovieExtend) Children() (r []Atom) {
} }
type TrackExtend struct { type TrackExtend struct {
Version uint8 Version uint8
Flags uint32 Flags uint32
TrackId uint32 TrackId uint32
DefaultSampleDescIdx uint32 DefaultSampleDescIdx uint32
DefaultSampleDuration uint32 DefaultSampleDuration uint32
DefaultSampleSize uint32 DefaultSampleSize uint32
DefaultSampleFlags uint32 DefaultSampleFlags uint32
AtomPos AtomPos
} }
func (self TrackExtend) Marshal(b []byte) (n int) { func (self TrackExtend) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(TREX)) pio.PutU32BE(b[4:], uint32(TREX))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -3024,16 +3024,16 @@ func (self TrackExtend) Children() (r []Atom) {
} }
type SampleSize struct { type SampleSize struct {
Version uint8 Version uint8
Flags uint32 Flags uint32
SampleSize uint32 SampleSize uint32
Entries []uint32 Entries []uint32
AtomPos AtomPos
} }
func (self SampleSize) Marshal(b []byte) (n int) { func (self SampleSize) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(STSZ)) pio.PutU32BE(b[4:], uint32(STSZ))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -3064,7 +3064,7 @@ func (self SampleSize) Len() (n int) {
return return
} }
n += 4 n += 4
n += 4*len(self.Entries) n += 4 * len(self.Entries)
return return
} }
func (self *SampleSize) Unmarshal(b []byte, offset int) (n int, err error) { 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 { type TrackFragRun struct {
Version uint8 Version uint8
Flags uint32 Flags uint32
DataOffset uint32 DataOffset uint32
FirstSampleFlags uint32 FirstSampleFlags uint32
Entries []TrackFragRunEntry Entries []TrackFragRunEntry
AtomPos AtomPos
} }
func (self TrackFragRun) Marshal(b []byte) (n int) { func (self TrackFragRun) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(TRUN)) pio.PutU32BE(b[4:], uint32(TRUN))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -3280,10 +3280,10 @@ func (self TrackFragRun) Children() (r []Atom) {
} }
type TrackFragRunEntry struct { type TrackFragRunEntry struct {
Duration uint32 Duration uint32
Size uint32 Size uint32
Flags uint32 Flags uint32
Cts uint32 Cts uint32
} }
func GetTrackFragRunEntry(b []byte) (self TrackFragRunEntry) { func GetTrackFragRunEntry(b []byte) (self TrackFragRunEntry) {
@ -3303,19 +3303,19 @@ func PutTrackFragRunEntry(b []byte, self TrackFragRunEntry) {
const LenTrackFragRunEntry = 16 const LenTrackFragRunEntry = 16
type TrackFragHeader struct { type TrackFragHeader struct {
Version uint8 Version uint8
Flags uint32 Flags uint32
BaseDataOffset uint64 BaseDataOffset uint64
StsdId uint32 StsdId uint32
DefaultDuration uint32 DefaultDuration uint32
DefaultSize uint32 DefaultSize uint32
DefaultFlags uint32 DefaultFlags uint32
AtomPos AtomPos
} }
func (self TrackFragHeader) Marshal(b []byte) (n int) { func (self TrackFragHeader) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(TFHD)) pio.PutU32BE(b[4:], uint32(TFHD))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }
@ -3459,15 +3459,15 @@ func (self TrackFragHeader) Children() (r []Atom) {
} }
type TrackFragDecodeTime struct { type TrackFragDecodeTime struct {
Version uint8 Version uint8
Flags uint32 Flags uint32
Time time.Time Time time.Time
AtomPos AtomPos
} }
func (self TrackFragDecodeTime) Marshal(b []byte) (n int) { func (self TrackFragDecodeTime) Marshal(b []byte) (n int) {
pio.PutU32BE(b[4:], uint32(TFDT)) pio.PutU32BE(b[4:], uint32(TFDT))
n += self.marshal(b[8:])+8 n += self.marshal(b[8:]) + 8
pio.PutU32BE(b[0:], uint32(n)) pio.PutU32BE(b[0:], uint32(n))
return return
} }

View File

@ -1,14 +1,13 @@
package main package main
import ( import (
"strings"
"fmt" "fmt"
"os"
"go/ast" "go/ast"
"go/parser" "go/parser"
"go/token"
"go/printer" "go/printer"
"go/token"
"os"
"strings"
) )
func getexprs(e ast.Expr) string { func getexprs(e ast.Expr) string {
@ -37,7 +36,7 @@ func genatomdecl(origfn *ast.FuncDecl, origname, origtag string) (decls []ast.De
if typ == "_unknowns" { if typ == "_unknowns" {
fieldslist.List = append(fieldslist.List, &ast.Field{ fieldslist.List = append(fieldslist.List, &ast.Field{
Names: []*ast.Ident{ast.NewIdent("Unknowns")}, Names: []*ast.Ident{ast.NewIdent("Unknowns")},
Type: ast.NewIdent("[]Atom"), Type: ast.NewIdent("[]Atom"),
}) })
} }
continue continue
@ -67,24 +66,24 @@ func genatomdecl(origfn *ast.FuncDecl, origname, origtag string) (decls []ast.De
case "bytesleft": case "bytesleft":
typ = "[]byte" typ = "[]byte"
case "bytes": case "bytes":
typ = "["+name2+"]byte" typ = "[" + name2 + "]byte"
case "uint24": case "uint24":
typ = "uint32" typ = "uint32"
case "time64", "time32": case "time64", "time32":
typ = "time.Time" typ = "time.Time"
case "atom": case "atom":
typ = "*"+name2 typ = "*" + name2
case "atoms": case "atoms":
typ = "[]*"+name2 typ = "[]*" + name2
case "slice": case "slice":
typ = "[]"+name2 typ = "[]" + name2
case "array": case "array":
typ = "["+len3+"]"+name2 typ = "[" + len3 + "]" + name2
} }
fieldslist.List = append(fieldslist.List, &ast.Field{ fieldslist.List = append(fieldslist.List, &ast.Field{
Names: []*ast.Ident{ast.NewIdent(name)}, 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 { func typegetlens(typ string) string {
n := typegetlen(typ) n := typegetlen(typ)
if n == 0 { if n == 0 {
return "Len"+typ return "Len" + typ
} else { } else {
return fmt.Sprint(n) return fmt.Sprint(n)
} }
@ -187,7 +186,7 @@ func typegetputfn(typ string) (fn string) {
case "fixed16": case "fixed16":
fn = "PutFixed16" fn = "PutFixed16"
default: default:
fn = "Put"+typ fn = "Put" + typ
} }
return return
} }
@ -218,7 +217,7 @@ func typegetgetfn(typ string) (fn string) {
case "fixed16": case "fixed16":
fn = "GetFixed16" fn = "GetFixed16"
default: default:
fn = "Get"+typ fn = "Get" + typ
} }
return return
} }
@ -237,14 +236,14 @@ func addn(n int) (stmts []ast.Stmt) {
return addns(fmt.Sprint(n)) return addns(fmt.Sprint(n))
} }
func simplecall(fun string, args... string) *ast.ExprStmt { func simplecall(fun string, args ...string) *ast.ExprStmt {
_args := []ast.Expr{} _args := []ast.Expr{}
for _, s := range args { for _, s := range args {
_args = append(_args, ast.NewIdent(s)) _args = append(_args, ast.NewIdent(s))
} }
return &ast.ExprStmt{ return &ast.ExprStmt{
X: &ast.CallExpr{ X: &ast.CallExpr{
Fun: ast.NewIdent(fun), Fun: ast.NewIdent(fun),
Args: _args, Args: _args,
}, },
} }
@ -283,7 +282,7 @@ func newdecl(origname, name string, params, res []*ast.Field, stmts []ast.Stmt)
List: []*ast.Field{ List: []*ast.Field{
&ast.Field{ &ast.Field{
Names: []*ast.Ident{ast.NewIdent("self")}, 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{}) getstmts = append(getstmts, &ast.ReturnStmt{})
decls = append(decls, &ast.FuncDecl{ decls = append(decls, &ast.FuncDecl{
Name: ast.NewIdent("Get"+origname), Name: ast.NewIdent("Get" + origname),
Type: &ast.FuncType{ Type: &ast.FuncType{
Params: &ast.FieldList{ Params: &ast.FieldList{
List: []*ast.Field{ List: []*ast.Field{
@ -336,7 +335,7 @@ func getstructputgetlenfn(origfn *ast.FuncDecl, origname string) (decls []ast.De
}) })
decls = append(decls, &ast.FuncDecl{ decls = append(decls, &ast.FuncDecl{
Name: ast.NewIdent("Put"+origname), Name: ast.NewIdent("Put" + origname),
Type: &ast.FuncType{ Type: &ast.FuncType{
Params: &ast.FieldList{ Params: &ast.FieldList{
List: []*ast.Field{ List: []*ast.Field{
@ -352,7 +351,7 @@ func getstructputgetlenfn(origfn *ast.FuncDecl, origname string) (decls []ast.De
Tok: token.CONST, Tok: token.CONST,
Specs: []ast.Spec{ Specs: []ast.Spec{
&ast.ValueSpec{ &ast.ValueSpec{
Names: []*ast.Ident{ast.NewIdent("Len"+origname)}, Names: []*ast.Ident{ast.NewIdent("Len" + origname)},
Values: []ast.Expr{ast.NewIdent(fmt.Sprint(totlen))}, Values: []ast.Expr{ast.NewIdent(fmt.Sprint(totlen))},
}, },
}, },
@ -371,7 +370,7 @@ func cc4decls(name string) (decls []ast.Decl) {
}, },
Values: []ast.Expr{ Values: []ast.Expr{
&ast.CallExpr{ &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))}}, 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) { callmarshal := func(name string) (stmts []ast.Stmt) {
callexpr := &ast.CallExpr{ callexpr := &ast.CallExpr{
Fun: ast.NewIdent(name+".Marshal"), Fun: ast.NewIdent(name + ".Marshal"),
Args: []ast.Expr{ast.NewIdent("b[n:]")}, Args: []ast.Expr{ast.NewIdent("b[n:]")},
} }
assign := &ast.AssignStmt{ assign := &ast.AssignStmt{
@ -446,7 +445,7 @@ func getatommarshalfn(origfn *ast.FuncDecl,
callputstruct := func(typ, name string) (stmts []ast.Stmt) { callputstruct := func(typ, name string) (stmts []ast.Stmt) {
stmts = append(stmts, &ast.ExprStmt{ stmts = append(stmts, &ast.ExprStmt{
X: &ast.CallExpr{ X: &ast.CallExpr{
Fun: ast.NewIdent(typegetputfn(typ)), Fun: ast.NewIdent(typegetputfn(typ)),
Args: []ast.Expr{ast.NewIdent("b[n:]"), ast.NewIdent(name)}, 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) { calllenstruct := func(typ, name string) (stmts []ast.Stmt) {
inc := typegetlens(typ)+"*len("+name+")" inc := typegetlens(typ) + "*len(" + name + ")"
stmts = append(stmts, &ast.AssignStmt{ stmts = append(stmts, &ast.AssignStmt{
Tok: token.ADD_ASSIGN, Tok: token.ADD_ASSIGN,
Lhs: []ast.Expr{ast.NewIdent("n")}, Lhs: []ast.Expr{ast.NewIdent("n")},
@ -470,7 +469,7 @@ func getatommarshalfn(origfn *ast.FuncDecl,
calllen := func(name string) (stmts []ast.Stmt) { calllen := func(name string) (stmts []ast.Stmt) {
callexpr := &ast.CallExpr{ callexpr := &ast.CallExpr{
Fun: ast.NewIdent(name+".Len"), Fun: ast.NewIdent(name + ".Len"),
Args: []ast.Expr{}, Args: []ast.Expr{},
} }
assign := &ast.AssignStmt{ assign := &ast.AssignStmt{
@ -484,13 +483,13 @@ func getatommarshalfn(origfn *ast.FuncDecl,
foreach := func(name, field string, block []ast.Stmt) (stmts []ast.Stmt) { foreach := func(name, field string, block []ast.Stmt) (stmts []ast.Stmt) {
rangestmt := &ast.RangeStmt{ rangestmt := &ast.RangeStmt{
Key: ast.NewIdent("_"), Key: ast.NewIdent("_"),
Value: ast.NewIdent(name), Value: ast.NewIdent(name),
Body: &ast.BlockStmt{ Body: &ast.BlockStmt{
List: block, List: block,
}, },
Tok: token.DEFINE, Tok: token.DEFINE,
X: ast.NewIdent(field), X: ast.NewIdent(field),
} }
stmts = append(stmts, rangestmt) stmts = append(stmts, rangestmt)
return return
@ -511,7 +510,7 @@ func getatommarshalfn(origfn *ast.FuncDecl,
List: block, List: block,
}, },
Tok: token.DEFINE, Tok: token.DEFINE,
X: ast.NewIdent(field), X: ast.NewIdent(field),
} }
stmts = append(stmts, rangestmt) stmts = append(stmts, rangestmt)
return return
@ -574,7 +573,7 @@ func getatommarshalfn(origfn *ast.FuncDecl,
unmarshalatom := func(typ, init string) (stmts []ast.Stmt) { unmarshalatom := func(typ, init string) (stmts []ast.Stmt) {
return []ast.Stmt{ return []ast.Stmt{
&ast.AssignStmt{Tok: token.DEFINE, &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{ &ast.IfStmt{
Init: &ast.AssignStmt{ Init: &ast.AssignStmt{
@ -591,10 +590,10 @@ func getatommarshalfn(origfn *ast.FuncDecl,
unmrashalatoms := func() (stmts []ast.Stmt) { unmrashalatoms := func() (stmts []ast.Stmt) {
blocks := []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:]))")}, 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:]))")}, Rhs: []ast.Expr{ast.NewIdent("int(pio.U32BE(b[n:]))")},
}) })
blocks = append(blocks, &ast.IfStmt{ blocks = append(blocks, &ast.IfStmt{
@ -614,7 +613,7 @@ func getatommarshalfn(origfn *ast.FuncDecl,
} }
for i, atom := range atomarrnames { for i, atom := range atomarrnames {
selfatom := "self."+atom selfatom := "self." + atom
cases = append(cases, &ast.CaseClause{ cases = append(cases, &ast.CaseClause{
List: []ast.Expr{ast.NewIdent(strings.ToUpper(struct2tag(atomarrtypes[i])))}, List: []ast.Expr{ast.NewIdent(strings.ToUpper(struct2tag(atomarrtypes[i])))},
Body: []ast.Stmt{&ast.BlockStmt{ Body: []ast.Stmt{&ast.BlockStmt{
@ -635,7 +634,7 @@ func getatommarshalfn(origfn *ast.FuncDecl,
} }
blocks = append(blocks, &ast.SwitchStmt{ blocks = append(blocks, &ast.SwitchStmt{
Tag: ast.NewIdent("tag"), Tag: ast.NewIdent("tag"),
Body: &ast.BlockStmt{List: cases}, Body: &ast.BlockStmt{List: cases},
}) })
@ -659,9 +658,9 @@ func getatommarshalfn(origfn *ast.FuncDecl,
ifnotnil := func(name string, block []ast.Stmt) (stmts []ast.Stmt) { ifnotnil := func(name string, block []ast.Stmt) (stmts []ast.Stmt) {
stmts = append(stmts, &ast.IfStmt{ stmts = append(stmts, &ast.IfStmt{
Cond: &ast.BinaryExpr{ Cond: &ast.BinaryExpr{
X: ast.NewIdent(name), X: ast.NewIdent(name),
Op: token.NEQ, Op: token.NEQ,
Y: ast.NewIdent("nil"), Y: ast.NewIdent("nil"),
}, },
Body: &ast.BlockStmt{List: block}, Body: &ast.BlockStmt{List: block},
}) })
@ -693,9 +692,9 @@ func getatommarshalfn(origfn *ast.FuncDecl,
checkcurlen := func(inc, debug string) (stmts []ast.Stmt) { checkcurlen := func(inc, debug string) (stmts []ast.Stmt) {
stmts = append(stmts, &ast.IfStmt{ stmts = append(stmts, &ast.IfStmt{
Cond: &ast.BinaryExpr{ Cond: &ast.BinaryExpr{
X: ast.NewIdent("len(b)"), X: ast.NewIdent("len(b)"),
Op: token.LSS, Op: token.LSS,
Y: ast.NewIdent("n+"+inc), Y: ast.NewIdent("n+" + inc),
}, },
Body: &ast.BlockStmt{List: parseerrreturn(debug)}, Body: &ast.BlockStmt{List: parseerrreturn(debug)},
}) })
@ -710,20 +709,20 @@ func getatommarshalfn(origfn *ast.FuncDecl,
} }
checkstructlendo := func(typ, name, debug string, checkstructlendo := func(typ, name, debug string,
foreach func(string,[]ast.Stmt)[]ast.Stmt, foreach func(string, []ast.Stmt) []ast.Stmt,
) (stmts []ast.Stmt) { ) (stmts []ast.Stmt) {
inc := typegetlens(typ)+"*len("+name+")" inc := typegetlens(typ) + "*len(" + name + ")"
stmts = append(stmts, checkcurlen(inc, debug)...) stmts = append(stmts, checkcurlen(inc, debug)...)
stmts = append(stmts, foreach(name, append( stmts = append(stmts, foreach(name, append(
[]ast.Stmt{ []ast.Stmt{
&ast.AssignStmt{ &ast.AssignStmt{
Tok: token.ASSIGN, Tok: token.ASSIGN,
Lhs: []ast.Expr{ Lhs: []ast.Expr{
ast.NewIdent(name+"[i]"), ast.NewIdent(name + "[i]"),
}, },
Rhs: []ast.Expr{ Rhs: []ast.Expr{
&ast.CallExpr{ &ast.CallExpr{
Fun: ast.NewIdent(typegetgetfn(typ)), Fun: ast.NewIdent(typegetgetfn(typ)),
Args: []ast.Expr{ast.NewIdent("b[n:]")}, Args: []ast.Expr{ast.NewIdent("b[n:]")},
}, },
}, },
@ -1054,4 +1053,3 @@ func main() {
genatoms(os.Args[2], os.Args[3]) genatoms(os.Args[2], os.Args[3])
} }
} }

View File

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

View File

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

View File

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

View File

@ -17,7 +17,7 @@ type Stream struct {
timeScale int64 timeScale int64
duration int64 duration int64
muxer *Muxer muxer *Muxer
demuxer *Demuxer demuxer *Demuxer
sample *mp4io.SampleTable sample *mp4io.SampleTable
@ -42,17 +42,17 @@ type Stream struct {
} }
func timeToTs(tm time.Duration, timeScale int64) int64 { 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 { 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 { 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 { 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/binary"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"github.com/datarhei/joy4/utils/bits/pio"
"github.com/datarhei/joy4/av" "github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/av/avutil" "github.com/datarhei/joy4/av/avutil"
"github.com/datarhei/joy4/codec" "github.com/datarhei/joy4/codec"
"github.com/datarhei/joy4/codec/aacparser" "github.com/datarhei/joy4/codec/aacparser"
"github.com/datarhei/joy4/codec/h264parser" "github.com/datarhei/joy4/codec/h264parser"
"github.com/datarhei/joy4/format/rtsp/sdp" "github.com/datarhei/joy4/format/rtsp/sdp"
"github.com/datarhei/joy4/utils/bits/pio"
"io" "io"
"net" "net"
"net/textproto" "net/textproto"
@ -31,7 +31,7 @@ var DebugRtsp = false
var SkipErrRtpBlock = false var SkipErrRtpBlock = false
const ( const (
stageDescribeDone = iota+1 stageDescribeDone = iota + 1
stageSetupDone stageSetupDone
stageWaitCodecData stageWaitCodecData
stageCodecDataDone stageCodecDataDone
@ -39,7 +39,7 @@ const (
type Client struct { type Client struct {
DebugRtsp bool DebugRtsp bool
DebugRtp bool DebugRtp bool
Headers []string Headers []string
SkipErrRtpBlock bool SkipErrRtpBlock bool
@ -52,20 +52,20 @@ type Client struct {
stage int stage int
setupIdx []int setupIdx []int
setupMap []int setupMap []int
authHeaders func(method string) []string authHeaders func(method string) []string
url *url.URL url *url.URL
conn *connWithTimeout conn *connWithTimeout
brconn *bufio.Reader brconn *bufio.Reader
requestUri string requestUri string
cseq uint cseq uint
streams []*Stream streams []*Stream
streamsintf []av.CodecData streamsintf []av.CodecData
session string session string
body io.Reader body io.Reader
} }
type Request struct { type Request struct {
@ -76,7 +76,7 @@ type Request struct {
type Response struct { type Response struct {
StatusCode int StatusCode int
Headers textproto.MIMEHeader Headers textproto.MIMEHeader
ContentLength int ContentLength int
Body []byte Body []byte
@ -105,12 +105,12 @@ func DialTimeout(uri string, timeout time.Duration) (self *Client, err error) {
connt := &connWithTimeout{Conn: conn} connt := &connWithTimeout{Conn: conn}
self = &Client{ self = &Client{
conn: connt, conn: connt,
brconn: bufio.NewReaderSize(connt, 256), brconn: bufio.NewReaderSize(connt, 256),
url: URL, url: URL,
requestUri: u2.String(), requestUri: u2.String(),
DebugRtp: DebugRtp, DebugRtp: DebugRtp,
DebugRtsp: DebugRtsp, DebugRtsp: DebugRtsp,
SkipErrRtpBlock: SkipErrRtpBlock, SkipErrRtpBlock: SkipErrRtpBlock,
} }
return return
@ -121,7 +121,7 @@ func Dial(uri string) (self *Client, err error) {
} }
func (self *Client) allCodecDataReady() bool { func (self *Client) allCodecDataReady() bool {
for _, si:= range self.setupIdx { for _, si := range self.setupIdx {
stream := self.streams[si] stream := self.streams[si]
if stream.CodecData == nil { if stream.CodecData == nil {
return false return false
@ -268,7 +268,7 @@ func (self *Client) parseBlockHeader(h []byte) (length int, no int, valid bool)
timestamp -= stream.firsttimestamp timestamp -= stream.firsttimestamp
if timestamp < stream.timestamp { if timestamp < stream.timestamp {
return return
} else if timestamp - stream.timestamp > uint32(stream.timeScale()*60*60) { } else if timestamp-stream.timestamp > uint32(stream.timeScale()*60*60) {
return return
} }
} }
@ -373,7 +373,7 @@ func (self *Client) handle401(res *Response) (err error) {
func (self *Client) findRTSP() (block []byte, data []byte, err error) { func (self *Client) findRTSP() (block []byte, data []byte, err error) {
const ( const (
R = iota+1 R = iota + 1
T T
S S
Header Header
@ -383,7 +383,7 @@ func (self *Client) findRTSP() (block []byte, data []byte, err error) {
peek := _peek[0:0] peek := _peek[0:0]
stat := 0 stat := 0
for i := 0;; i++ { for i := 0; ; i++ {
var b byte var b byte
if b, err = self.brconn.ReadByte(); err != nil { if b, err = self.brconn.ReadByte(); err != nil {
return return
@ -434,7 +434,7 @@ func (self *Client) findRTSP() (block []byte, data []byte, err error) {
fmt.Println("rtsp: dollar at", i, len(peek)) fmt.Println("rtsp: dollar at", i, len(peek))
} }
if blocklen, _, ok := self.parseBlockHeader(peek); ok { if blocklen, _, ok := self.parseBlockHeader(peek); ok {
left := blocklen+4-len(peek) left := blocklen + 4 - len(peek)
block = append(peek, make([]byte, left)...) block = append(peek, make([]byte, left)...)
if _, err = io.ReadFull(self.brconn, block[len(peek):]); err != nil { if _, err = io.ReadFull(self.brconn, block[len(peek):]); err != nil {
return 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) { func (self *Client) readLFLF() (block []byte, data []byte, err error) {
const ( const (
LF = iota+1 LF = iota + 1
LFLF LFLF
) )
peek := []byte{} peek := []byte{}
@ -471,7 +471,7 @@ func (self *Client) readLFLF() (block []byte, data []byte, err error) {
stat = LF stat = LF
lpos = pos lpos = pos
} else if stat == LF { } else if stat == LF {
if pos - lpos <= 2 { if pos-lpos <= 2 {
stat = LFLF stat = LFLF
} else { } else {
lpos = pos lpos = pos
@ -485,9 +485,9 @@ func (self *Client) readLFLF() (block []byte, data []byte, err error) {
if stat == LFLF { if stat == LFLF {
data = peek data = peek
return return
} else if dollarpos != -1 && dollarpos - pos >= 12 { } else if dollarpos != -1 && dollarpos-pos >= 12 {
hdrlen := dollarpos-pos hdrlen := dollarpos - pos
start := len(peek)-hdrlen start := len(peek) - hdrlen
if blocklen, _, ok := self.parseBlockHeader(peek[start:]); ok { if blocklen, _, ok := self.parseBlockHeader(peek[start:]); ok {
block = append(peek[start:], make([]byte, blocklen+4-hdrlen)...) block = append(peek[start:], make([]byte, blocklen+4-hdrlen)...)
if _, err = io.ReadFull(self.brconn, block[hdrlen:]); err != nil { 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 return
} }
naluType := packet[0]&0x1f naluType := packet[0] & 0x1f
/* /*
Table 7-1 NAL unit type codes Table 7-1 NAL unit type codes
@ -830,16 +830,16 @@ func (self *Stream) handleH264Payload(timestamp uint32, packet []byte) (err erro
*/ */
switch { switch {
case naluType >= 1 && naluType <= 5: case naluType >= 1 && naluType <= 5:
if naluType == 5 { if naluType == 5 {
self.pkt.IsKeyFrame = true self.pkt.IsKeyFrame = true
} }
self.gotpkt = true self.gotpkt = true
// raw nalu to avcc // raw nalu to avcc
b := make([]byte, 4+len(packet)) b := make([]byte, 4+len(packet))
pio.PutU32BE(b[0:4], uint32(len(packet))) pio.PutU32BE(b[0:4], uint32(len(packet)))
copy(b[4:], packet) copy(b[4:], packet)
self.pkt.Data = b self.pkt.Data = b
self.timestamp = timestamp self.timestamp = timestamp
case naluType == 7: // sps case naluType == 7: // sps
if self.client != nil && self.client.DebugRtp { 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 case naluType == 24: // STAP-A
/* /*
0 1 2 3 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 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 | | RTP Header |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|STAP-A NAL HDR | NALU 1 Size | NALU 1 HDR | |STAP-A NAL HDR | NALU 1 Size | NALU 1 HDR |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NALU 1 Data | | NALU 1 Data |
: : : :
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | NALU 2 Size | NALU 2 HDR | | | NALU 2 Size | NALU 2 HDR |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NALU 2 Data | | NALU 2 Data |
: : : :
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| :...OPTIONAL RTP padding | | :...OPTIONAL RTP padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 7. An example of an RTP packet including an STAP-A Figure 7. An example of an RTP packet including an STAP-A
containing two single-time aggregation units containing two single-time aggregation units
*/ */
packet = packet[1:] packet = packet[1:]
for len(packet) >= 2 { 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) { if size+2 > len(packet) {
break break
} }
@ -1141,7 +1141,7 @@ func (self *Client) handleBlock(block []byte) (pkt av.Packet, ok bool, err error
return return
} }
i := blockno/2 i := blockno / 2
if i >= len(self.streams) { if i >= len(self.streams) {
err = fmt.Errorf("rtsp: block no=%d invalid", blockno) err = fmt.Errorf("rtsp: block no=%d invalid", blockno)
return return
@ -1158,11 +1158,11 @@ func (self *Client) handleBlock(block []byte) (pkt av.Packet, ok bool, err error
if stream.gotpkt { if stream.gotpkt {
/* /*
TODO: sync AV by rtcp NTP timestamp TODO: sync AV by rtcp NTP timestamp
TODO: handle timestamp overflow TODO: handle timestamp overflow
https://tools.ietf.org/html/rfc3550 https://tools.ietf.org/html/rfc3550
A receiver can then synchronize presentation of the audio and video packets by relating 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. their RTP timestamps using the timestamp pairs in RTCP SR packets.
*/ */
if stream.firsttimestamp == 0 { if stream.firsttimestamp == 0 {
stream.firsttimestamp = stream.timestamp stream.firsttimestamp = stream.timestamp
@ -1171,10 +1171,10 @@ func (self *Client) handleBlock(block []byte) (pkt av.Packet, ok bool, err error
ok = true ok = true
pkt = stream.pkt 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]) 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) err = fmt.Errorf("rtp: time invalid stream#%d time=%v lasttime=%v", pkt.Idx, pkt.Time, stream.lasttime)
return return
} }
@ -1236,4 +1236,3 @@ func Handler(h *avutil.RegisterHandler) {
return return
} }
} }

View File

@ -19,11 +19,10 @@ type Stream struct {
spsChanged bool spsChanged bool
ppsChanged bool ppsChanged bool
gotpkt bool gotpkt bool
pkt av.Packet pkt av.Packet
timestamp uint32 timestamp uint32
firsttimestamp uint32 firsttimestamp uint32
lasttime time.Duration lasttime time.Duration
} }

View File

@ -3,13 +3,13 @@ package ts
import ( import (
"bufio" "bufio"
"fmt" "fmt"
"time"
"github.com/datarhei/joy4/utils/bits/pio"
"github.com/datarhei/joy4/av" "github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/format/ts/tsio"
"github.com/datarhei/joy4/codec/aacparser" "github.com/datarhei/joy4/codec/aacparser"
"github.com/datarhei/joy4/codec/h264parser" "github.com/datarhei/joy4/codec/h264parser"
"github.com/datarhei/joy4/format/ts/tsio"
"github.com/datarhei/joy4/utils/bits/pio"
"io" "io"
"time"
) )
type Demuxer struct { type Demuxer struct {
@ -28,7 +28,7 @@ type Demuxer struct {
func NewDemuxer(r io.Reader) *Demuxer { func NewDemuxer(r io.Reader) *Demuxer {
return &Demuxer{ return &Demuxer{
tshdr: make([]byte, 188), 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 return
} }
self.pmt = &tsio.PMT{} 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 return
} }
@ -156,7 +156,7 @@ func (self *Demuxer) readTSPacket() (err error) {
return return
} }
self.pat = &tsio.PAT{} 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 return
} }
} }
@ -192,13 +192,13 @@ func (self *Stream) addPacket(payload []byte, timedelta time.Duration) {
demuxer := self.demuxer demuxer := self.demuxer
pkt := av.Packet{ pkt := av.Packet{
Idx: int8(self.idx), Idx: int8(self.idx),
IsKeyFrame: self.iskeyframe, IsKeyFrame: self.iskeyframe,
Time: dts+timedelta, Time: dts + timedelta,
Data: payload, Data: payload,
} }
if pts != dts { if pts != dts {
pkt.CompositionTime = pts-dts pkt.CompositionTime = pts - dts
} }
demuxer.pkts = append(demuxer.pkts, pkt) demuxer.pkts = append(demuxer.pkts, pkt)
} }

View File

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

View File

@ -1,9 +1,9 @@
package ts package ts
import ( import (
"time"
"github.com/datarhei/joy4/av" "github.com/datarhei/joy4/av"
"github.com/datarhei/joy4/format/ts/tsio" "github.com/datarhei/joy4/format/ts/tsio"
"time"
) )
type Stream struct { type Stream struct {
@ -12,16 +12,15 @@ type Stream struct {
demuxer *Demuxer demuxer *Demuxer
muxer *Muxer muxer *Muxer
pid uint16 pid uint16
streamId uint8 streamId uint8
streamType uint8 streamType uint8
tsw *tsio.TSWriter tsw *tsio.TSWriter
idx int idx int
iskeyframe bool iskeyframe bool
pts, dts time.Duration pts, dts time.Duration
data []byte data []byte
datalen int datalen int
} }

View File

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

View File

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

View File

@ -6,13 +6,13 @@ import (
type Reader struct { type Reader struct {
buf [][]byte buf [][]byte
R io.ReadSeeker R io.ReadSeeker
} }
func NewReaderSize(r io.ReadSeeker, size int) *Reader { func NewReaderSize(r io.ReadSeeker, size int) *Reader {
buf := make([]byte, size*2) buf := make([]byte, size*2)
return &Reader{ return &Reader{
R: r, R: r,
buf: [][]byte{buf[0:size], buf[size:]}, 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) { func (self *Reader) ReadAt(b []byte, off int64) (n int, err error) {
return return
} }

View File

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

View File

@ -1,4 +1,3 @@
package pio package pio
func U8(b []byte) (i uint8) { func U8(b []byte) (i uint8) {
@ -7,85 +6,116 @@ func U8(b []byte) (i uint8) {
func U16BE(b []byte) (i uint16) { func U16BE(b []byte) (i uint16) {
i = uint16(b[0]) i = uint16(b[0])
i <<= 8; i |= uint16(b[1]) i <<= 8
i |= uint16(b[1])
return return
} }
func I16BE(b []byte) (i int16) { func I16BE(b []byte) (i int16) {
i = int16(b[0]) i = int16(b[0])
i <<= 8; i |= int16(b[1]) i <<= 8
i |= int16(b[1])
return return
} }
func I24BE(b []byte) (i int32) { func I24BE(b []byte) (i int32) {
i = int32(int8(b[0])) i = int32(int8(b[0]))
i <<= 8; i |= int32(b[1]) i <<= 8
i <<= 8; i |= int32(b[2]) i |= int32(b[1])
i <<= 8
i |= int32(b[2])
return return
} }
func U24BE(b []byte) (i uint32) { func U24BE(b []byte) (i uint32) {
i = uint32(b[0]) i = uint32(b[0])
i <<= 8; i |= uint32(b[1]) i <<= 8
i <<= 8; i |= uint32(b[2]) i |= uint32(b[1])
i <<= 8
i |= uint32(b[2])
return return
} }
func I32BE(b []byte) (i int32) { func I32BE(b []byte) (i int32) {
i = int32(int8(b[0])) i = int32(int8(b[0]))
i <<= 8; i |= int32(b[1]) i <<= 8
i <<= 8; i |= int32(b[2]) i |= int32(b[1])
i <<= 8; i |= int32(b[3]) i <<= 8
i |= int32(b[2])
i <<= 8
i |= int32(b[3])
return return
} }
func U32LE(b []byte) (i uint32) { func U32LE(b []byte) (i uint32) {
i = uint32(b[3]) i = uint32(b[3])
i <<= 8; i |= uint32(b[2]) i <<= 8
i <<= 8; i |= uint32(b[1]) i |= uint32(b[2])
i <<= 8; i |= uint32(b[0]) i <<= 8
i |= uint32(b[1])
i <<= 8
i |= uint32(b[0])
return return
} }
func U32BE(b []byte) (i uint32) { func U32BE(b []byte) (i uint32) {
i = uint32(b[0]) i = uint32(b[0])
i <<= 8; i |= uint32(b[1]) i <<= 8
i <<= 8; i |= uint32(b[2]) i |= uint32(b[1])
i <<= 8; i |= uint32(b[3]) i <<= 8
i |= uint32(b[2])
i <<= 8
i |= uint32(b[3])
return return
} }
func U40BE(b []byte) (i uint64) { func U40BE(b []byte) (i uint64) {
i = uint64(b[0]) i = uint64(b[0])
i <<= 8; i |= uint64(b[1]) i <<= 8
i <<= 8; i |= uint64(b[2]) i |= uint64(b[1])
i <<= 8; i |= uint64(b[3]) i <<= 8
i <<= 8; i |= uint64(b[4]) i |= uint64(b[2])
i <<= 8
i |= uint64(b[3])
i <<= 8
i |= uint64(b[4])
return return
} }
func U64BE(b []byte) (i uint64) { func U64BE(b []byte) (i uint64) {
i = uint64(b[0]) i = uint64(b[0])
i <<= 8; i |= uint64(b[1]) i <<= 8
i <<= 8; i |= uint64(b[2]) i |= uint64(b[1])
i <<= 8; i |= uint64(b[3]) i <<= 8
i <<= 8; i |= uint64(b[4]) i |= uint64(b[2])
i <<= 8; i |= uint64(b[5]) i <<= 8
i <<= 8; i |= uint64(b[6]) i |= uint64(b[3])
i <<= 8; i |= uint64(b[7]) 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 return
} }
func I64BE(b []byte) (i int64) { func I64BE(b []byte) (i int64) {
i = int64(int8(b[0])) i = int64(int8(b[0]))
i <<= 8; i |= int64(b[1]) i <<= 8
i <<= 8; i |= int64(b[2]) i |= int64(b[1])
i <<= 8; i |= int64(b[3]) i <<= 8
i <<= 8; i |= int64(b[4]) i |= int64(b[2])
i <<= 8; i |= int64(b[5]) i <<= 8
i <<= 8; i |= int64(b[6]) i |= int64(b[3])
i <<= 8; i |= int64(b[7]) 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 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) { for e != 0 && i < len(in) {
left := len(in[i])-off left := len(in[i]) - off
read := left read := left
if e > 0 && e < read { if e > 0 && e < read {
read = e read = e
} }
out[n] = in[i][off:off+read] out[n] = in[i][off : off+read]
n++ n++
left -= read left -= read
e -= read e -= read
@ -66,4 +66,3 @@ func VecSlice(in [][]byte, s int, e int) (out [][]byte) {
out = out[:n] out = out[:n]
return return
} }

View File

@ -1,4 +1,3 @@
package pio package pio
import ( import (
@ -6,7 +5,7 @@ import (
) )
func ExampleVec() { 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)) println(VecLen(vec))
vec = VecSlice(vec, 1, -1) vec = VecSlice(vec, 1, -1)

View File

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