From 972a362dc1af59b4e38c8a32ecad6bf44ff8a755 Mon Sep 17 00:00:00 2001 From: jinleileiking Date: Mon, 11 Dec 2017 22:23:11 +0800 Subject: [PATCH 01/13] :bug: when datalen is 0, parse failed --- format/flv/flvio/flvio.go | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/format/flv/flvio/flvio.go b/format/flv/flvio/flvio.go index aca07708..c7b1113d 100644 --- a/format/flv/flvio/flvio.go +++ b/format/flv/flvio/flvio.go @@ -2,10 +2,11 @@ package flvio import ( "fmt" - "github.com/nareix/joy4/utils/bits/pio" - "github.com/nareix/joy4/av" "io" "time" + + "github.com/nareix/joy4/av" + "github.com/nareix/joy4/utils/bits/pio" ) func TsToTime(ts int32) time.Duration { @@ -308,16 +309,18 @@ func ReadTag(r io.Reader, b []byte) (tag Tag, ts int32, err error) { return } - data := make([]byte, datalen) - if _, err = io.ReadFull(r, data); err != nil { - return - } + if datalen != 0 { + data := make([]byte, datalen) + if _, err = io.ReadFull(r, data); err != nil { + return + } - var n int - if n, err = (&tag).ParseHeader(data); err != nil { - return + var n int + if n, err = (&tag).ParseHeader(data); err != nil { + return + } + tag.Data = data[n:] } - tag.Data = data[n:] if _, err = io.ReadFull(r, b[:4]); err != nil { return From 13a58452a10a2c8e6e973a20ca0eb0d361e12323 Mon Sep 17 00:00:00 2001 From: JINLEI1 Date: Mon, 18 Dec 2017 19:41:35 +0800 Subject: [PATCH 02/13] replace nareix with jinleileiking....for temp --- av/av.go | 91 +++++++++++------------ av/avconv/avconv.go | 8 +- av/avutil/avutil.go | 2 +- av/pktque/buf.go | 2 +- av/pktque/filters.go | 2 +- av/pubsub/queue.go | 4 +- av/transcode/transcode.go | 4 +- cgo/ffmpeg/audio.go | 6 +- cgo/ffmpeg/video.go | 4 +- codec/aacparser/parser.go | 4 +- codec/codec.go | 4 +- codec/fake/fake.go | 2 +- codec/h264parser/parser.go | 6 +- examples/audio_decode/main.go | 8 +- examples/http_flv_and_rtmp_server/main.go | 10 +-- examples/open_probe_file/main.go | 6 +- examples/rtmp_publish/main.go | 8 +- examples/rtmp_server_channels/main.go | 12 +-- examples/rtmp_server_proxy/main.go | 6 +- examples/rtmp_server_speex_to_aac/main.go | 12 +-- examples/transcode/main.go | 10 +-- format/aac/aac.go | 6 +- format/flv/flv.go | 25 +++++-- format/flv/flvio/amf0.go | 2 +- format/flv/flvio/flvio.go | 28 ++++++- format/format.go | 14 ++-- format/mp4/demuxer.go | 8 +- format/mp4/handler.go | 4 +- format/mp4/mp4io/atoms.go | 2 +- format/mp4/mp4io/gen/gen.go | 2 +- format/mp4/mp4io/mp4io.go | 2 +- format/mp4/muxer.go | 10 +-- format/mp4/stream.go | 4 +- format/rtmp/rtmp.go | 10 +-- format/rtsp/client.go | 14 ++-- format/rtsp/sdp/parser.go | 2 +- format/rtsp/stream.go | 4 +- format/ts/demuxer.go | 10 +-- format/ts/handler.go | 4 +- format/ts/muxer.go | 8 +- format/ts/stream.go | 4 +- format/ts/tsio/tsio.go | 2 +- 42 files changed, 204 insertions(+), 172 deletions(-) diff --git a/av/av.go b/av/av.go index 76b1f615..97c4d3a2 100644 --- a/av/av.go +++ b/av/av.go @@ -1,4 +1,3 @@ - // Package av defines basic interfaces and data structures of container demux/mux and audio encode/decode. package av @@ -11,17 +10,17 @@ import ( type SampleFormat uint8 const ( - U8 = SampleFormat(iota + 1) // 8-bit unsigned integer - S16 // signed 16-bit integer - S32 // signed 32-bit integer - FLT // 32-bit float - DBL // 64-bit float - U8P // 8-bit unsigned integer in planar - S16P // signed 16-bit integer in planar - S32P // signed 32-bit integer in planar - FLTP // 32-bit float in planar - DBLP // 64-bit float in planar - U32 // unsigned 32-bit integer + U8 = SampleFormat(iota + 1) // 8-bit unsigned integer + S16 // signed 16-bit integer + S32 // signed 32-bit integer + FLT // 32-bit float + DBL // 64-bit float + U8P // 8-bit unsigned integer in planar + S16P // signed 16-bit integer in planar + S32P // signed 32-bit integer in planar + FLTP // 32-bit float in planar + DBLP // 64-bit float in planar + U32 // unsigned 32-bit integer ) func (self SampleFormat) BytesPerSample() int { @@ -116,11 +115,11 @@ func (self ChannelLayout) Count() (n int) { type CodecType uint32 var ( - H264 = MakeVideoCodecType(avCodecTypeMagic + 1) - AAC = MakeAudioCodecType(avCodecTypeMagic + 1) - PCM_MULAW = MakeAudioCodecType(avCodecTypeMagic + 2) - PCM_ALAW = MakeAudioCodecType(avCodecTypeMagic + 3) - SPEEX = MakeAudioCodecType(avCodecTypeMagic + 4) + H264 = MakeVideoCodecType(avCodecTypeMagic + 1) + AAC = MakeAudioCodecType(avCodecTypeMagic + 1) + PCM_MULAW = MakeAudioCodecType(avCodecTypeMagic + 2) + PCM_ALAW = MakeAudioCodecType(avCodecTypeMagic + 3) + SPEEX = MakeAudioCodecType(avCodecTypeMagic + 4) NELLYMOSER = MakeAudioCodecType(avCodecTypeMagic + 5) ) @@ -171,7 +170,7 @@ const avCodecTypeMagic = 233333 // can be converted to VideoCodecData or AudioCodecData using: // // codecdata.(AudioCodecData) or codecdata.(VideoCodecData) -// +// // for H264, CodecData is AVCDecoderConfigure bytes, includes SPS/PPS. type CodecData interface { Type() CodecType // Video/Audio codec type @@ -179,15 +178,15 @@ type CodecData interface { type VideoCodecData interface { CodecData - Width() int // Video height + Width() int // Video height Height() int // Video width } type AudioCodecData interface { CodecData - SampleFormat() SampleFormat // audio sample format - SampleRate() int // audio sample rate - ChannelLayout() ChannelLayout // audio channel layout + SampleFormat() SampleFormat // audio sample format + SampleRate() int // audio sample rate + ChannelLayout() ChannelLayout // audio channel layout PacketDuration([]byte) (time.Duration, error) // get audio compressed packet duration } @@ -196,16 +195,16 @@ type PacketWriter interface { } type PacketReader interface { - ReadPacket() (Packet,error) + ReadPacket() (Packet, error) } // Muxer describes the steps of writing compressed audio/video packets into container formats like MP4/FLV/MPEG-TS. -// +// // Container formats, rtmp.Conn, and transcode.Muxer implements Muxer interface. type Muxer interface { WriteHeader([]CodecData) error // write the file header - PacketWriter // write compressed audio/video packets - WriteTrailer() error // finish writing file, this func can be called only once + PacketWriter // write compressed audio/video packets + WriteTrailer() error // finish writing file, this func can be called only once } // Muxer with Close() method @@ -216,7 +215,7 @@ type MuxCloser interface { // Demuxer can read compressed audio/video packets from container formats like MP4/FLV/MPEG-TS. type Demuxer interface { - PacketReader // read compressed audio/video packets + PacketReader // read compressed audio/video packets Streams() ([]CodecData, error) // reads the file header, contains video/audio meta infomations } @@ -228,20 +227,21 @@ type DemuxCloser interface { // Packet stores compressed audio/video data. type Packet struct { - IsKeyFrame bool // video packet is key frame - Idx int8 // stream index in container format + IsKeyFrame bool // video packet is key frame + Idx int8 // stream index in container format CompositionTime time.Duration // packet presentation time minus decode time for H264 B-Frame - Time time.Duration // packet decode time - Data []byte // packet data + AVCPacketType string + Time time.Duration // packet decode time + Data []byte // packet data } // Raw audio frame. type AudioFrame struct { - SampleFormat SampleFormat // audio sample format, e.g: S16,FLTP,... + SampleFormat SampleFormat // audio sample format, e.g: S16,FLTP,... ChannelLayout ChannelLayout // audio channel layout, e.g: CH_MONO,CH_STEREO,... - SampleCount int // sample count in this frame - SampleRate int // sample rate - Data [][]byte // data array for planar format len(Data) > 1 + SampleCount int // sample count in this frame + SampleRate int // sample rate + Data [][]byte // data array for planar format len(Data) > 1 } func (self AudioFrame) Duration() time.Duration { @@ -291,26 +291,25 @@ func (self AudioFrame) Concat(in AudioFrame) (out AudioFrame) { // AudioEncoder can encode raw audio frame into compressed audio packets. // cgo/ffmpeg inplements AudioEncoder, using ffmpeg.NewAudioEncoder to create it. type AudioEncoder interface { - CodecData() (AudioCodecData, error) // encoder's codec data can put into container - Encode(AudioFrame) ([][]byte, error) // encode raw audio frame into compressed pakcet(s) - Close() // close encoder, free cgo contexts - SetSampleRate(int) (error) // set encoder sample rate - SetChannelLayout(ChannelLayout) (error) // set encoder channel layout - SetSampleFormat(SampleFormat) (error) // set encoder sample format - SetBitrate(int) (error) // set encoder bitrate - SetOption(string,interface{}) (error) // encoder setopt, in ffmpeg is av_opt_set_dict() - GetOption(string,interface{}) (error) // encoder getopt + CodecData() (AudioCodecData, error) // encoder's codec data can put into container + Encode(AudioFrame) ([][]byte, error) // encode raw audio frame into compressed pakcet(s) + Close() // close encoder, free cgo contexts + SetSampleRate(int) error // set encoder sample rate + SetChannelLayout(ChannelLayout) error // set encoder channel layout + SetSampleFormat(SampleFormat) error // set encoder sample format + SetBitrate(int) error // set encoder bitrate + SetOption(string, interface{}) error // encoder setopt, in ffmpeg is av_opt_set_dict() + GetOption(string, interface{}) error // encoder getopt } // AudioDecoder can decode compressed audio packets into raw audio frame. // use ffmpeg.NewAudioDecoder to create it. type AudioDecoder interface { Decode([]byte) (bool, AudioFrame, error) // decode one compressed audio packet - Close() // close decode, free cgo contexts + Close() // close decode, free cgo contexts } // AudioResampler can convert raw audio frames in different sample rate/format/channel layout. type AudioResampler interface { Resample(AudioFrame) (AudioFrame, error) // convert raw audio frames } - diff --git a/av/avconv/avconv.go b/av/avconv/avconv.go index fa8a5a76..f523f367 100644 --- a/av/avconv/avconv.go +++ b/av/avconv/avconv.go @@ -4,10 +4,10 @@ import ( "fmt" "io" "time" - "github.com/nareix/joy4/av/avutil" - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/av/pktque" - "github.com/nareix/joy4/av/transcode" + "github.com/jinleileiking/joy4/av/avutil" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/av/pktque" + "github.com/jinleileiking/joy4/av/transcode" ) var Debug bool diff --git a/av/avutil/avutil.go b/av/avutil/avutil.go index 59ebd4a0..3437ee6d 100644 --- a/av/avutil/avutil.go +++ b/av/avutil/avutil.go @@ -5,7 +5,7 @@ import ( "strings" "fmt" "bytes" - "github.com/nareix/joy4/av" + "github.com/jinleileiking/joy4/av" "net/url" "os" "path" diff --git a/av/pktque/buf.go b/av/pktque/buf.go index 6624f559..fcb9ac6d 100644 --- a/av/pktque/buf.go +++ b/av/pktque/buf.go @@ -1,7 +1,7 @@ package pktque import ( - "github.com/nareix/joy4/av" + "github.com/jinleileiking/joy4/av" ) type Buf struct { diff --git a/av/pktque/filters.go b/av/pktque/filters.go index 83b943d2..2e90fa70 100644 --- a/av/pktque/filters.go +++ b/av/pktque/filters.go @@ -4,7 +4,7 @@ package pktque import ( "time" - "github.com/nareix/joy4/av" + "github.com/jinleileiking/joy4/av" ) type Filter interface { diff --git a/av/pubsub/queue.go b/av/pubsub/queue.go index 10b3f735..a1a89307 100644 --- a/av/pubsub/queue.go +++ b/av/pubsub/queue.go @@ -2,8 +2,8 @@ package pubsub import ( - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/av/pktque" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/av/pktque" "io" "sync" "time" diff --git a/av/transcode/transcode.go b/av/transcode/transcode.go index 6f512d97..ff514e24 100644 --- a/av/transcode/transcode.go +++ b/av/transcode/transcode.go @@ -5,8 +5,8 @@ package transcode import ( "fmt" "time" - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/av/pktque" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/av/pktque" ) var Debug bool diff --git a/cgo/ffmpeg/audio.go b/cgo/ffmpeg/audio.go index fbd676dc..2f8b1bac 100644 --- a/cgo/ffmpeg/audio.go +++ b/cgo/ffmpeg/audio.go @@ -16,9 +16,9 @@ import ( "runtime" "fmt" "time" - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/av/avutil" - "github.com/nareix/joy4/codec/aacparser" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/av/avutil" + "github.com/jinleileiking/joy4/codec/aacparser" ) const debug = false diff --git a/cgo/ffmpeg/video.go b/cgo/ffmpeg/video.go index 085b229a..5059e1b3 100644 --- a/cgo/ffmpeg/video.go +++ b/cgo/ffmpeg/video.go @@ -14,8 +14,8 @@ import ( "fmt" "image" "reflect" - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/codec/h264parser" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/codec/h264parser" ) type VideoDecoder struct { diff --git a/codec/aacparser/parser.go b/codec/aacparser/parser.go index 6432574a..f555b567 100644 --- a/codec/aacparser/parser.go +++ b/codec/aacparser/parser.go @@ -1,8 +1,8 @@ package aacparser import ( - "github.com/nareix/joy4/utils/bits" - "github.com/nareix/joy4/av" + "github.com/jinleileiking/joy4/utils/bits" + "github.com/jinleileiking/joy4/av" "time" "fmt" "bytes" diff --git a/codec/codec.go b/codec/codec.go index d37df77c..ac13f4f5 100644 --- a/codec/codec.go +++ b/codec/codec.go @@ -1,8 +1,8 @@ package codec import ( - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/codec/fake" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/codec/fake" "time" ) diff --git a/codec/fake/fake.go b/codec/fake/fake.go index 51e056f4..82568d6f 100644 --- a/codec/fake/fake.go +++ b/codec/fake/fake.go @@ -1,7 +1,7 @@ package fake import ( - "github.com/nareix/joy4/av" + "github.com/jinleileiking/joy4/av" ) type CodecData struct { diff --git a/codec/h264parser/parser.go b/codec/h264parser/parser.go index 35c8d837..87aa7210 100644 --- a/codec/h264parser/parser.go +++ b/codec/h264parser/parser.go @@ -2,9 +2,9 @@ package h264parser import ( - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/utils/bits" - "github.com/nareix/joy4/utils/bits/pio" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/utils/bits" + "github.com/jinleileiking/joy4/utils/bits/pio" "fmt" "bytes" ) diff --git a/examples/audio_decode/main.go b/examples/audio_decode/main.go index 99594bed..260f97a0 100644 --- a/examples/audio_decode/main.go +++ b/examples/audio_decode/main.go @@ -2,10 +2,10 @@ package main import ( - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/format" - "github.com/nareix/joy4/av/avutil" - "github.com/nareix/joy4/cgo/ffmpeg" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/format" + "github.com/jinleileiking/joy4/av/avutil" + "github.com/jinleileiking/joy4/cgo/ffmpeg" ) // need ffmpeg installed diff --git a/examples/http_flv_and_rtmp_server/main.go b/examples/http_flv_and_rtmp_server/main.go index 28916973..27d02ca4 100644 --- a/examples/http_flv_and_rtmp_server/main.go +++ b/examples/http_flv_and_rtmp_server/main.go @@ -4,11 +4,11 @@ import ( "sync" "io" "net/http" - "github.com/nareix/joy4/format" - "github.com/nareix/joy4/av/avutil" - "github.com/nareix/joy4/av/pubsub" - "github.com/nareix/joy4/format/rtmp" - "github.com/nareix/joy4/format/flv" + "github.com/jinleileiking/joy4/format" + "github.com/jinleileiking/joy4/av/avutil" + "github.com/jinleileiking/joy4/av/pubsub" + "github.com/jinleileiking/joy4/format/rtmp" + "github.com/jinleileiking/joy4/format/flv" ) func init() { diff --git a/examples/open_probe_file/main.go b/examples/open_probe_file/main.go index 4960fdd9..db0eac14 100644 --- a/examples/open_probe_file/main.go +++ b/examples/open_probe_file/main.go @@ -2,9 +2,9 @@ package main import ( "fmt" - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/av/avutil" - "github.com/nareix/joy4/format" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/av/avutil" + "github.com/jinleileiking/joy4/format" ) func init() { diff --git a/examples/rtmp_publish/main.go b/examples/rtmp_publish/main.go index 4c39af8b..4fc4a1be 100644 --- a/examples/rtmp_publish/main.go +++ b/examples/rtmp_publish/main.go @@ -1,10 +1,10 @@ package main import ( - "github.com/nareix/joy4/av/pktque" - "github.com/nareix/joy4/format" - "github.com/nareix/joy4/av/avutil" - "github.com/nareix/joy4/format/rtmp" + "github.com/jinleileiking/joy4/av/pktque" + "github.com/jinleileiking/joy4/format" + "github.com/jinleileiking/joy4/av/avutil" + "github.com/jinleileiking/joy4/format/rtmp" ) func init() { diff --git a/examples/rtmp_server_channels/main.go b/examples/rtmp_server_channels/main.go index 36170c0d..50d47f95 100644 --- a/examples/rtmp_server_channels/main.go +++ b/examples/rtmp_server_channels/main.go @@ -2,12 +2,12 @@ package main import ( "fmt" - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/av/avutil" - "github.com/nareix/joy4/av/pktque" - "github.com/nareix/joy4/av/pubsub" - "github.com/nareix/joy4/format" - "github.com/nareix/joy4/format/rtmp" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/av/avutil" + "github.com/jinleileiking/joy4/av/pktque" + "github.com/jinleileiking/joy4/av/pubsub" + "github.com/jinleileiking/joy4/format" + "github.com/jinleileiking/joy4/format/rtmp" "sync" "time" ) diff --git a/examples/rtmp_server_proxy/main.go b/examples/rtmp_server_proxy/main.go index 43fd20d8..d171f1f5 100644 --- a/examples/rtmp_server_proxy/main.go +++ b/examples/rtmp_server_proxy/main.go @@ -3,9 +3,9 @@ package main import ( "fmt" "strings" - "github.com/nareix/joy4/format" - "github.com/nareix/joy4/av/avutil" - "github.com/nareix/joy4/format/rtmp" + "github.com/jinleileiking/joy4/format" + "github.com/jinleileiking/joy4/av/avutil" + "github.com/jinleileiking/joy4/format/rtmp" ) func init() { diff --git a/examples/rtmp_server_speex_to_aac/main.go b/examples/rtmp_server_speex_to_aac/main.go index 3f00b371..aecb5222 100644 --- a/examples/rtmp_server_speex_to_aac/main.go +++ b/examples/rtmp_server_speex_to_aac/main.go @@ -1,12 +1,12 @@ package main import ( - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/av/transcode" - "github.com/nareix/joy4/format" - "github.com/nareix/joy4/av/avutil" - "github.com/nareix/joy4/format/rtmp" - "github.com/nareix/joy4/cgo/ffmpeg" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/av/transcode" + "github.com/jinleileiking/joy4/format" + "github.com/jinleileiking/joy4/av/avutil" + "github.com/jinleileiking/joy4/format/rtmp" + "github.com/jinleileiking/joy4/cgo/ffmpeg" ) // need ffmpeg with libspeex and libfdkaac installed diff --git a/examples/transcode/main.go b/examples/transcode/main.go index 29101193..42ce3a15 100644 --- a/examples/transcode/main.go +++ b/examples/transcode/main.go @@ -1,11 +1,11 @@ package main import ( - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/av/transcode" - "github.com/nareix/joy4/format" - "github.com/nareix/joy4/av/avutil" - "github.com/nareix/joy4/cgo/ffmpeg" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/av/transcode" + "github.com/jinleileiking/joy4/format" + "github.com/jinleileiking/joy4/av/avutil" + "github.com/jinleileiking/joy4/cgo/ffmpeg" ) // need ffmpeg with libfdkaac installed diff --git a/format/aac/aac.go b/format/aac/aac.go index 5a65a874..fbe74810 100644 --- a/format/aac/aac.go +++ b/format/aac/aac.go @@ -2,9 +2,9 @@ package aac import ( - "github.com/nareix/joy4/av/avutil" - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/codec/aacparser" + "github.com/jinleileiking/joy4/av/avutil" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/codec/aacparser" "time" "fmt" "io" diff --git a/format/flv/flv.go b/format/flv/flv.go index 6f07da64..eb241def 100644 --- a/format/flv/flv.go +++ b/format/flv/flv.go @@ -3,15 +3,16 @@ package flv import ( "bufio" "fmt" - "github.com/nareix/joy4/utils/bits/pio" - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/av/avutil" - "github.com/nareix/joy4/codec" - "github.com/nareix/joy4/codec/aacparser" - "github.com/nareix/joy4/codec/fake" - "github.com/nareix/joy4/codec/h264parser" - "github.com/nareix/joy4/format/flv/flvio" "io" + + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/av/avutil" + "github.com/jinleileiking/joy4/codec" + "github.com/jinleileiking/joy4/codec/aacparser" + "github.com/jinleileiking/joy4/codec/fake" + "github.com/jinleileiking/joy4/codec/h264parser" + "github.com/jinleileiking/joy4/format/flv/flvio" + "github.com/jinleileiking/joy4/utils/bits/pio" ) var MaxProbePacketCount = 20 @@ -91,9 +92,12 @@ func (self *Prober) PushTag(tag flvio.Tag, timestamp int32) (err error) { err = fmt.Errorf("flv: h264 seqhdr invalid") return } + + // spew.Dump(stream) self.VideoStreamIdx = len(self.Streams) self.Streams = append(self.Streams, stream) self.GotVideo = true + self.CacheTag(tag, timestamp) } case flvio.AVC_NALU: @@ -171,7 +175,12 @@ func (self *Prober) TagToPacket(tag flvio.Tag, timestamp int32) (pkt av.Packet, ok = true pkt.Data = tag.Data pkt.CompositionTime = flvio.TsToTime(tag.CompositionTime) + pkt.AVCPacketType = "NALU" pkt.IsKeyFrame = tag.FrameType == flvio.FRAME_KEY + case flvio.AVC_SEQHDR: + pkt.AVCPacketType = "SEQHDR" + pkt.IsKeyFrame = tag.FrameType == flvio.FRAME_KEY + pkt.Data = tag.Data } case flvio.TAG_AUDIO: diff --git a/format/flv/flvio/amf0.go b/format/flv/flvio/amf0.go index 05b4a037..d9feef87 100644 --- a/format/flv/flvio/amf0.go +++ b/format/flv/flvio/amf0.go @@ -5,7 +5,7 @@ import ( "math" "fmt" "time" - "github.com/nareix/joy4/utils/bits/pio" + "github.com/jinleileiking/joy4/utils/bits/pio" ) type AMF0ParseError struct { diff --git a/format/flv/flvio/flvio.go b/format/flv/flvio/flvio.go index c7b1113d..010d9b8c 100644 --- a/format/flv/flvio/flvio.go +++ b/format/flv/flvio/flvio.go @@ -1,12 +1,14 @@ package flvio import ( + "Gout/joy4/codec/h264parser" "fmt" "io" "time" - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/utils/bits/pio" + "github.com/davecgh/go-spew/spew" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/utils/bits/pio" ) func TsToTime(ts int32) time.Duration { @@ -151,6 +153,8 @@ type Tag struct { CompositionTime int32 Data []byte + + NALUFormat string } func (self Tag) ChannelLayout() av.ChannelLayout { @@ -320,11 +324,31 @@ func ReadTag(r io.Reader, b []byte) (tag Tag, ts int32, err error) { return } tag.Data = data[n:] + + if tag.Type == TAG_VIDEO { + _, nal_type := h264parser.SplitNALUs(tag.Data) + + if nal_type == h264parser.NALU_AVCC { + tag.NALUFormat = "AVCC" + } + + if nal_type == h264parser.NALU_RAW { + tag.NALUFormat = "RAW" + } + + if nal_type == h264parser.NALU_ANNEXB { + tag.NALUFormat = "ANNEXB" + } + + spew.Dump(tag.NALUFormat) + } } + // b[:4] ---> preTagSize if _, err = io.ReadFull(r, b[:4]); err != nil { return } + return } diff --git a/format/format.go b/format/format.go index 1c07ac8f..f490c717 100644 --- a/format/format.go +++ b/format/format.go @@ -1,13 +1,13 @@ package format import ( - "github.com/nareix/joy4/format/mp4" - "github.com/nareix/joy4/format/ts" - "github.com/nareix/joy4/format/rtmp" - "github.com/nareix/joy4/format/rtsp" - "github.com/nareix/joy4/format/flv" - "github.com/nareix/joy4/format/aac" - "github.com/nareix/joy4/av/avutil" + "github.com/jinleileiking/joy4/format/mp4" + "github.com/jinleileiking/joy4/format/ts" + "github.com/jinleileiking/joy4/format/rtmp" + "github.com/jinleileiking/joy4/format/rtsp" + "github.com/jinleileiking/joy4/format/flv" + "github.com/jinleileiking/joy4/format/aac" + "github.com/jinleileiking/joy4/av/avutil" ) func RegisterAll() { diff --git a/format/mp4/demuxer.go b/format/mp4/demuxer.go index dbd91376..c8868096 100644 --- a/format/mp4/demuxer.go +++ b/format/mp4/demuxer.go @@ -3,10 +3,10 @@ package mp4 import ( "time" "fmt" - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/codec/aacparser" - "github.com/nareix/joy4/codec/h264parser" - "github.com/nareix/joy4/format/mp4/mp4io" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/codec/aacparser" + "github.com/jinleileiking/joy4/codec/h264parser" + "github.com/jinleileiking/joy4/format/mp4/mp4io" "io" ) diff --git a/format/mp4/handler.go b/format/mp4/handler.go index aeef1cc3..a3b4cbe7 100644 --- a/format/mp4/handler.go +++ b/format/mp4/handler.go @@ -2,8 +2,8 @@ package mp4 import ( "io" - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/av/avutil" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/av/avutil" ) var CodecTypes = []av.CodecType{av.H264, av.AAC} diff --git a/format/mp4/mp4io/atoms.go b/format/mp4/mp4io/atoms.go index c90485cc..f5163a12 100644 --- a/format/mp4/mp4io/atoms.go +++ b/format/mp4/mp4io/atoms.go @@ -1,6 +1,6 @@ package mp4io -import "github.com/nareix/joy4/utils/bits/pio" +import "github.com/jinleileiking/joy4/utils/bits/pio" import "time" const MOOF = Tag(0x6d6f6f66) diff --git a/format/mp4/mp4io/gen/gen.go b/format/mp4/mp4io/gen/gen.go index 1a2857f3..8b9ade84 100644 --- a/format/mp4/mp4io/gen/gen.go +++ b/format/mp4/mp4io/gen/gen.go @@ -967,7 +967,7 @@ func genatoms(filename, outfilename string) { &ast.GenDecl{ Tok: token.IMPORT, Specs: []ast.Spec{ - &ast.ImportSpec{Path: &ast.BasicLit{Kind: token.STRING, Value: `"github.com/nareix/joy4/utils/bits/pio"`}}, + &ast.ImportSpec{Path: &ast.BasicLit{Kind: token.STRING, Value: `"github.com/jinleileiking/joy4/utils/bits/pio"`}}, }, }, &ast.GenDecl{ diff --git a/format/mp4/mp4io/mp4io.go b/format/mp4/mp4io/mp4io.go index 0227a843..f868d95e 100644 --- a/format/mp4/mp4io/mp4io.go +++ b/format/mp4/mp4io/mp4io.go @@ -2,7 +2,7 @@ package mp4io import ( - "github.com/nareix/joy4/utils/bits/pio" + "github.com/jinleileiking/joy4/utils/bits/pio" "os" "io" "fmt" diff --git a/format/mp4/muxer.go b/format/mp4/muxer.go index d1ef7e0c..c02bccab 100644 --- a/format/mp4/muxer.go +++ b/format/mp4/muxer.go @@ -3,11 +3,11 @@ package mp4 import ( "fmt" "time" - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/codec/aacparser" - "github.com/nareix/joy4/codec/h264parser" - "github.com/nareix/joy4/format/mp4/mp4io" - "github.com/nareix/joy4/utils/bits/pio" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/codec/aacparser" + "github.com/jinleileiking/joy4/codec/h264parser" + "github.com/jinleileiking/joy4/format/mp4/mp4io" + "github.com/jinleileiking/joy4/utils/bits/pio" "io" "bufio" ) diff --git a/format/mp4/stream.go b/format/mp4/stream.go index b837cd99..5889372a 100644 --- a/format/mp4/stream.go +++ b/format/mp4/stream.go @@ -1,8 +1,8 @@ package mp4 import ( - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/format/mp4/mp4io" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/format/mp4/mp4io" "time" ) diff --git a/format/rtmp/rtmp.go b/format/rtmp/rtmp.go index d7cd56df..23da95f2 100644 --- a/format/rtmp/rtmp.go +++ b/format/rtmp/rtmp.go @@ -8,11 +8,11 @@ import ( "crypto/sha256" "encoding/hex" "fmt" - "github.com/nareix/joy4/utils/bits/pio" - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/av/avutil" - "github.com/nareix/joy4/format/flv" - "github.com/nareix/joy4/format/flv/flvio" + "github.com/jinleileiking/joy4/utils/bits/pio" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/av/avutil" + "github.com/jinleileiking/joy4/format/flv" + "github.com/jinleileiking/joy4/format/flv/flvio" "io" "net" "net/url" diff --git a/format/rtsp/client.go b/format/rtsp/client.go index 28f8592c..de5cf4cc 100644 --- a/format/rtsp/client.go +++ b/format/rtsp/client.go @@ -8,13 +8,13 @@ import ( "encoding/binary" "encoding/hex" "fmt" - "github.com/nareix/joy4/utils/bits/pio" - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/av/avutil" - "github.com/nareix/joy4/codec" - "github.com/nareix/joy4/codec/aacparser" - "github.com/nareix/joy4/codec/h264parser" - "github.com/nareix/joy4/format/rtsp/sdp" + "github.com/jinleileiking/joy4/utils/bits/pio" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/av/avutil" + "github.com/jinleileiking/joy4/codec" + "github.com/jinleileiking/joy4/codec/aacparser" + "github.com/jinleileiking/joy4/codec/h264parser" + "github.com/jinleileiking/joy4/format/rtsp/sdp" "io" "net" "net/textproto" diff --git a/format/rtsp/sdp/parser.go b/format/rtsp/sdp/parser.go index a092ddfc..ff69b006 100644 --- a/format/rtsp/sdp/parser.go +++ b/format/rtsp/sdp/parser.go @@ -4,7 +4,7 @@ import ( "encoding/base64" "encoding/hex" "fmt" - "github.com/nareix/joy4/av" + "github.com/jinleileiking/joy4/av" "strconv" "strings" ) diff --git a/format/rtsp/stream.go b/format/rtsp/stream.go index f3497cdb..8160270d 100644 --- a/format/rtsp/stream.go +++ b/format/rtsp/stream.go @@ -1,8 +1,8 @@ package rtsp import ( - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/format/rtsp/sdp" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/format/rtsp/sdp" "time" ) diff --git a/format/ts/demuxer.go b/format/ts/demuxer.go index df9c0cf1..7f726af7 100644 --- a/format/ts/demuxer.go +++ b/format/ts/demuxer.go @@ -4,11 +4,11 @@ import ( "bufio" "fmt" "time" - "github.com/nareix/joy4/utils/bits/pio" - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/format/ts/tsio" - "github.com/nareix/joy4/codec/aacparser" - "github.com/nareix/joy4/codec/h264parser" + "github.com/jinleileiking/joy4/utils/bits/pio" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/format/ts/tsio" + "github.com/jinleileiking/joy4/codec/aacparser" + "github.com/jinleileiking/joy4/codec/h264parser" "io" ) diff --git a/format/ts/handler.go b/format/ts/handler.go index 068ddf97..61424b3f 100644 --- a/format/ts/handler.go +++ b/format/ts/handler.go @@ -2,8 +2,8 @@ package ts import ( "io" - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/av/avutil" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/av/avutil" ) func Handler(h *avutil.RegisterHandler) { diff --git a/format/ts/muxer.go b/format/ts/muxer.go index 030a1c13..55a6c213 100644 --- a/format/ts/muxer.go +++ b/format/ts/muxer.go @@ -2,10 +2,10 @@ package ts import ( "fmt" - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/codec/aacparser" - "github.com/nareix/joy4/codec/h264parser" - "github.com/nareix/joy4/format/ts/tsio" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/codec/aacparser" + "github.com/jinleileiking/joy4/codec/h264parser" + "github.com/jinleileiking/joy4/format/ts/tsio" "io" "time" ) diff --git a/format/ts/stream.go b/format/ts/stream.go index 36b8831f..d75ec205 100644 --- a/format/ts/stream.go +++ b/format/ts/stream.go @@ -2,8 +2,8 @@ package ts import ( "time" - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/format/ts/tsio" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/format/ts/tsio" ) type Stream struct { diff --git a/format/ts/tsio/tsio.go b/format/ts/tsio/tsio.go index ee4563ed..10d04105 100644 --- a/format/ts/tsio/tsio.go +++ b/format/ts/tsio/tsio.go @@ -5,7 +5,7 @@ import ( "io" "time" "fmt" - "github.com/nareix/joy4/utils/bits/pio" + "github.com/jinleileiking/joy4/utils/bits/pio" ) const ( From 0151a833940788f1448f94d089a0ea75342f09e9 Mon Sep 17 00:00:00 2001 From: JINLEI1 Date: Mon, 18 Dec 2017 21:13:12 +0800 Subject: [PATCH 03/13] add nalus --- av/av.go | 9 +++- codec/h264parser/parser.go | 86 +++++++++++++++++++++++++------------- format/flv/flv.go | 2 + format/flv/flvio/flvio.go | 19 +++++++-- 4 files changed, 83 insertions(+), 33 deletions(-) diff --git a/av/av.go b/av/av.go index 97c4d3a2..2babbabe 100644 --- a/av/av.go +++ b/av/av.go @@ -4,6 +4,8 @@ package av import ( "fmt" "time" + + "github.com/jinleileiking/joy4/common" ) // Audio sample format. @@ -231,8 +233,11 @@ type Packet struct { Idx int8 // stream index in container format CompositionTime time.Duration // packet presentation time minus decode time for H264 B-Frame AVCPacketType string - Time time.Duration // packet decode time - Data []byte // packet data + NALUFormat string + NALUInfos []common.TNALUInfo + + Time time.Duration // packet decode time + Data []byte // packet data } // Raw audio frame. diff --git a/codec/h264parser/parser.go b/codec/h264parser/parser.go index 87aa7210..48a432bb 100644 --- a/codec/h264parser/parser.go +++ b/codec/h264parser/parser.go @@ -1,12 +1,13 @@ - package h264parser import ( + "bytes" + "fmt" + "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/common" "github.com/jinleileiking/joy4/utils/bits" "github.com/jinleileiking/joy4/utils/bits/pio" - "fmt" - "bytes" ) const ( @@ -131,7 +132,7 @@ Annex B is commonly used in live and streaming formats such as transport streams 2. AVCC The other common method of storing an H.264 stream is the AVCC format. In this format, each NALU is preceded with its length (in big endian format). This method is easier to parse, but you lose the byte alignment features of Annex B. Just to complicate things, the length may be encoded using 1, 2 or 4 bytes. This value is stored in a header object. This header is often called ‘extradata’ or ‘sequence header’. Its basic format is as follows: -bits +bits 8 version ( always 0x01 ) 8 avc profile ( sps[0][1] ) 8 avc compatibility ( sps[0][2] ) @@ -199,8 +200,8 @@ Additionally, there is a new variable called NALULengthSizeMinusOne. This confus An advantage to this format is the ability to configure the decoder at the start and jump into the middle of a stream. This is a common use case where the media is available on a random access medium such as a hard drive, and is therefore used in common container formats such as MP4 and MKV. */ -var StartCodeBytes = []byte{0,0,1} -var AUDBytes = []byte{0,0,0,1,0x9,0xf0,0,0,0,1} // AUD +var StartCodeBytes = []byte{0, 0, 1} +var AUDBytes = []byte{0, 0, 0, 1, 0x9, 0xf0, 0, 0, 0, 1} // AUD func CheckNALUsType(b []byte) (typ int) { _, typ = SplitNALUs(b) @@ -499,9 +500,9 @@ func ParseSPS(data []byte) (self SPSInfo, err error) { } type CodecData struct { - Record []byte + Record []byte RecordInfo AVCDecoderConfRecord - SPSInfo SPSInfo + SPSInfo SPSInfo } func (self CodecData) Type() av.CodecType { @@ -589,8 +590,8 @@ func (self *AVCDecoderConfRecord) Unmarshal(b []byte) (n int, err error) { self.AVCProfileIndication = b[1] self.ProfileCompatibility = b[2] self.AVCLevelIndication = b[3] - self.LengthSizeMinusOne = b[4]&0x03 - spscount := int(b[5]&0x1f) + self.LengthSizeMinusOne = b[4] & 0x03 + spscount := int(b[5] & 0x1f) n += 6 for i := 0; i < spscount; i++ { @@ -638,10 +639,10 @@ func (self *AVCDecoderConfRecord) Unmarshal(b []byte) (n int, err error) { func (self AVCDecoderConfRecord) Len() (n int) { n = 7 for _, sps := range self.SPS { - n += 2+len(sps) + n += 2 + len(sps) } for _, pps := range self.PPS { - n += 2+len(pps) + n += 2 + len(pps) } return } @@ -651,8 +652,8 @@ func (self AVCDecoderConfRecord) Marshal(b []byte) (n int) { b[1] = self.AVCProfileIndication b[2] = self.ProfileCompatibility b[3] = self.AVCLevelIndication - b[4] = self.LengthSizeMinusOne|0xfc - b[5] = uint8(len(self.SPS))|0xe0 + b[4] = self.LengthSizeMinusOne | 0xfc + b[5] = uint8(len(self.SPS)) | 0xe0 n += 6 for _, sps := range self.SPS { @@ -690,28 +691,32 @@ func (self SliceType) String() string { } const ( - SLICE_P = iota+1 + SLICE_P = iota + 1 SLICE_B SLICE_I ) -func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, err error) { +func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, info common.TNALUInfo, err error) { + + info.RefIdc = (int(packet[0]&0x1f) >> 5) + + info.UnitType = MAP_UNIT_TYPE[int(packet[0]&0x1f)] if len(packet) <= 1 { err = fmt.Errorf("h264parser: packet too short to parse slice header") return } - nal_unit_type := packet[0]&0x1f - switch nal_unit_type { - case 1,2,5,19: - // slice_layer_without_partitioning_rbsp - // slice_data_partition_a_layer_rbsp + // nal_unit_type := packet[0] & 0x1f + // switch nal_unit_type { + // case 1, 2, 5, 19: + // // slice_layer_without_partitioning_rbsp + // // slice_data_partition_a_layer_rbsp - default: - err = fmt.Errorf("h264parser: nal_unit_type=%d has no slice header", nal_unit_type) - return - } + // default: + // err = fmt.Errorf("h264parser: nal_unit_type=%d has no slice header", nal_unit_type) + // return + // } r := &bits.GolombBitReader{R: bytes.NewReader(packet[1:])} @@ -727,11 +732,11 @@ func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, err error) { } switch u { - case 0,3,5,8: + case 0, 3, 5, 8: sliceType = SLICE_P - case 1,6: + case 1, 6: sliceType = SLICE_B - case 2,4,7,9: + case 2, 4, 7, 9: sliceType = SLICE_I default: err = fmt.Errorf("h264parser: slice_type=%d invalid", u) @@ -741,3 +746,28 @@ func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, err error) { return } +var MAP_UNIT_TYPE map[int]string + +func init() { + MAP_UNIT_TYPE = map[int]string{ + 0: "ERROR", + 1: "N-IDR", + 2: "SliceA", + 3: "SliceB", + 4: "SliceC", + 5: "IDR", + 6: "SEI", + 7: "SPS", + 8: "PPS", + 9: "AUD", + 10: "EOSEQ", + 11: "EOSTREAM", + 12: "FILLER", + 13: "SPS-EXT", + 14: "REV 14", + 15: "REV 15", + 16: "REV 16", + 17: "REV 17", + 18: "REV 18", + } +} diff --git a/format/flv/flv.go b/format/flv/flv.go index eb241def..59e8f5c4 100644 --- a/format/flv/flv.go +++ b/format/flv/flv.go @@ -177,6 +177,8 @@ func (self *Prober) TagToPacket(tag flvio.Tag, timestamp int32) (pkt av.Packet, pkt.CompositionTime = flvio.TsToTime(tag.CompositionTime) pkt.AVCPacketType = "NALU" pkt.IsKeyFrame = tag.FrameType == flvio.FRAME_KEY + pkt.NALUFormat = tag.NALUFormat + pkt.NALUInfos = tag.NALUInfos case flvio.AVC_SEQHDR: pkt.AVCPacketType = "SEQHDR" pkt.IsKeyFrame = tag.FrameType == flvio.FRAME_KEY diff --git a/format/flv/flvio/flvio.go b/format/flv/flvio/flvio.go index 010d9b8c..325d6a49 100644 --- a/format/flv/flvio/flvio.go +++ b/format/flv/flvio/flvio.go @@ -1,13 +1,14 @@ package flvio import ( - "Gout/joy4/codec/h264parser" "fmt" "io" "time" "github.com/davecgh/go-spew/spew" "github.com/jinleileiking/joy4/av" + "github.com/jinleileiking/joy4/codec/h264parser" + "github.com/jinleileiking/joy4/common" "github.com/jinleileiking/joy4/utils/bits/pio" ) @@ -155,6 +156,7 @@ type Tag struct { Data []byte NALUFormat string + NALUInfos []common.TNALUInfo } func (self Tag) ChannelLayout() av.ChannelLayout { @@ -325,8 +327,9 @@ func ReadTag(r io.Reader, b []byte) (tag Tag, ts int32, err error) { } tag.Data = data[n:] + // Data is h264 nalus if tag.Type == TAG_VIDEO { - _, nal_type := h264parser.SplitNALUs(tag.Data) + nalus, nal_type := h264parser.SplitNALUs(tag.Data) if nal_type == h264parser.NALU_AVCC { tag.NALUFormat = "AVCC" @@ -340,7 +343,17 @@ func ReadTag(r io.Reader, b []byte) (tag Tag, ts int32, err error) { tag.NALUFormat = "ANNEXB" } - spew.Dump(tag.NALUFormat) + for _, nalu := range nalus { + if _, info, err := h264parser.ParseSliceHeaderFromNALU(nalu); err == nil { + // spew.Dump(info) + tag.NALUInfos = append(tag.NALUInfos, info) + } else { + spew.Dump(err) + } + + } + + // spew.Dump(tag.NALUInfos) } } From 0306b0687373394f2d5384c9eab82eb8990a3290 Mon Sep 17 00:00:00 2001 From: JINLEI1 Date: Fri, 5 Jan 2018 17:52:41 +0800 Subject: [PATCH 04/13] do not break when slice not i , or b p --- codec/h264parser/parser.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/codec/h264parser/parser.go b/codec/h264parser/parser.go index 48a432bb..5612ff82 100644 --- a/codec/h264parser/parser.go +++ b/codec/h264parser/parser.go @@ -738,9 +738,9 @@ func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, info common.T sliceType = SLICE_B case 2, 4, 7, 9: sliceType = SLICE_I - default: - err = fmt.Errorf("h264parser: slice_type=%d invalid", u) - return + // default: + // err = fmt.Errorf("h264parser: slice_type=%d invalid", u) + // return } return From 357b78741c782232d388d3fd9a8de7e0408e21ba Mon Sep 17 00:00:00 2001 From: JINLEI1 Date: Thu, 11 Jan 2018 15:16:05 +0800 Subject: [PATCH 05/13] record data --- codec/h264parser/parser.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/codec/h264parser/parser.go b/codec/h264parser/parser.go index 5612ff82..e72b496b 100644 --- a/codec/h264parser/parser.go +++ b/codec/h264parser/parser.go @@ -701,6 +701,14 @@ func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, info common.T info.RefIdc = (int(packet[0]&0x1f) >> 5) info.UnitType = MAP_UNIT_TYPE[int(packet[0]&0x1f)] + info.NumBytes = len(packet) + info.Data = append(info.Data, packet...) + + // if info.UnitType == "FILLER" { + // if len(packet) > 16 { + // spew.Dump(packet[0:15]) + // } + // } if len(packet) <= 1 { err = fmt.Errorf("h264parser: packet too short to parse slice header") From 244805ed870bcd89586070009d3a22a79758c489 Mon Sep 17 00:00:00 2001 From: JINLEI1 Date: Thu, 11 Jan 2018 18:06:00 +0800 Subject: [PATCH 06/13] add slice type --- codec/h264parser/parser.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/codec/h264parser/parser.go b/codec/h264parser/parser.go index e72b496b..5e9b1fb7 100644 --- a/codec/h264parser/parser.go +++ b/codec/h264parser/parser.go @@ -750,11 +750,13 @@ func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, info common.T // err = fmt.Errorf("h264parser: slice_type=%d invalid", u) // return } + info.SliceType = MAP_SLICE_TYPE[int(u)] return } var MAP_UNIT_TYPE map[int]string +var MAP_SLICE_TYPE map[int]string func init() { MAP_UNIT_TYPE = map[int]string{ @@ -778,4 +780,16 @@ func init() { 17: "REV 17", 18: "REV 18", } + MAP_SLICE_TYPE = map[int]string{ + 0: "P", + 1: "B", + 2: "I", + 3: "SP", + 4: "SI", + 5: "P", + 6: "B", + 7: "I", + 8: "SP", + 9: "SI", + } } From 316d69054a120824e890cb366783b3a42e51390d Mon Sep 17 00:00:00 2001 From: JINLEI1 Date: Mon, 15 Jan 2018 19:52:40 +0800 Subject: [PATCH 07/13] ts modifys --- codec/h264parser/parser.go | 24 +++++++++++ format/ts/demuxer.go | 63 +++++++++++++++++++++++------ format/ts/handler.go | 3 +- format/ts/stream.go | 19 ++++----- format/ts/tsio/tsio.go | 82 +++++++++++++++++++++----------------- 5 files changed, 133 insertions(+), 58 deletions(-) diff --git a/codec/h264parser/parser.go b/codec/h264parser/parser.go index 5e9b1fb7..f5e9b37f 100644 --- a/codec/h264parser/parser.go +++ b/codec/h264parser/parser.go @@ -755,6 +755,30 @@ func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, info common.T return } +func ParseNALUs(b []byte) (info common.TNALUInfos) { + nalus, nal_type := SplitNALUs(b) + + if nal_type == NALU_AVCC { + info.NALUFormat = "AVCC" + } else if nal_type == NALU_RAW { + info.NALUFormat = "RAW" + } else if nal_type == NALU_ANNEXB { + info.NALUFormat = "ANNEXB" + } else { + info.NALUFormat = "OTHER" + } + + for _, nalu := range nalus { + if _, inf, err := ParseSliceHeaderFromNALU(nalu); err == nil { + info.Infos = append(info.Infos, inf) + } else { + fmt.Println("Error parse header") + } + + } + return +} + var MAP_UNIT_TYPE map[int]string var MAP_SLICE_TYPE map[int]string diff --git a/format/ts/demuxer.go b/format/ts/demuxer.go index 7f726af7..a7430806 100644 --- a/format/ts/demuxer.go +++ b/format/ts/demuxer.go @@ -3,13 +3,14 @@ package ts import ( "bufio" "fmt" + "io" "time" - "github.com/jinleileiking/joy4/utils/bits/pio" + "github.com/jinleileiking/joy4/av" - "github.com/jinleileiking/joy4/format/ts/tsio" "github.com/jinleileiking/joy4/codec/aacparser" "github.com/jinleileiking/joy4/codec/h264parser" - "io" + "github.com/jinleileiking/joy4/format/ts/tsio" + "github.com/jinleileiking/joy4/utils/bits/pio" ) type Demuxer struct { @@ -17,6 +18,10 @@ type Demuxer struct { pkts []av.Packet + Pat *tsio.PAT + Pmt *tsio.PMT + Payloads [][]byte + pat *tsio.PAT pmt *tsio.PMT streams []*Stream @@ -28,23 +33,29 @@ type Demuxer struct { func NewDemuxer(r io.Reader) *Demuxer { return &Demuxer{ tshdr: make([]byte, 188), - r: bufio.NewReaderSize(r, pio.RecommendBufioSize), + r: bufio.NewReaderSize(r, pio.RecommendBufioSize), } } func (self *Demuxer) Streams() (streams []av.CodecData, err error) { if err = self.probe(); err != nil { - return + // fmt.Println("probe error") + // spew.Dump("stream probe error", err) + // return } + + // dump streams to return for _, stream := range self.streams { streams = append(streams, stream.CodecData) } return } +// parse all data func (self *Demuxer) probe() (err error) { if self.stage == 0 { for { + //found pmt if self.pmt != nil { n := 0 for _, stream := range self.streams { @@ -101,7 +112,7 @@ func (self *Demuxer) initPMT(payload []byte) (err error) { return } self.pmt = &tsio.PMT{} - if _, err = self.pmt.Unmarshal(payload[psihdrlen:psihdrlen+datalen]); err != nil { + if _, err = self.pmt.Unmarshal(payload[psihdrlen : psihdrlen+datalen]); err != nil { return } @@ -112,6 +123,13 @@ func (self *Demuxer) initPMT(payload []byte) (err error) { stream.demuxer = self stream.pid = info.ElementaryPID stream.streamType = info.StreamType + if info.StreamType == 27 { + stream.streamTypeDes = "h264" + } else if info.StreamType == 15 { + stream.streamTypeDes = "avc" + } else { + stream.streamTypeDes = "other" + } switch info.StreamType { case tsio.ElementaryStreamTypeH264: self.streams = append(self.streams, stream) @@ -133,6 +151,7 @@ func (self *Demuxer) payloadEnd() (n int, err error) { return } +// find pat, pmt, and pes func (self *Demuxer) readTSPacket() (err error) { var hdrlen int var pid uint16 @@ -146,6 +165,8 @@ func (self *Demuxer) readTSPacket() (err error) { if pid, start, iskeyframe, hdrlen, err = tsio.ParseTSHeader(self.tshdr); err != nil { return } + + // fmt.Println("Got header") payload := self.tshdr[hdrlen:] if self.pat == nil { @@ -156,9 +177,11 @@ func (self *Demuxer) readTSPacket() (err error) { return } self.pat = &tsio.PAT{} - if _, err = self.pat.Unmarshal(payload[psihdrlen:psihdrlen+datalen]); err != nil { + if _, err = self.pat.Unmarshal(payload[psihdrlen : psihdrlen+datalen]); err != nil { return } + // fmt.Println("Got pat") + self.Pat = self.pat } } else if self.pmt == nil { for _, entry := range self.pat.Entries { @@ -166,6 +189,8 @@ func (self *Demuxer) readTSPacket() (err error) { if err = self.initPMT(payload); err != nil { return } + // fmt.Println("Got pmt") + self.Pmt = self.pmt break } } @@ -175,6 +200,7 @@ func (self *Demuxer) readTSPacket() (err error) { if err = stream.handleTSPacket(start, iskeyframe, payload); err != nil { return } + // fmt.Println("Got ts") break } } @@ -192,13 +218,13 @@ func (self *Stream) addPacket(payload []byte, timedelta time.Duration) { demuxer := self.demuxer pkt := av.Packet{ - Idx: int8(self.idx), + Idx: int8(self.idx), IsKeyFrame: self.iskeyframe, - Time: dts+timedelta, - Data: payload, + Time: dts + timedelta, + Data: payload, } if pts != dts { - pkt.CompositionTime = pts-dts + pkt.CompositionTime = pts - dts } demuxer.pkts = append(demuxer.pkts, pkt) } @@ -216,6 +242,8 @@ func (self *Stream) payloadEnd() (n int, err error) { switch self.streamType { case tsio.ElementaryStreamTypeAdtsAAC: + self.demuxer.Payloads = append(self.demuxer.Payloads, payload) + // fmt.Println("Payload aac end") var config aacparser.MPEG4AudioConfig delta := time.Duration(0) @@ -236,16 +264,23 @@ func (self *Stream) payloadEnd() (n int, err error) { } case tsio.ElementaryStreamTypeH264: - nalus, _ := h264parser.SplitNALUs(payload) + self.demuxer.Payloads = append(self.demuxer.Payloads, payload) + // fmt.Println("Payload h264 end") + nalus, typ := h264parser.SplitNALUs(payload) + + // spew.Dump(typ) var sps, pps []byte for _, nalu := range nalus { if len(nalu) > 0 { naltype := nalu[0] & 0x1f + // spew.Dump(naltype) switch { case naltype == 7: sps = nalu + // spew.Dump("got sps") case naltype == 8: pps = nalu + // spew.Dump("got pps") case h264parser.IsDataNALU(nalu): // raw nalu to avcc b := make([]byte, 4+len(nalu)) @@ -267,6 +302,8 @@ func (self *Stream) payloadEnd() (n int, err error) { return } +var total int + func (self *Stream) handleTSPacket(start bool, iskeyframe bool, payload []byte) (err error) { if start { if _, err = self.payloadEnd(); err != nil { @@ -286,5 +323,7 @@ func (self *Stream) handleTSPacket(start bool, iskeyframe bool, payload []byte) } else { self.data = append(self.data, payload...) } + total = total + 1 + // spew.Dump(total) return } diff --git a/format/ts/handler.go b/format/ts/handler.go index 61424b3f..b5f92ea3 100644 --- a/format/ts/handler.go +++ b/format/ts/handler.go @@ -2,6 +2,7 @@ package ts import ( "io" + "github.com/jinleileiking/joy4/av" "github.com/jinleileiking/joy4/av/avutil" ) @@ -13,6 +14,7 @@ func Handler(h *avutil.RegisterHandler) { return b[0] == 0x47 && b[188] == 0x47 } + // fmt.Println("found ts") h.ReaderDemuxer = func(r io.Reader) av.Demuxer { return NewDemuxer(r) } @@ -23,4 +25,3 @@ func Handler(h *avutil.RegisterHandler) { h.CodecTypes = CodecTypes } - diff --git a/format/ts/stream.go b/format/ts/stream.go index d75ec205..19d48835 100644 --- a/format/ts/stream.go +++ b/format/ts/stream.go @@ -2,6 +2,7 @@ package ts import ( "time" + "github.com/jinleileiking/joy4/av" "github.com/jinleileiking/joy4/format/ts/tsio" ) @@ -12,16 +13,16 @@ type Stream struct { demuxer *Demuxer muxer *Muxer - pid uint16 - streamId uint8 - streamType uint8 + pid uint16 + streamId uint8 + streamType uint8 + streamTypeDes string - tsw *tsio.TSWriter - idx int + tsw *tsio.TSWriter + idx int iskeyframe bool - pts, dts time.Duration - data []byte - datalen int + pts, dts time.Duration + data []byte + datalen int } - diff --git a/format/ts/tsio/tsio.go b/format/ts/tsio/tsio.go index 10d04105..a02b51ff 100644 --- a/format/ts/tsio/tsio.go +++ b/format/ts/tsio/tsio.go @@ -1,10 +1,10 @@ - package tsio import ( + "fmt" "io" "time" - "fmt" + "github.com/jinleileiking/joy4/utils/bits/pio" ) @@ -48,7 +48,7 @@ type PAT struct { } func (self PAT) Len() (n int) { - return len(self.Entries)*4 + return len(self.Entries) * 4 } func (self PAT) Marshal(b []byte) (n int) { @@ -73,10 +73,10 @@ func (self *PAT) Unmarshal(b []byte) (n int, err error) { entry.ProgramNumber = pio.U16BE(b[n:]) n += 2 if entry.ProgramNumber == 0 { - entry.NetworkPID = pio.U16BE(b[n:])&0x1fff + entry.NetworkPID = pio.U16BE(b[n:]) & 0x1fff n += 2 } else { - entry.ProgramMapPID = pio.U16BE(b[n:])&0x1fff + entry.ProgramMapPID = pio.U16BE(b[n:]) & 0x1fff n += 2 } self.Entries = append(self.Entries, entry) @@ -98,6 +98,7 @@ type Descriptor struct { type ElementaryStreamInfo struct { StreamType uint8 + StreamTypeDes string ElementaryPID uint16 Descriptors []Descriptor } @@ -117,7 +118,7 @@ func (self PMT) Len() (n int) { n += 2 for _, desc := range self.ProgramDescriptors { - n += 2+len(desc.Data) + n += 2 + len(desc.Data) } for _, info := range self.ElementaryStreamInfos { @@ -133,7 +134,7 @@ func (self PMT) Len() (n int) { n += 2 for _, desc := range info.Descriptors { - n += 2+len(desc.Data) + n += 2 + len(desc.Data) } } @@ -162,7 +163,7 @@ func (self PMT) Marshal(b []byte) (n int) { n += 2 pos := n n += self.fillDescs(b[n:], self.ProgramDescriptors) - desclen := n-pos + desclen := n - pos pio.PutU16BE(b[hold:], uint16(desclen)|0xf<<12) for _, info := range self.ElementaryStreamInfos { @@ -178,7 +179,7 @@ func (self PMT) Marshal(b []byte) (n int) { n += 2 pos := n n += self.fillDescs(b[n:], info.Descriptors) - desclen := n-pos + desclen := n - pos pio.PutU16BE(b[hold:], uint16(desclen)|0x3c<<10) } @@ -219,13 +220,13 @@ func (self *PMT) Unmarshal(b []byte) (n int, err error) { // 111(3) // PCRPID(13) - self.PCRPID = pio.U16BE(b[0:2])&0x1fff + self.PCRPID = pio.U16BE(b[0:2]) & 0x1fff n += 2 // Reserved(4)=0xf // Reserved(2)=0x0 // Program info length(10) - desclen := int(pio.U16BE(b[2:4])&0x3ff) + desclen := int(pio.U16BE(b[2:4]) & 0x3ff) n += 2 if desclen > 0 { @@ -233,7 +234,7 @@ func (self *PMT) Unmarshal(b []byte) (n int, err error) { err = ErrParsePMT return } - if self.ProgramDescriptors, err = self.parseDescs(b[n:n+desclen]); err != nil { + if self.ProgramDescriptors, err = self.parseDescs(b[n : n+desclen]); err != nil { return } n += desclen @@ -247,16 +248,23 @@ func (self *PMT) Unmarshal(b []byte) (n int, err error) { var info ElementaryStreamInfo info.StreamType = b[n] + if info.StreamType == 0x0f { + info.StreamTypeDes = "aac" + } else if info.StreamType == 0x1b { + info.StreamTypeDes = "h264" + } else { + info.StreamTypeDes = "other" + } n++ // Reserved(3) // Elementary PID(13) - info.ElementaryPID = pio.U16BE(b[n:])&0x1fff + info.ElementaryPID = pio.U16BE(b[n:]) & 0x1fff n += 2 // Reserved(6) // ES Info length(10) - desclen := int(pio.U16BE(b[n:])&0x3ff) + desclen := int(pio.U16BE(b[n:]) & 0x3ff) n += 2 if desclen > 0 { @@ -264,7 +272,7 @@ func (self *PMT) Unmarshal(b []byte) (n int, err error) { err = ErrParsePMT return } - if info.Descriptors, err = self.parseDescs(b[n:n+desclen]); err != nil { + if info.Descriptors, err = self.parseDescs(b[n : n+desclen]); err != nil { return } n += desclen @@ -345,7 +353,7 @@ func FillPSI(h []byte, tableid uint8, tableext uint16, datalen int) (n int) { n++ // section_syntax_indicator(1)=1,private_bit(1)=0,reserved(2)=3,unused(2)=0,section_length(10) - pio.PutU16BE(h[n:], uint16(0xa<<12 | 2+3+4+datalen)) + pio.PutU16BE(h[n:], uint16(0xa<<12|2+3+4+datalen)) n += 2 // Table ID extension(16) @@ -375,7 +383,7 @@ func FillPSI(h []byte, tableid uint8, tableext uint16, datalen int) (n int) { func TimeToPCR(tm time.Duration) (pcr uint64) { // base(33)+resverd(6)+ext(9) - ts := uint64(tm*PCR_HZ/time.Second) + ts := uint64(tm * PCR_HZ / time.Second) base := ts / 300 ext := ts % 300 pcr = base<<15 | 0x3f<<9 | ext @@ -386,12 +394,12 @@ func PCRToTime(pcr uint64) (tm time.Duration) { base := pcr >> 15 ext := pcr & 0x1ff ts := base*300 + ext - tm = time.Duration(ts)*time.Second/time.Duration(PCR_HZ) + tm = time.Duration(ts) * time.Second / time.Duration(PCR_HZ) return } func TimeToTs(tm time.Duration) (v uint64) { - ts := uint64(tm*PTS_HZ/time.Second) + ts := uint64(tm * PTS_HZ / time.Second) // 0010 PTS 32..30 1 PTS 29..15 1 PTS 14..00 1 v = ((ts>>30)&0x7)<<33 | ((ts>>15)&0x7fff)<<17 | (ts&0x7fff)<<1 | 0x100010001 return @@ -399,8 +407,8 @@ func TimeToTs(tm time.Duration) (v uint64) { func TsToTime(v uint64) (tm time.Duration) { // 0010 PTS 32..30 1 PTS 29..15 1 PTS 14..00 1 - ts := (((v>>33)&0x7)<<30) | (((v>>17)&0x7fff) << 15) | ((v>>1)&0x7fff) - tm = time.Duration(ts)*time.Second/time.Duration(PTS_HZ) + ts := (((v >> 33) & 0x7) << 30) | (((v >> 17) & 0x7fff) << 15) | ((v >> 1) & 0x7fff) + tm = time.Duration(ts) * time.Second / time.Duration(PTS_HZ) return } @@ -415,13 +423,14 @@ func ParsePESHeader(h []byte) (hdrlen int, streamid uint8, datalen int, pts, dts return } streamid = h[3] + // spew.Printf("streamid %x", streamid) flags := h[7] - hdrlen = int(h[8])+9 + hdrlen = int(h[8]) + 9 datalen = int(pio.U16BE(h[4:6])) if datalen > 0 { - datalen -= int(h[8])+3 + datalen -= int(h[8]) + 3 } const PTS = 1 << 7 @@ -433,12 +442,14 @@ func ParsePESHeader(h []byte) (hdrlen int, streamid uint8, datalen int, pts, dts return } pts = TsToTime(pio.U40BE(h[9:14])) + // spew.Dump("pts", pts) if flags&DTS != 0 { if len(h) < 19 { err = ErrPESHeader return } dts = TsToTime(pio.U40BE(h[14:19])) + // spew.Dump("dts", dts) } } @@ -479,7 +490,7 @@ func FillPESHeader(h []byte, streamid uint8, datalen int, pts, dts time.Duration } pio.PutU16BE(h[4:6], pktlen) - h[6] = 2<<6|1 // resverd(6,2)=2,original_or_copy(0,1)=1 + h[6] = 2<<6 | 1 // resverd(6,2)=2,original_or_copy(0,1)=1 h[7] = flags h[8] = uint8(n) @@ -499,9 +510,9 @@ func FillPESHeader(h []byte, streamid uint8, datalen int, pts, dts time.Duration } type TSWriter struct { - w io.Writer + w io.Writer ContinuityCounter uint - tshdr []byte + tshdr []byte } func NewTSWriter(pid uint16) *TSWriter { @@ -521,21 +532,21 @@ func (self *TSWriter) WritePackets(w io.Writer, datav [][]byte, pcr time.Duratio writepos := 0 for writepos < datavlen { - self.tshdr[1] = self.tshdr[1]&0x1f - self.tshdr[3] = byte(self.ContinuityCounter)&0xf|0x30 + self.tshdr[1] = self.tshdr[1] & 0x1f + self.tshdr[3] = byte(self.ContinuityCounter)&0xf | 0x30 self.tshdr[5] = 0 // flags hdrlen := 6 self.ContinuityCounter++ if writepos == 0 { - self.tshdr[1] = 0x40|self.tshdr[1] // Payload Unit Start Indicator + self.tshdr[1] = 0x40 | self.tshdr[1] // Payload Unit Start Indicator if pcr != 0 { hdrlen += 6 - self.tshdr[5] = 0x10|self.tshdr[5] // PCR flag (Discontinuity indicator 0x80) + self.tshdr[5] = 0x10 | self.tshdr[5] // PCR flag (Discontinuity indicator 0x80) pio.PutU48BE(self.tshdr[6:12], TimeToPCR(pcr)) } if sync { - self.tshdr[5] = 0x40|self.tshdr[5] // Random Access indicator + self.tshdr[5] = 0x40 | self.tshdr[5] // Random Access indicator } } @@ -551,7 +562,7 @@ func (self *TSWriter) WritePackets(w io.Writer, datav [][]byte, pcr time.Duratio } n := pio.VecSliceTo(datav, writev, writepos, end) - self.tshdr[4] = byte(hdrlen)-5 // length + self.tshdr[4] = byte(hdrlen) - 5 // length if _, err = w.Write(self.tshdr[:hdrlen]); err != nil { return } @@ -561,7 +572,7 @@ func (self *TSWriter) WritePackets(w io.Writer, datav [][]byte, pcr time.Duratio } } if padtail > 0 { - if _, err = w.Write(self.tshdr[188-padtail:188]); err != nil { + if _, err = w.Write(self.tshdr[188-padtail : 188]); err != nil { return } } @@ -578,13 +589,12 @@ func ParseTSHeader(tshdr []byte) (pid uint16, start bool, iskeyframe bool, hdrle err = fmt.Errorf("tshdr sync invalid") return } - pid = uint16((tshdr[1]&0x1f))<<8|uint16(tshdr[2]) + pid = uint16((tshdr[1]&0x1f))<<8 | uint16(tshdr[2]) start = tshdr[1]&0x40 != 0 hdrlen += 4 if tshdr[3]&0x20 != 0 { - hdrlen += int(tshdr[4])+1 + hdrlen += int(tshdr[4]) + 1 iskeyframe = tshdr[5]&0x40 != 0 } return } - From 51fec277891779c1aa67b6deb4e5098caa490c34 Mon Sep 17 00:00:00 2001 From: JINLEI1 Date: Mon, 15 Jan 2018 19:54:26 +0800 Subject: [PATCH 08/13] up --- format/ts/demuxer.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/format/ts/demuxer.go b/format/ts/demuxer.go index a7430806..7894fd12 100644 --- a/format/ts/demuxer.go +++ b/format/ts/demuxer.go @@ -266,7 +266,8 @@ func (self *Stream) payloadEnd() (n int, err error) { case tsio.ElementaryStreamTypeH264: self.demuxer.Payloads = append(self.demuxer.Payloads, payload) // fmt.Println("Payload h264 end") - nalus, typ := h264parser.SplitNALUs(payload) + // nalus, typ := h264parser.SplitNALUs(payload) + nalus, _ := h264parser.SplitNALUs(payload) // spew.Dump(typ) var sps, pps []byte From bff8ba09882a7942eac807f9a1c84df0fd648c62 Mon Sep 17 00:00:00 2001 From: JINLEI1 Date: Mon, 15 Jan 2018 21:07:11 +0800 Subject: [PATCH 09/13] ts done --- codec/h264parser/parser.go | 1 + format/ts/demuxer.go | 24 +++++++++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/codec/h264parser/parser.go b/codec/h264parser/parser.go index f5e9b37f..1b0fc5fc 100644 --- a/codec/h264parser/parser.go +++ b/codec/h264parser/parser.go @@ -698,6 +698,7 @@ const ( func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, info common.TNALUInfo, err error) { + // spew.Printf("%08b\n", packet[0]&0x1f) info.RefIdc = (int(packet[0]&0x1f) >> 5) info.UnitType = MAP_UNIT_TYPE[int(packet[0]&0x1f)] diff --git a/format/ts/demuxer.go b/format/ts/demuxer.go index 7894fd12..1e2f9cd7 100644 --- a/format/ts/demuxer.go +++ b/format/ts/demuxer.go @@ -13,14 +13,21 @@ import ( "github.com/jinleileiking/joy4/utils/bits/pio" ) +type TPayloadInfos struct { + Pts int + Dts int + PayloadInfo []byte +} + type Demuxer struct { r *bufio.Reader pkts []av.Packet - Pat *tsio.PAT - Pmt *tsio.PMT - Payloads [][]byte + Pat *tsio.PAT + Pmt *tsio.PMT + Payloads [][]byte + PayloadInfos []TPayloadInfos pat *tsio.PAT pmt *tsio.PMT @@ -243,6 +250,10 @@ func (self *Stream) payloadEnd() (n int, err error) { switch self.streamType { case tsio.ElementaryStreamTypeAdtsAAC: self.demuxer.Payloads = append(self.demuxer.Payloads, payload) + payload_info.PayloadInfo = payload + self.demuxer.PayloadInfos = append(self.demuxer.PayloadInfos, payload_info) + + // self.demuxer.PayloadInfos.PayloadInfo = append(self.demuxer.PayloadInfos.PayloadInfo, payload) // fmt.Println("Payload aac end") var config aacparser.MPEG4AudioConfig @@ -265,6 +276,10 @@ func (self *Stream) payloadEnd() (n int, err error) { case tsio.ElementaryStreamTypeH264: self.demuxer.Payloads = append(self.demuxer.Payloads, payload) + // self.demuxer.PayloadInfos.PayloadInfo = append(self.demuxer.PayloadInfos.PayloadInfo, payload) + payload_info.PayloadInfo = payload + self.demuxer.PayloadInfos = append(self.demuxer.PayloadInfos, payload_info) + // fmt.Println("Payload h264 end") // nalus, typ := h264parser.SplitNALUs(payload) nalus, _ := h264parser.SplitNALUs(payload) @@ -304,6 +319,7 @@ func (self *Stream) payloadEnd() (n int, err error) { } var total int +var payload_info TPayloadInfos func (self *Stream) handleTSPacket(start bool, iskeyframe bool, payload []byte) (err error) { if start { @@ -314,6 +330,8 @@ func (self *Stream) handleTSPacket(start bool, iskeyframe bool, payload []byte) if hdrlen, _, self.datalen, self.pts, self.dts, err = tsio.ParsePESHeader(payload); err != nil { return } + payload_info.Pts = int(self.pts) + payload_info.Dts = int(self.dts) self.iskeyframe = iskeyframe if self.datalen == 0 { self.data = make([]byte, 0, 4096) From 89c4beb8149a3a7893cfc8b71b634ed97539c0cd Mon Sep 17 00:00:00 2001 From: JINLEI1 Date: Tue, 16 Jan 2018 10:37:33 +0800 Subject: [PATCH 10/13] add missing common --- common/common.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 common/common.go diff --git a/common/common.go b/common/common.go new file mode 100644 index 00000000..f5beb51d --- /dev/null +++ b/common/common.go @@ -0,0 +1,14 @@ +package common + +type TNALUInfos struct { + NALUFormat string + Infos []TNALUInfo +} + +type TNALUInfo struct { + UnitType string + RefIdc int + NumBytes int + Data []byte + SliceType string +} From e931de714e0e0bde2ec5e42ec0e6a3f13a696611 Mon Sep 17 00:00:00 2001 From: JINLEI1 Date: Fri, 2 Mar 2018 15:29:44 +0800 Subject: [PATCH 11/13] add eos parse --- format/flv/flv.go | 5 +++++ format/flv/flvio/flvio.go | 13 ++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/format/flv/flv.go b/format/flv/flv.go index 59e8f5c4..df103c51 100644 --- a/format/flv/flv.go +++ b/format/flv/flv.go @@ -183,6 +183,11 @@ func (self *Prober) TagToPacket(tag flvio.Tag, timestamp int32) (pkt av.Packet, pkt.AVCPacketType = "SEQHDR" pkt.IsKeyFrame = tag.FrameType == flvio.FRAME_KEY pkt.Data = tag.Data + case flvio.AVC_EOS: + ok = true + pkt.AVCPacketType = "EOS" + pkt.IsKeyFrame = tag.FrameType == flvio.FRAME_KEY + pkt.Data = tag.Data } case flvio.TAG_AUDIO: diff --git a/format/flv/flvio/flvio.go b/format/flv/flvio/flvio.go index 325d6a49..efe124f8 100644 --- a/format/flv/flvio/flvio.go +++ b/format/flv/flvio/flvio.go @@ -211,6 +211,7 @@ func (self Tag) audioFillHeader(b []byte) (n int) { return } +// VIDEODATA + AVCVIDEOPACKET func (self *Tag) videoParseHeader(b []byte) (n int, err error) { if len(b) < n+1 { err = fmt.Errorf("videodata: parse invalid") @@ -283,6 +284,8 @@ const ( const TagHeaderLength = 11 const TagTrailerLength = 4 +//FLVTAG +// 09/08 ... xxxxx func ParseTagHeader(b []byte) (tag Tag, ts int32, datalen int, err error) { tagtype := b[0] @@ -328,7 +331,8 @@ func ReadTag(r io.Reader, b []byte) (tag Tag, ts int32, err error) { tag.Data = data[n:] // Data is h264 nalus - if tag.Type == TAG_VIDEO { + if tag.Type == TAG_VIDEO && len(tag.Data) != 0 { + nalus, nal_type := h264parser.SplitNALUs(tag.Data) if nal_type == h264parser.NALU_AVCC { @@ -344,6 +348,8 @@ func ReadTag(r io.Reader, b []byte) (tag Tag, ts int32, err error) { } for _, nalu := range nalus { + // spew.Dump(nalus) + // os.Exit(1) if _, info, err := h264parser.ParseSliceHeaderFromNALU(nalu); err == nil { // spew.Dump(info) tag.NALUInfos = append(tag.NALUInfos, info) @@ -355,6 +361,11 @@ func ReadTag(r io.Reader, b []byte) (tag Tag, ts int32, err error) { // spew.Dump(tag.NALUInfos) } + + if tag.Type == TAG_VIDEO && len(tag.Data) == 0 { + tag.NALUFormat = "N/A" + } + } // b[:4] ---> preTagSize From aa1df0adc869a10b63b8da59fdcf8be7d316cb3a Mon Sep 17 00:00:00 2001 From: JINLEI1 Date: Wed, 23 May 2018 12:06:24 +0800 Subject: [PATCH 12/13] add timestamp --- av/av.go | 1 + format/flv/flv.go | 1 + format/flv/flvio/flvio.go | 4 +++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/av/av.go b/av/av.go index 2babbabe..91503355 100644 --- a/av/av.go +++ b/av/av.go @@ -232,6 +232,7 @@ type Packet struct { IsKeyFrame bool // video packet is key frame Idx int8 // stream index in container format CompositionTime time.Duration // packet presentation time minus decode time for H264 B-Frame + Timestamp int32 AVCPacketType string NALUFormat string NALUInfos []common.TNALUInfo diff --git a/format/flv/flv.go b/format/flv/flv.go index df103c51..1746bad4 100644 --- a/format/flv/flv.go +++ b/format/flv/flv.go @@ -175,6 +175,7 @@ func (self *Prober) TagToPacket(tag flvio.Tag, timestamp int32) (pkt av.Packet, ok = true pkt.Data = tag.Data pkt.CompositionTime = flvio.TsToTime(tag.CompositionTime) + pkt.Timestamp = tag.Timestamp pkt.AVCPacketType = "NALU" pkt.IsKeyFrame = tag.FrameType == flvio.FRAME_KEY pkt.NALUFormat = tag.NALUFormat diff --git a/format/flv/flvio/flvio.go b/format/flv/flvio/flvio.go index efe124f8..8cb1bcf5 100644 --- a/format/flv/flvio/flvio.go +++ b/format/flv/flvio/flvio.go @@ -153,7 +153,8 @@ type Tag struct { CompositionTime int32 - Data []byte + Data []byte + Timestamp int32 NALUFormat string NALUInfos []common.TNALUInfo @@ -329,6 +330,7 @@ func ReadTag(r io.Reader, b []byte) (tag Tag, ts int32, err error) { return } tag.Data = data[n:] + tag.Timestamp = ts // Data is h264 nalus if tag.Type == TAG_VIDEO && len(tag.Data) != 0 { From 5977273146ad486e21ad0b62a78a6252b83837e2 Mon Sep 17 00:00:00 2001 From: JINLEI1 Date: Wed, 23 May 2018 13:14:39 +0800 Subject: [PATCH 13/13] add unit type int --- codec/h264parser/parser.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/codec/h264parser/parser.go b/codec/h264parser/parser.go index 1b0fc5fc..8a391ca7 100644 --- a/codec/h264parser/parser.go +++ b/codec/h264parser/parser.go @@ -785,20 +785,20 @@ var MAP_SLICE_TYPE map[int]string func init() { MAP_UNIT_TYPE = map[int]string{ - 0: "ERROR", - 1: "N-IDR", - 2: "SliceA", - 3: "SliceB", - 4: "SliceC", - 5: "IDR", - 6: "SEI", - 7: "SPS", - 8: "PPS", - 9: "AUD", - 10: "EOSEQ", - 11: "EOSTREAM", - 12: "FILLER", - 13: "SPS-EXT", + 0: "(0)ERROR", + 1: "(1)N-IDR", + 2: "(2)SliceA", + 3: "(3)SliceB", + 4: "(4)SliceC", + 5: "(5)IDR", + 6: "(6)SEI", + 7: "(7)SPS", + 8: "(8)PPS", + 9: "(9)AUD", + 10: "(10)EOSEQ", + 11: "(11)EOSTREAM", + 12: "(12)FILLER", + 13: "(13)SPS-EXT", 14: "REV 14", 15: "REV 15", 16: "REV 16",