rewrite handler codec types logic, rm ts unused files
This commit is contained in:
parent
66bd404f1a
commit
2dea41f479
@ -171,17 +171,13 @@ func ConvertCmdline(args []string) (err error) {
|
|||||||
}
|
}
|
||||||
defer demuxer.Close()
|
defer demuxer.Close()
|
||||||
|
|
||||||
if muxer, err = avutil.Create(output); err != nil {
|
var handler avutil.RegisterHandler
|
||||||
|
if handler, muxer, err = avutil.DefaultHandlers.FindCreate(output); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer muxer.Close()
|
defer muxer.Close()
|
||||||
|
|
||||||
type intf interface {
|
options.OutputCodecTypes = handler.CodecTypes
|
||||||
SupportedCodecTypes() []av.CodecType
|
|
||||||
}
|
|
||||||
if fn, ok := muxer.(intf); ok {
|
|
||||||
options.OutputCodecTypes = fn.SupportedCodecTypes()
|
|
||||||
}
|
|
||||||
|
|
||||||
convdemux := &Demuxer{
|
convdemux := &Demuxer{
|
||||||
Options: options,
|
Options: options,
|
||||||
|
@ -11,22 +11,22 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
)
|
)
|
||||||
|
|
||||||
type handlerDemuxer struct {
|
type HandlerDemuxer struct {
|
||||||
av.Demuxer
|
av.Demuxer
|
||||||
r io.ReadCloser
|
r io.ReadCloser
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *handlerDemuxer) Close() error {
|
func (self *HandlerDemuxer) Close() error {
|
||||||
return self.r.Close()
|
return self.r.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
type handlerMuxer struct {
|
type HandlerMuxer struct {
|
||||||
av.Muxer
|
av.Muxer
|
||||||
w io.WriteCloser
|
w io.WriteCloser
|
||||||
stage int
|
stage int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *handlerMuxer) WriteHeader(streams []av.CodecData) (err error) {
|
func (self *HandlerMuxer) WriteHeader(streams []av.CodecData) (err error) {
|
||||||
if self.stage == 0 {
|
if self.stage == 0 {
|
||||||
if err = self.Muxer.WriteHeader(streams); err != nil {
|
if err = self.Muxer.WriteHeader(streams); err != nil {
|
||||||
return
|
return
|
||||||
@ -36,7 +36,7 @@ func (self *handlerMuxer) WriteHeader(streams []av.CodecData) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *handlerMuxer) WriteTrailer() (err error) {
|
func (self *HandlerMuxer) WriteTrailer() (err error) {
|
||||||
if self.stage == 1 {
|
if self.stage == 1 {
|
||||||
if err = self.Muxer.WriteTrailer(); err != nil {
|
if err = self.Muxer.WriteTrailer(); err != nil {
|
||||||
return
|
return
|
||||||
@ -46,7 +46,7 @@ func (self *handlerMuxer) WriteTrailer() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *handlerMuxer) Close() (err error) {
|
func (self *HandlerMuxer) Close() (err error) {
|
||||||
if err = self.WriteTrailer(); err != nil {
|
if err = self.WriteTrailer(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -64,6 +64,7 @@ type RegisterHandler struct {
|
|||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
type Handlers struct {
|
type Handlers struct {
|
||||||
@ -163,7 +164,7 @@ func (self *Handlers) Open(uri string) (demuxer av.DemuxCloser, err error) {
|
|||||||
if r, err = self.openUrl(u, uri); err != nil {
|
if r, err = self.openUrl(u, uri); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
demuxer = &handlerDemuxer{
|
demuxer = &HandlerDemuxer{
|
||||||
Demuxer: handler.ReaderDemuxer(r),
|
Demuxer: handler.ReaderDemuxer(r),
|
||||||
r: r,
|
r: r,
|
||||||
}
|
}
|
||||||
@ -183,7 +184,7 @@ func (self *Handlers) Open(uri string) (demuxer av.DemuxCloser, err error) {
|
|||||||
|
|
||||||
for _, handler := range self.handlers {
|
for _, handler := range self.handlers {
|
||||||
if handler.Probe != nil && handler.Probe(probebuf[:]) && handler.ReaderDemuxer != nil {
|
if handler.Probe != nil && handler.Probe(probebuf[:]) && handler.ReaderDemuxer != nil {
|
||||||
demuxer = &handlerDemuxer{
|
demuxer = &HandlerDemuxer{
|
||||||
Demuxer: handler.ReaderDemuxer(io.MultiReader(bytes.NewReader(probebuf[:]), r)),
|
Demuxer: handler.ReaderDemuxer(io.MultiReader(bytes.NewReader(probebuf[:]), r)),
|
||||||
r: r,
|
r: r,
|
||||||
}
|
}
|
||||||
@ -197,13 +198,18 @@ func (self *Handlers) Open(uri string) (demuxer av.DemuxCloser, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *Handlers) Create(uri string) (muxer av.MuxCloser, err error) {
|
func (self *Handlers) Create(uri string) (muxer av.MuxCloser, err error) {
|
||||||
|
_, muxer, err = self.FindCreate(uri)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *Handlers) FindCreate(uri string) (handler RegisterHandler, muxer av.MuxCloser, err error) {
|
||||||
listen := false
|
listen := false
|
||||||
if strings.HasPrefix(uri, "listen:") {
|
if strings.HasPrefix(uri, "listen:") {
|
||||||
uri = uri[len("listen:"):]
|
uri = uri[len("listen:"):]
|
||||||
listen = true
|
listen = true
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, handler := range self.handlers {
|
for _, handler = range self.handlers {
|
||||||
if listen {
|
if listen {
|
||||||
if handler.ServerMuxer != nil {
|
if handler.ServerMuxer != nil {
|
||||||
var ok bool
|
var ok bool
|
||||||
@ -223,13 +229,13 @@ func (self *Handlers) Create(uri string) (muxer av.MuxCloser, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ext != "" {
|
if ext != "" {
|
||||||
for _, handler := range self.handlers {
|
for _, handler = range self.handlers {
|
||||||
if handler.Ext == ext && handler.WriterMuxer != nil {
|
if handler.Ext == ext && handler.WriterMuxer != nil {
|
||||||
var w io.WriteCloser
|
var w io.WriteCloser
|
||||||
if w, err = self.createUrl(u, uri); err != nil {
|
if w, err = self.createUrl(u, uri); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
muxer = &handlerMuxer{
|
muxer = &HandlerMuxer{
|
||||||
Muxer: handler.WriterMuxer(w),
|
Muxer: handler.WriterMuxer(w),
|
||||||
w: w,
|
w: w,
|
||||||
}
|
}
|
||||||
|
@ -24,10 +24,6 @@ func NewMuxer(w io.Writer) *Muxer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Muxer) SupportedCodecTypes() []av.CodecType {
|
|
||||||
return []av.CodecType{av.AAC}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Muxer) WriteHeader(streams []av.CodecData) (err error) {
|
func (self *Muxer) WriteHeader(streams []av.CodecData) (err error) {
|
||||||
if len(streams) > 1 || streams[0].Type() != av.AAC {
|
if len(streams) > 1 || streams[0].Type() != av.AAC {
|
||||||
err = fmt.Errorf("aac: must be only one aac stream")
|
err = fmt.Errorf("aac: must be only one aac stream")
|
||||||
@ -120,4 +116,6 @@ func Handler(h *avutil.RegisterHandler) {
|
|||||||
_, _, _, _, err := aacparser.ParseADTSHeader(b)
|
_, _, _, _, err := aacparser.ParseADTSHeader(b)
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h.CodecTypes = []av.CodecType{av.AAC}
|
||||||
}
|
}
|
||||||
|
@ -281,11 +281,7 @@ func NewMuxer(w io.Writer) *Muxer {
|
|||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
var SupportedCodecTypes = []av.CodecType{av.H264, av.AAC, av.SPEEX}
|
var CodecTypes = []av.CodecType{av.H264, av.AAC, av.SPEEX}
|
||||||
|
|
||||||
func (self *Muxer) SupportedCodecTypes() []av.CodecType {
|
|
||||||
return SupportedCodecTypes
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Muxer) WriteHeader(streams []av.CodecData) (err error) {
|
func (self *Muxer) WriteHeader(streams []av.CodecData) (err error) {
|
||||||
var flags uint8
|
var flags uint8
|
||||||
@ -420,12 +416,17 @@ func Handler(h *avutil.RegisterHandler) {
|
|||||||
h.Probe = func(b []byte) bool {
|
h.Probe = func(b []byte) bool {
|
||||||
return b[0] == 'F' && b[1] == 'L' && b[2] == 'V'
|
return b[0] == 'F' && b[1] == 'L' && b[2] == 'V'
|
||||||
}
|
}
|
||||||
|
|
||||||
h.Ext = ".flv"
|
h.Ext = ".flv"
|
||||||
|
|
||||||
h.ReaderDemuxer = func(r io.Reader) av.Demuxer {
|
h.ReaderDemuxer = func(r io.Reader) av.Demuxer {
|
||||||
return NewDemuxer(r)
|
return NewDemuxer(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
h.WriterMuxer = func(w io.Writer) av.Muxer {
|
h.WriterMuxer = func(w io.Writer) av.Muxer {
|
||||||
return NewMuxer(w)
|
return NewMuxer(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h.CodecTypes = CodecTypes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,13 +6,19 @@ import (
|
|||||||
"github.com/nareix/joy4/av/avutil"
|
"github.com/nareix/joy4/av/avutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var CodecTypes = []av.CodecType{av.H264, av.AAC}
|
||||||
|
|
||||||
func Handler(h *avutil.RegisterHandler) {
|
func Handler(h *avutil.RegisterHandler) {
|
||||||
h.Ext = ".mp4"
|
h.Ext = ".mp4"
|
||||||
|
|
||||||
h.ReaderDemuxer = func(r io.Reader) av.Demuxer {
|
h.ReaderDemuxer = func(r io.Reader) av.Demuxer {
|
||||||
return NewDemuxer(r.(io.ReadSeeker))
|
return NewDemuxer(r.(io.ReadSeeker))
|
||||||
}
|
}
|
||||||
|
|
||||||
h.WriterMuxer = func(w io.Writer) av.Muxer {
|
h.WriterMuxer = func(w io.Writer) av.Muxer {
|
||||||
return NewMuxer(w.(io.WriteSeeker))
|
return NewMuxer(w.(io.WriteSeeker))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h.CodecTypes = CodecTypes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,10 +22,6 @@ func NewMuxer(w io.WriteSeeker) *Muxer {
|
|||||||
return &Muxer{w: w}
|
return &Muxer{w: w}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Muxer) SupportedCodecTypes() []av.CodecType {
|
|
||||||
return []av.CodecType{av.H264, av.AAC}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Muxer) newStream(codec av.CodecData) (err error) {
|
func (self *Muxer) newStream(codec av.CodecData) (err error) {
|
||||||
switch codec.Type() {
|
switch codec.Type() {
|
||||||
case av.H264, av.AAC:
|
case av.H264, av.AAC:
|
||||||
|
@ -21,6 +21,8 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var Debug bool
|
||||||
|
|
||||||
func ParseURL(uri string) (u *url.URL, err error) {
|
func ParseURL(uri string) (u *url.URL, err error) {
|
||||||
if u, err = url.Parse(uri); err != nil {
|
if u, err = url.Parse(uri); err != nil {
|
||||||
return
|
return
|
||||||
@ -52,8 +54,6 @@ func DialTimeout(uri string, timeout time.Duration) (conn *Conn, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var Debug bool
|
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
Addr string
|
Addr string
|
||||||
HandlePublish func(*Conn)
|
HandlePublish func(*Conn)
|
||||||
@ -317,9 +317,7 @@ func createURL(tcurl, app, play string) (u *url.URL) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Conn) SupportedCodecTypes() []av.CodecType {
|
var CodecTypes = flv.CodecTypes
|
||||||
return flv.SupportedCodecTypes
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Conn) recvConnect() (err error) {
|
func (self *Conn) recvConnect() (err error) {
|
||||||
var connectpath string
|
var connectpath string
|
||||||
@ -1707,5 +1705,7 @@ func Handler(h *avutil.RegisterHandler) {
|
|||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h.CodecTypes = CodecTypes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
|||||||
|
|
||||||
The first h264 packet
|
|
||||||
|
|
||||||
00000000 00 00 00 01 09 f0 00 00 00 01 06 00 07 86 96 7f |................|
|
|
||||||
^ ^
|
|
||||||
00000010 80 00 00 40 80 00 00 01 06 05 11 03 87 f4 4e cd |...@..........N.|
|
|
||||||
^
|
|
||||||
00000020 0a 4b dc a1 94 3a c3 d4 9b 17 1f 00 80 00 00 00 |.K...:..........|
|
|
||||||
00000030 01 27 4d 40 0a a9 19 bf 2c b8 0b 50 10 10 13 0a |.'M@....,..P....|
|
|
||||||
^
|
|
||||||
00000040 d7 bd f0 10 00 00 00 01 28 fe 09 88 00 00 01 25 |........(......%|
|
|
||||||
^ ^
|
|
||||||
00000050 b8 20 20 bf ed 7e de 3b 56 7f 03 c5 d1 06 9a c3 |. ..~.;V.......|
|
|
||||||
00000060 74 e5 9d 18 e6 3f 9d 63 19 cc 46 fd 36 13 c5 b8 |t....?.c..F.6...|
|
|
||||||
00000070 7f 3e d9 39 1b 21 74 61 6d 9d b7 5b 71 e6 a2 de |.>.9.!tam..[q...|
|
|
||||||
00000080 68 0b bf 7e b8 d4 9d 2f 49 19 3b 11 6e 40 a3 0a |h..~.../I.;.n@..|
|
|
||||||
00000090 3f 02 c5 a3 47 1d ed 2a 3a a1 33 0e 15 2f 36 d8 |?...G..*:.3../6.|
|
|
||||||
000000a0 c7 2a eb c6 bf 0d 95 e4 42 3e 7b 5f 44 3f b9 a5 |.*......B>{_D?..|
|
|
||||||
000000b0 d7 a2 c6 f4 41 e8 82 b5 cc cd c9 a4 ec 29 6f 58 |....A........)oX|
|
|
||||||
000000c0 6c 78 38 7c b5 5b 27 97 9d 56 5f e0 00 00 01 25 |lx8|.['..V_....%|
|
|
||||||
^
|
|
||||||
000000d0 2b 82 02 0b af 43 64 9c f1 eb 03 7e 39 a0 b6 f8 |+....Cd....~9...|
|
|
||||||
000000e0 eb c4 88 d2 ef 79 1f 7c d6 4e 1a d3 5d 27 39 ca |.....y.|.N..]'9.|
|
|
||||||
000000f0 c6 0b a9 63 78 e2 19 41 71 d4 47 26 bc 58 e4 45 |...cx..Aq.G&.X.E|
|
|
||||||
00000100 db 77 7b 60 7f d9 e4 11 03 3d 05 0d 72 5e 0d a0 |.w{`.....=..r^..|
|
|
||||||
00000110 56 4f 1a a9 9e 4f 80 |VO...O.|
|
|
||||||
|
|
||||||
[h264 @ 0x7fdf01802200] NAL 9(AUD) at 4/279 length 1
|
|
||||||
[h264 @ 0x7fdf01802200] NAL 6(SEI) at 10/279 length 10
|
|
||||||
[h264 @ 0x7fdf01802200] NAL 6(SEI) at 24/279 length 20
|
|
||||||
[h264 @ 0x7fdf01802200] NAL 7(SPS) at 49/279 length 18
|
|
||||||
[h264 @ 0x7fdf01802200] NAL 8(PPS) at 72/279 length 3
|
|
||||||
[h264 @ 0x7fdf01802200] NAL 5(IDR) at 79/279 length 124
|
|
||||||
[h264 @ 0x7fdf01802200] NAL 5(IDR) at 207/279 length 71
|
|
||||||
|
|
||||||
AUD is a must for QuickTime player.
|
|
||||||
|
|
||||||
NAL_SLICE = 1,
|
|
||||||
NAL_DPA = 2,
|
|
||||||
NAL_DPB = 3,
|
|
||||||
NAL_DPC = 4,
|
|
||||||
NAL_IDR_SLICE = 5,
|
|
||||||
NAL_SEI = 6,
|
|
||||||
NAL_SPS = 7,
|
|
||||||
NAL_PPS = 8,
|
|
||||||
NAL_AUD = 9,
|
|
||||||
NAL_END_SEQUENCE = 10,
|
|
||||||
NAL_END_STREAM = 11,
|
|
||||||
NAL_FILLER_DATA = 12,
|
|
||||||
NAL_SPS_EXT = 13,
|
|
||||||
NAL_AUXILIARY_SLICE = 19,
|
|
||||||
|
|
@ -8,11 +8,15 @@ import (
|
|||||||
|
|
||||||
func Handler(h *avutil.RegisterHandler) {
|
func Handler(h *avutil.RegisterHandler) {
|
||||||
h.Ext = ".ts"
|
h.Ext = ".ts"
|
||||||
|
|
||||||
h.ReaderDemuxer = func(r io.Reader) av.Demuxer {
|
h.ReaderDemuxer = func(r io.Reader) av.Demuxer {
|
||||||
return NewDemuxer(r)
|
return NewDemuxer(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
h.WriterMuxer = func(w io.Writer) av.Muxer {
|
h.WriterMuxer = func(w io.Writer) av.Muxer {
|
||||||
return NewMuxer(w)
|
return NewMuxer(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h.CodecTypes = CodecTypes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,22 +26,18 @@ type Muxer struct {
|
|||||||
tswPMT *TSWriter
|
tswPMT *TSWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
var supportedCodecTypes = []av.CodecType{av.H264, av.AAC}
|
var CodecTypes = []av.CodecType{av.H264, av.AAC}
|
||||||
|
|
||||||
func (self Muxer) SupportedCodecTypes() []av.CodecType {
|
|
||||||
return supportedCodecTypes
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Muxer) newStream(codec av.CodecData) (err error) {
|
func (self *Muxer) newStream(codec av.CodecData) (err error) {
|
||||||
ok := false
|
ok := false
|
||||||
for _, c := range supportedCodecTypes {
|
for _, c := range CodecTypes {
|
||||||
if codec.Type() == c {
|
if codec.Type() == c {
|
||||||
ok = true
|
ok = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
err = fmt.Errorf("codec type=%x is not supported", codec.Type())
|
err = fmt.Errorf("ts: codec type=%s is not supported", codec.Type())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,164 +39,6 @@ func ReadUInt64(r io.Reader, n int) (res uint64, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadTSHeader(r io.Reader) (self TSHeader, err error) {
|
|
||||||
var flags uint
|
|
||||||
|
|
||||||
// sync(8)
|
|
||||||
// transport_error_indicator(1)
|
|
||||||
// payload_unit_start_indicator(1)
|
|
||||||
// transport_priority(1)
|
|
||||||
// pid(13)
|
|
||||||
// Scrambling control(2)
|
|
||||||
// Adaptation field flag(1)
|
|
||||||
// Continuity counter(4)
|
|
||||||
if flags, err = ReadUInt(r, 4); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if DebugReader {
|
|
||||||
fmt.Fprintf(DebugOutput, "ts: flags %s\n", FieldsDumper{
|
|
||||||
Fields: []struct {
|
|
||||||
Length int
|
|
||||||
Desc string
|
|
||||||
}{
|
|
||||||
{8, "sync"},
|
|
||||||
{1, "transport_error_indicator"},
|
|
||||||
{1, "payload_unit_start_indicator"},
|
|
||||||
{1, "transport_priority"},
|
|
||||||
{13, "pid"},
|
|
||||||
{2, "scrambling_control"},
|
|
||||||
{1, "adaptation_field_flag"},
|
|
||||||
{1, "payload_flag"},
|
|
||||||
{4, "continuity_counter"},
|
|
||||||
},
|
|
||||||
Val: flags,
|
|
||||||
Length: 32,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if flags&0x400000 != 0 {
|
|
||||||
// When set to '1' it indicates that this TS packet contains the first PES packet.
|
|
||||||
self.PayloadUnitStart = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags&0xff000000)>>24 != 0x47 {
|
|
||||||
err = fmt.Errorf("invalid sync")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.PID = (flags & 0x1fff00) >> 8
|
|
||||||
self.ContinuityCounter = flags & 0xf
|
|
||||||
|
|
||||||
if flags&0x20 != 0 {
|
|
||||||
var flags, length uint
|
|
||||||
if length, err = ReadUInt(r, 1); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if length > 0 {
|
|
||||||
lr := &io.LimitedReader{R: r, N: int64(length)}
|
|
||||||
if flags, err = ReadUInt(lr, 1); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if DebugReader {
|
|
||||||
fmt.Fprintf(DebugOutput, "ts: ext_flags %s\n", FieldsDumper{
|
|
||||||
Fields: []struct {
|
|
||||||
Length int
|
|
||||||
Desc string
|
|
||||||
}{
|
|
||||||
{1, "discontinuity_indicator"},
|
|
||||||
{1, "random_access_indicator"},
|
|
||||||
{1, "elementary_stream_priority_indicator"},
|
|
||||||
{1, "pcr_flag"},
|
|
||||||
{1, "opcr_flag"},
|
|
||||||
{1, "splicing_point_flag"},
|
|
||||||
{1, "transport_private_data_flag"},
|
|
||||||
{1, "adaptation_field_extension_flag"},
|
|
||||||
},
|
|
||||||
Val: flags,
|
|
||||||
Length: 8,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// random_access_indicator
|
|
||||||
if flags&0x40 != 0 {
|
|
||||||
self.RandomAccessIndicator = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// PCR
|
|
||||||
if flags&0x10 != 0 {
|
|
||||||
var v uint64
|
|
||||||
if v, err = ReadUInt64(lr, 6); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// clock is 27MHz
|
|
||||||
self.PCR = UIntToPCR(v)
|
|
||||||
if DebugReader {
|
|
||||||
fmt.Fprintf(DebugOutput, "ts: PCR %d %f\n", self.PCR, float32(self.PCR)/PCR_HZ)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OPCR
|
|
||||||
if flags&0x08 != 0 {
|
|
||||||
var v uint64
|
|
||||||
if v, err = ReadUInt64(lr, 6); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
self.OPCR = UIntToPCR(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Splice countdown
|
|
||||||
if flags&0x04 != 0 {
|
|
||||||
if _, err = ReadUInt(lr, 1); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transport private data
|
|
||||||
if flags&0x02 != 0 {
|
|
||||||
var length uint
|
|
||||||
if length, err = ReadUInt(lr, 1); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
b := make([]byte, length)
|
|
||||||
if _, err = lr.Read(b); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adaptation extension
|
|
||||||
if lr.N > 0 {
|
|
||||||
if DebugReader {
|
|
||||||
// rubish
|
|
||||||
fmt.Fprintln(DebugOutput, "ts: skip", lr.N)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = ReadDummy(lr, int(lr.N)); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadTSPacket(r io.Reader, data []byte) (self TSHeader, n int, err error) {
|
|
||||||
lr := &io.LimitedReader{R: r, N: 188}
|
|
||||||
if self, err = ReadTSHeader(lr); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if DebugReader {
|
|
||||||
fmt.Fprintln(DebugOutput, "ts: data len", lr.N)
|
|
||||||
}
|
|
||||||
if n, err = lr.Read(data[:lr.N]); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadPSI(r io.Reader) (self PSI, lr *io.LimitedReader, cr *Crc32Reader, err error) {
|
func ReadPSI(r io.Reader) (self PSI, lr *io.LimitedReader, cr *Crc32Reader, err error) {
|
||||||
var flags, pointer, length uint
|
var flags, pointer, length uint
|
||||||
|
|
||||||
@ -205,10 +47,6 @@ func ReadPSI(r io.Reader) (self PSI, lr *io.LimitedReader, cr *Crc32Reader, err
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if DebugReader {
|
|
||||||
fmt.Fprintf(DebugOutput, "psi: pointer=%d\n", pointer)
|
|
||||||
}
|
|
||||||
|
|
||||||
if pointer != 0 {
|
if pointer != 0 {
|
||||||
if err = ReadDummy(r, int(pointer)); err != nil {
|
if err = ReadDummy(r, int(pointer)); err != nil {
|
||||||
return
|
return
|
||||||
@ -229,10 +67,6 @@ func ReadPSI(r io.Reader) (self PSI, lr *io.LimitedReader, cr *Crc32Reader, err
|
|||||||
}
|
}
|
||||||
length = flags & 0x3FF
|
length = flags & 0x3FF
|
||||||
|
|
||||||
if DebugReader {
|
|
||||||
fmt.Fprintf(DebugOutput, "psi: tableid=%d len=%d\n", self.TableId, length)
|
|
||||||
}
|
|
||||||
|
|
||||||
lr = &io.LimitedReader{R: cr, N: int64(length)}
|
lr = &io.LimitedReader{R: cr, N: int64(length)}
|
||||||
|
|
||||||
// Table ID extension(16)
|
// Table ID extension(16)
|
||||||
@ -247,21 +81,6 @@ func ReadPSI(r io.Reader) (self PSI, lr *io.LimitedReader, cr *Crc32Reader, err
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if DebugReader {
|
|
||||||
fmt.Fprintf(DebugOutput, "psi: %s\n", FieldsDumper{
|
|
||||||
Fields: []struct {
|
|
||||||
Length int
|
|
||||||
Desc string
|
|
||||||
}{
|
|
||||||
{2, "resverd"},
|
|
||||||
{5, "version"},
|
|
||||||
{1, "current_next_indicator"},
|
|
||||||
},
|
|
||||||
Val: flags,
|
|
||||||
Length: 8,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// section_number(8)
|
// section_number(8)
|
||||||
if self.SecNum, err = ReadUInt(lr, 1); err != nil {
|
if self.SecNum, err = ReadUInt(lr, 1); err != nil {
|
||||||
return
|
return
|
||||||
@ -272,15 +91,6 @@ func ReadPSI(r io.Reader) (self PSI, lr *io.LimitedReader, cr *Crc32Reader, err
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if DebugReader {
|
|
||||||
fmt.Fprintf(DebugOutput, "psi: table_id=%x table_extension=%x secnum=%x lastsecnum=%x\n",
|
|
||||||
self.TableId,
|
|
||||||
self.TableIdExtension,
|
|
||||||
self.SecNum,
|
|
||||||
self.LastSecNum,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
lr.N -= 4
|
lr.N -= 4
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -322,20 +132,6 @@ func ReadPMT(r io.Reader) (self PMT, err error) {
|
|||||||
}
|
}
|
||||||
self.PCRPID = flags & 0x1fff
|
self.PCRPID = flags & 0x1fff
|
||||||
|
|
||||||
if DebugReader {
|
|
||||||
fmt.Fprintf(DebugOutput, "pmt: %s\n", FieldsDumper{
|
|
||||||
Fields: []struct {
|
|
||||||
Length int
|
|
||||||
Desc string
|
|
||||||
}{
|
|
||||||
{3, "reserved"},
|
|
||||||
{13, "pcrpid"},
|
|
||||||
},
|
|
||||||
Val: flags,
|
|
||||||
Length: 16,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reserved(4)=0xf
|
// Reserved(4)=0xf
|
||||||
// Reserved(2)=0x0
|
// Reserved(2)=0x0
|
||||||
// Program info length(10)
|
// Program info length(10)
|
||||||
@ -344,10 +140,6 @@ func ReadPMT(r io.Reader) (self PMT, err error) {
|
|||||||
}
|
}
|
||||||
length = flags & 0x3ff
|
length = flags & 0x3ff
|
||||||
|
|
||||||
if DebugReader {
|
|
||||||
fmt.Fprintf(DebugOutput, "pmt: ProgramDescriptorsLen=%d\n", length)
|
|
||||||
}
|
|
||||||
|
|
||||||
if length > 0 {
|
if length > 0 {
|
||||||
lr := &io.LimitedReader{R: lr, N: int64(length)}
|
lr := &io.LimitedReader{R: lr, N: int64(length)}
|
||||||
if self.ProgramDescriptors, err = readDescs(lr); err != nil {
|
if self.ProgramDescriptors, err = readDescs(lr); err != nil {
|
||||||
@ -368,20 +160,6 @@ func ReadPMT(r io.Reader) (self PMT, err error) {
|
|||||||
}
|
}
|
||||||
info.ElementaryPID = flags & 0x1fff
|
info.ElementaryPID = flags & 0x1fff
|
||||||
|
|
||||||
if DebugReader {
|
|
||||||
fmt.Fprintf(DebugOutput, "pmt: info1 %s\n", FieldsDumper{
|
|
||||||
Fields: []struct {
|
|
||||||
Length int
|
|
||||||
Desc string
|
|
||||||
}{
|
|
||||||
{3, "reserved"},
|
|
||||||
{13, "elementary_pid"},
|
|
||||||
},
|
|
||||||
Val: flags,
|
|
||||||
Length: 16,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reserved(6)
|
// Reserved(6)
|
||||||
// ES Info length(10)
|
// ES Info length(10)
|
||||||
if flags, err = ReadUInt(lr, 2); err != nil {
|
if flags, err = ReadUInt(lr, 2); err != nil {
|
||||||
@ -389,20 +167,6 @@ func ReadPMT(r io.Reader) (self PMT, err error) {
|
|||||||
}
|
}
|
||||||
length = flags & 0x3ff
|
length = flags & 0x3ff
|
||||||
|
|
||||||
if DebugReader {
|
|
||||||
fmt.Fprintf(DebugOutput, "pmt: info2 %s\n", FieldsDumper{
|
|
||||||
Fields: []struct {
|
|
||||||
Length int
|
|
||||||
Desc string
|
|
||||||
}{
|
|
||||||
{6, "reserved"},
|
|
||||||
{10, "es_info_length"},
|
|
||||||
},
|
|
||||||
Val: flags,
|
|
||||||
Length: 16,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if length > 0 {
|
if length > 0 {
|
||||||
lr := &io.LimitedReader{R: lr, N: int64(length)}
|
lr := &io.LimitedReader{R: lr, N: int64(length)}
|
||||||
if info.Descriptors, err = readDescs(lr); err != nil {
|
if info.Descriptors, err = readDescs(lr); err != nil {
|
||||||
@ -412,15 +176,7 @@ func ReadPMT(r io.Reader) (self PMT, err error) {
|
|||||||
self.ElementaryStreamInfos = append(self.ElementaryStreamInfos, info)
|
self.ElementaryStreamInfos = append(self.ElementaryStreamInfos, info)
|
||||||
}
|
}
|
||||||
|
|
||||||
if DebugReader {
|
|
||||||
fmt.Fprintf(DebugOutput, "pmt: ProgramDescriptors %v\n", self.ProgramDescriptors)
|
|
||||||
fmt.Fprintf(DebugOutput, "pmt: ElementaryStreamInfos %v\n", self.ElementaryStreamInfos)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = cr.ReadCrc32UIntAndCheck(); err != nil {
|
if err = cr.ReadCrc32UIntAndCheck(); err != nil {
|
||||||
if DebugReader {
|
|
||||||
fmt.Fprintf(DebugOutput, "pmt: %s\n", err)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,16 +212,9 @@ func ReadPAT(r io.Reader) (self PAT, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err = cr.ReadCrc32UIntAndCheck(); err != nil {
|
if err = cr.ReadCrc32UIntAndCheck(); err != nil {
|
||||||
if DebugReader {
|
|
||||||
fmt.Fprintf(DebugOutput, "pat: %s\n", err)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if DebugReader {
|
|
||||||
fmt.Fprintf(DebugOutput, "pat: %v\n", self)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -491,9 +240,6 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
|
|||||||
if length, err = ReadUInt(r, 2); err != nil {
|
if length, err = ReadUInt(r, 2); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if DebugReader {
|
|
||||||
fmt.Fprintf(DebugOutput, "pes: StreamId=%x length=%d\n", self.StreamId, length)
|
|
||||||
}
|
|
||||||
|
|
||||||
if length == 0 {
|
if length == 0 {
|
||||||
length = 1 << 31
|
length = 1 << 31
|
||||||
@ -511,23 +257,6 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if DebugReader {
|
|
||||||
fmt.Fprintf(DebugOutput, "pes: %s\n", FieldsDumper{
|
|
||||||
Fields: []struct {
|
|
||||||
Length int
|
|
||||||
Desc string
|
|
||||||
}{
|
|
||||||
{2, "scrambling_control"},
|
|
||||||
{1, "priority"},
|
|
||||||
{1, "data_alignment_indicator"},
|
|
||||||
{1, "copyright"},
|
|
||||||
{1, "original_or_copy"},
|
|
||||||
},
|
|
||||||
Val: flags,
|
|
||||||
Length: 6,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// PTS DTS flags(2)
|
// PTS DTS flags(2)
|
||||||
// ESCR flag(1)
|
// ESCR flag(1)
|
||||||
// ES rate flag(1)
|
// ES rate flag(1)
|
||||||
@ -539,25 +268,6 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if DebugReader {
|
|
||||||
fmt.Fprintf(DebugOutput, "pes: %s\n", FieldsDumper{
|
|
||||||
Fields: []struct {
|
|
||||||
Length int
|
|
||||||
Desc string
|
|
||||||
}{
|
|
||||||
{2, "pts_dts_flags"},
|
|
||||||
{1, "escr_flag"},
|
|
||||||
{1, "es_rate_flag"},
|
|
||||||
{1, "dsm_trick_mode_flag"},
|
|
||||||
{1, "additional_copy_info_flag"},
|
|
||||||
{1, "pes_crc_flag"},
|
|
||||||
{1, "pes_extension_flag"},
|
|
||||||
},
|
|
||||||
Val: flags,
|
|
||||||
Length: 8,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// PES header data length(8)
|
// PES header data length(8)
|
||||||
if length, err = ReadUInt(lr, 1); err != nil {
|
if length, err = ReadUInt(lr, 1); err != nil {
|
||||||
return
|
return
|
||||||
@ -570,10 +280,6 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.PTS = PESUIntToTs(v)
|
self.PTS = PESUIntToTs(v)
|
||||||
|
|
||||||
if DebugReader {
|
|
||||||
fmt.Fprintf(DebugOutput, "pes: pts %d %f\n", self.PTS, float32(self.PTS)/float32(PTS_HZ))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags&0x40 != 0 && flags&0x80 != 0 {
|
if flags&0x40 != 0 && flags&0x80 != 0 {
|
||||||
@ -582,9 +288,6 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.DTS = PESUIntToTs(v)
|
self.DTS = PESUIntToTs(v)
|
||||||
if DebugReader {
|
|
||||||
fmt.Fprintf(DebugOutput, "pes: dts %d %f\n", self.DTS, float32(self.DTS)/float32(PTS_HZ))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ESCR flag
|
// ESCR flag
|
||||||
|
@ -11,7 +11,6 @@ type Stream struct {
|
|||||||
|
|
||||||
buf bytes.Buffer
|
buf bytes.Buffer
|
||||||
peshdr *PESHeader
|
peshdr *PESHeader
|
||||||
tshdr TSHeader
|
|
||||||
|
|
||||||
demuxer *Demuxer
|
demuxer *Demuxer
|
||||||
muxer *Muxer
|
muxer *Muxer
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
package ts
|
package ts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"io"
|
||||||
"os"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -10,17 +9,6 @@ const (
|
|||||||
ElementaryStreamTypeAdtsAAC = 0x0F
|
ElementaryStreamTypeAdtsAAC = 0x0F
|
||||||
)
|
)
|
||||||
|
|
||||||
type TSHeader struct {
|
|
||||||
PID uint
|
|
||||||
PCR uint64
|
|
||||||
OPCR uint64
|
|
||||||
ContinuityCounter uint
|
|
||||||
PayloadUnitStart bool
|
|
||||||
DiscontinuityIndicator bool
|
|
||||||
RandomAccessIndicator bool
|
|
||||||
HeaderLength uint
|
|
||||||
}
|
|
||||||
|
|
||||||
type PATEntry struct {
|
type PATEntry struct {
|
||||||
ProgramNumber uint
|
ProgramNumber uint
|
||||||
NetworkPID uint
|
NetworkPID uint
|
||||||
@ -96,27 +84,9 @@ func PCRToUInt(pcr uint64) uint64 {
|
|||||||
return base<<15 | 0x3f<<9 | ext
|
return base<<15 | 0x3f<<9 | ext
|
||||||
}
|
}
|
||||||
|
|
||||||
var DebugOutput = os.Stdout
|
type TSWriter struct {
|
||||||
var DebugReader = false
|
w io.Writer
|
||||||
var DebugWriter = false
|
ContinuityCounter uint
|
||||||
|
tshdr []byte
|
||||||
type FieldsDumper struct {
|
|
||||||
Fields []struct {
|
|
||||||
Length int
|
|
||||||
Desc string
|
|
||||||
}
|
|
||||||
Val uint
|
|
||||||
Length uint
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self FieldsDumper) String() (res string) {
|
|
||||||
pos := uint(self.Length)
|
|
||||||
for _, field := range self.Fields {
|
|
||||||
pos -= uint(field.Length)
|
|
||||||
val := (self.Val >> pos) & (1<<uint(field.Length) - 1)
|
|
||||||
if val != 0 {
|
|
||||||
res += fmt.Sprintf("%s=%x ", field.Desc, val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
package ts
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestPESTsConv(t *testing.T) {
|
|
||||||
t.Logf("%x", PESTsToUInt(0x123))
|
|
||||||
}
|
|
@ -1,135 +0,0 @@
|
|||||||
package ts
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
type iovec struct {
|
|
||||||
data [][]byte
|
|
||||||
Len int
|
|
||||||
pos int
|
|
||||||
idx int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *iovec) Prepend(b []byte) {
|
|
||||||
self.data = append([][]byte{b}, self.data...)
|
|
||||||
self.Len += len(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *iovec) Append(b []byte) {
|
|
||||||
self.data = append(self.data, b)
|
|
||||||
self.Len += len(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *iovec) WriteTo(w io.Writer, n int) (written int, err error) {
|
|
||||||
for n > 0 && self.Len > 0 {
|
|
||||||
data := self.data[self.idx]
|
|
||||||
|
|
||||||
var b []byte
|
|
||||||
if n > len(data) {
|
|
||||||
b = data
|
|
||||||
} else {
|
|
||||||
b = data[:n]
|
|
||||||
}
|
|
||||||
|
|
||||||
data = data[len(b):]
|
|
||||||
if len(data) == 0 {
|
|
||||||
self.idx++
|
|
||||||
} else {
|
|
||||||
self.data[self.idx] = data
|
|
||||||
}
|
|
||||||
self.Len -= len(b)
|
|
||||||
n -= len(b)
|
|
||||||
written += len(b)
|
|
||||||
|
|
||||||
if _, err = w.Write(b); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type sysiovec struct {
|
|
||||||
Base uintptr
|
|
||||||
Len uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
type vecWriter struct {
|
|
||||||
fd uintptr
|
|
||||||
smallBytesBuf []byte
|
|
||||||
iov []sysiovec
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *vecWriter) Write(p []byte) (written int, err error) {
|
|
||||||
iov := sysiovec{
|
|
||||||
Len: uint64(len(p)),
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(p) < 16 {
|
|
||||||
iov.Base = uintptr(len(self.smallBytesBuf))
|
|
||||||
self.smallBytesBuf = append(self.smallBytesBuf, p...)
|
|
||||||
} else {
|
|
||||||
iov.Base = uintptr(unsafe.Pointer(&p[0]))
|
|
||||||
}
|
|
||||||
|
|
||||||
self.iov = append(self.iov, iov)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *vecWriter) Flush() (err error) {
|
|
||||||
for i := range self.iov {
|
|
||||||
iov := &self.iov[i]
|
|
||||||
if iov.Base < uintptr(len(self.smallBytesBuf)) {
|
|
||||||
iov.Base = uintptr(unsafe.Pointer(&self.smallBytesBuf[iov.Base]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
N := 1024
|
|
||||||
for i := 0; i < len(self.iov); i += N {
|
|
||||||
n := len(self.iov) - i
|
|
||||||
if n > N {
|
|
||||||
n = N
|
|
||||||
}
|
|
||||||
_, _, errno := syscall.Syscall(syscall.SYS_WRITEV, self.fd, uintptr(unsafe.Pointer(&self.iov[i])), uintptr(n))
|
|
||||||
if errno != 0 {
|
|
||||||
err = fmt.Errorf("writev failed with error: %d", errno)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if DebugWriter {
|
|
||||||
fmt.Printf("vecw: smallBytesBuf=%d iovNr=%d\n", len(self.smallBytesBuf), len(self.iov))
|
|
||||||
}
|
|
||||||
|
|
||||||
self.iov = self.iov[:0]
|
|
||||||
self.smallBytesBuf = self.smallBytesBuf[:0]
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func newVecWriter(w io.Writer) (vecw *vecWriter) {
|
|
||||||
var err error
|
|
||||||
var f *os.File
|
|
||||||
|
|
||||||
switch obj := w.(type) {
|
|
||||||
case *net.TCPConn:
|
|
||||||
f, err = obj.File()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case *os.File:
|
|
||||||
f = obj
|
|
||||||
default:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
vecw = &vecWriter{
|
|
||||||
fd: f.Fd(),
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
@ -2,7 +2,6 @@ package ts
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -22,12 +21,6 @@ func WriteUInt(w io.Writer, val uint, n int) (err error) {
|
|||||||
return WriteUInt64(w, uint64(val), n)
|
return WriteUInt64(w, uint64(val), n)
|
||||||
}
|
}
|
||||||
|
|
||||||
type TSWriter struct {
|
|
||||||
w io.Writer
|
|
||||||
ContinuityCounter uint
|
|
||||||
tshdr []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func WritePSI(w io.Writer, self PSI, data []byte) (err error) {
|
func WritePSI(w io.Writer, self PSI, data []byte) (err error) {
|
||||||
// pointer(8)
|
// pointer(8)
|
||||||
// table_id(8)
|
// table_id(8)
|
||||||
@ -59,10 +52,6 @@ func WritePSI(w io.Writer, self PSI, data []byte) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if DebugWriter {
|
|
||||||
fmt.Fprintf(DebugOutput, "psiw: length=%d\n", length)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Table ID extension(16)
|
// Table ID extension(16)
|
||||||
if err = WriteUInt(cw, self.TableIdExtension, 2); err != nil {
|
if err = WriteUInt(cw, self.TableIdExtension, 2); err != nil {
|
||||||
return
|
return
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
package ts
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestWriteTSHeader(t *testing.T) {
|
|
||||||
bw := &bytes.Buffer{}
|
|
||||||
w := &TSWriter{
|
|
||||||
W: bw,
|
|
||||||
PCR: 0x12345678,
|
|
||||||
}
|
|
||||||
w.Write([]byte{'h', 'e', 'l', 'o'}[:], false)
|
|
||||||
t.Logf("\n%s", hex.Dump(bw.Bytes()))
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user