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()
|
||||
|
||||
if muxer, err = avutil.Create(output); err != nil {
|
||||
var handler avutil.RegisterHandler
|
||||
if handler, muxer, err = avutil.DefaultHandlers.FindCreate(output); err != nil {
|
||||
return
|
||||
}
|
||||
defer muxer.Close()
|
||||
|
||||
type intf interface {
|
||||
SupportedCodecTypes() []av.CodecType
|
||||
}
|
||||
if fn, ok := muxer.(intf); ok {
|
||||
options.OutputCodecTypes = fn.SupportedCodecTypes()
|
||||
}
|
||||
options.OutputCodecTypes = handler.CodecTypes
|
||||
|
||||
convdemux := &Demuxer{
|
||||
Options: options,
|
||||
|
@ -11,22 +11,22 @@ import (
|
||||
"path"
|
||||
)
|
||||
|
||||
type handlerDemuxer struct {
|
||||
type HandlerDemuxer struct {
|
||||
av.Demuxer
|
||||
r io.ReadCloser
|
||||
}
|
||||
|
||||
func (self *handlerDemuxer) Close() error {
|
||||
func (self *HandlerDemuxer) Close() error {
|
||||
return self.r.Close()
|
||||
}
|
||||
|
||||
type handlerMuxer struct {
|
||||
type HandlerMuxer struct {
|
||||
av.Muxer
|
||||
w io.WriteCloser
|
||||
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 err = self.Muxer.WriteHeader(streams); err != nil {
|
||||
return
|
||||
@ -36,7 +36,7 @@ func (self *handlerMuxer) WriteHeader(streams []av.CodecData) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (self *handlerMuxer) WriteTrailer() (err error) {
|
||||
func (self *HandlerMuxer) WriteTrailer() (err error) {
|
||||
if self.stage == 1 {
|
||||
if err = self.Muxer.WriteTrailer(); err != nil {
|
||||
return
|
||||
@ -46,7 +46,7 @@ func (self *handlerMuxer) WriteTrailer() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (self *handlerMuxer) Close() (err error) {
|
||||
func (self *HandlerMuxer) Close() (err error) {
|
||||
if err = self.WriteTrailer(); err != nil {
|
||||
return
|
||||
}
|
||||
@ -64,6 +64,7 @@ type RegisterHandler struct {
|
||||
AudioDecoder func(av.AudioCodecData)(av.AudioDecoder,error)
|
||||
ServerDemuxer func(string)(bool,av.DemuxCloser,error)
|
||||
ServerMuxer func(string)(bool,av.MuxCloser,error)
|
||||
CodecTypes []av.CodecType
|
||||
}
|
||||
|
||||
type Handlers struct {
|
||||
@ -163,7 +164,7 @@ func (self *Handlers) Open(uri string) (demuxer av.DemuxCloser, err error) {
|
||||
if r, err = self.openUrl(u, uri); err != nil {
|
||||
return
|
||||
}
|
||||
demuxer = &handlerDemuxer{
|
||||
demuxer = &HandlerDemuxer{
|
||||
Demuxer: handler.ReaderDemuxer(r),
|
||||
r: r,
|
||||
}
|
||||
@ -183,7 +184,7 @@ func (self *Handlers) Open(uri string) (demuxer av.DemuxCloser, err error) {
|
||||
|
||||
for _, handler := range self.handlers {
|
||||
if handler.Probe != nil && handler.Probe(probebuf[:]) && handler.ReaderDemuxer != nil {
|
||||
demuxer = &handlerDemuxer{
|
||||
demuxer = &HandlerDemuxer{
|
||||
Demuxer: handler.ReaderDemuxer(io.MultiReader(bytes.NewReader(probebuf[:]), 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) {
|
||||
_, muxer, err = self.FindCreate(uri)
|
||||
return
|
||||
}
|
||||
|
||||
func (self *Handlers) FindCreate(uri string) (handler RegisterHandler, muxer av.MuxCloser, err error) {
|
||||
listen := false
|
||||
if strings.HasPrefix(uri, "listen:") {
|
||||
uri = uri[len("listen:"):]
|
||||
listen = true
|
||||
}
|
||||
|
||||
for _, handler := range self.handlers {
|
||||
for _, handler = range self.handlers {
|
||||
if listen {
|
||||
if handler.ServerMuxer != nil {
|
||||
var ok bool
|
||||
@ -223,13 +229,13 @@ func (self *Handlers) Create(uri string) (muxer av.MuxCloser, err error) {
|
||||
}
|
||||
|
||||
if ext != "" {
|
||||
for _, handler := range self.handlers {
|
||||
for _, handler = range self.handlers {
|
||||
if handler.Ext == ext && handler.WriterMuxer != nil {
|
||||
var w io.WriteCloser
|
||||
if w, err = self.createUrl(u, uri); err != nil {
|
||||
return
|
||||
}
|
||||
muxer = &handlerMuxer{
|
||||
muxer = &HandlerMuxer{
|
||||
Muxer: handler.WriterMuxer(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) {
|
||||
if len(streams) > 1 || streams[0].Type() != av.AAC {
|
||||
err = fmt.Errorf("aac: must be only one aac stream")
|
||||
@ -120,4 +116,6 @@ func Handler(h *avutil.RegisterHandler) {
|
||||
_, _, _, _, err := aacparser.ParseADTSHeader(b)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
h.CodecTypes = []av.CodecType{av.AAC}
|
||||
}
|
||||
|
@ -281,11 +281,7 @@ func NewMuxer(w io.Writer) *Muxer {
|
||||
return self
|
||||
}
|
||||
|
||||
var SupportedCodecTypes = []av.CodecType{av.H264, av.AAC, av.SPEEX}
|
||||
|
||||
func (self *Muxer) SupportedCodecTypes() []av.CodecType {
|
||||
return SupportedCodecTypes
|
||||
}
|
||||
var CodecTypes = []av.CodecType{av.H264, av.AAC, av.SPEEX}
|
||||
|
||||
func (self *Muxer) WriteHeader(streams []av.CodecData) (err error) {
|
||||
var flags uint8
|
||||
@ -420,12 +416,17 @@ func Handler(h *avutil.RegisterHandler) {
|
||||
h.Probe = func(b []byte) bool {
|
||||
return b[0] == 'F' && b[1] == 'L' && b[2] == 'V'
|
||||
}
|
||||
|
||||
h.Ext = ".flv"
|
||||
|
||||
h.ReaderDemuxer = func(r io.Reader) av.Demuxer {
|
||||
return NewDemuxer(r)
|
||||
}
|
||||
|
||||
h.WriterMuxer = func(w io.Writer) av.Muxer {
|
||||
return NewMuxer(w)
|
||||
}
|
||||
|
||||
h.CodecTypes = CodecTypes
|
||||
}
|
||||
|
||||
|
@ -6,13 +6,19 @@ import (
|
||||
"github.com/nareix/joy4/av/avutil"
|
||||
)
|
||||
|
||||
var CodecTypes = []av.CodecType{av.H264, av.AAC}
|
||||
|
||||
func Handler(h *avutil.RegisterHandler) {
|
||||
h.Ext = ".mp4"
|
||||
|
||||
h.ReaderDemuxer = func(r io.Reader) av.Demuxer {
|
||||
return NewDemuxer(r.(io.ReadSeeker))
|
||||
}
|
||||
|
||||
h.WriterMuxer = func(w io.Writer) av.Muxer {
|
||||
return NewMuxer(w.(io.WriteSeeker))
|
||||
}
|
||||
|
||||
h.CodecTypes = CodecTypes
|
||||
}
|
||||
|
||||
|
@ -22,10 +22,6 @@ func NewMuxer(w io.WriteSeeker) *Muxer {
|
||||
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) {
|
||||
switch codec.Type() {
|
||||
case av.H264, av.AAC:
|
||||
|
@ -21,6 +21,8 @@ import (
|
||||
"crypto/rand"
|
||||
)
|
||||
|
||||
var Debug bool
|
||||
|
||||
func ParseURL(uri string) (u *url.URL, err error) {
|
||||
if u, err = url.Parse(uri); err != nil {
|
||||
return
|
||||
@ -52,8 +54,6 @@ func DialTimeout(uri string, timeout time.Duration) (conn *Conn, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
var Debug bool
|
||||
|
||||
type Server struct {
|
||||
Addr string
|
||||
HandlePublish func(*Conn)
|
||||
@ -317,9 +317,7 @@ func createURL(tcurl, app, play string) (u *url.URL) {
|
||||
return
|
||||
}
|
||||
|
||||
func (self *Conn) SupportedCodecTypes() []av.CodecType {
|
||||
return flv.SupportedCodecTypes
|
||||
}
|
||||
var CodecTypes = flv.CodecTypes
|
||||
|
||||
func (self *Conn) recvConnect() (err error) {
|
||||
var connectpath string
|
||||
@ -1707,5 +1705,7 @@ func Handler(h *avutil.RegisterHandler) {
|
||||
|
||||
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) {
|
||||
h.Ext = ".ts"
|
||||
|
||||
h.ReaderDemuxer = func(r io.Reader) av.Demuxer {
|
||||
return NewDemuxer(r)
|
||||
}
|
||||
|
||||
h.WriterMuxer = func(w io.Writer) av.Muxer {
|
||||
return NewMuxer(w)
|
||||
}
|
||||
|
||||
h.CodecTypes = CodecTypes
|
||||
}
|
||||
|
||||
|
@ -26,22 +26,18 @@ type Muxer struct {
|
||||
tswPMT *TSWriter
|
||||
}
|
||||
|
||||
var supportedCodecTypes = []av.CodecType{av.H264, av.AAC}
|
||||
|
||||
func (self Muxer) SupportedCodecTypes() []av.CodecType {
|
||||
return supportedCodecTypes
|
||||
}
|
||||
var CodecTypes = []av.CodecType{av.H264, av.AAC}
|
||||
|
||||
func (self *Muxer) newStream(codec av.CodecData) (err error) {
|
||||
ok := false
|
||||
for _, c := range supportedCodecTypes {
|
||||
for _, c := range CodecTypes {
|
||||
if codec.Type() == c {
|
||||
ok = true
|
||||
break
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -39,164 +39,6 @@ func ReadUInt64(r io.Reader, n int) (res uint64, err error) {
|
||||
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) {
|
||||
var flags, pointer, length uint
|
||||
|
||||
@ -205,10 +47,6 @@ func ReadPSI(r io.Reader) (self PSI, lr *io.LimitedReader, cr *Crc32Reader, err
|
||||
return
|
||||
}
|
||||
|
||||
if DebugReader {
|
||||
fmt.Fprintf(DebugOutput, "psi: pointer=%d\n", pointer)
|
||||
}
|
||||
|
||||
if pointer != 0 {
|
||||
if err = ReadDummy(r, int(pointer)); err != nil {
|
||||
return
|
||||
@ -229,10 +67,6 @@ func ReadPSI(r io.Reader) (self PSI, lr *io.LimitedReader, cr *Crc32Reader, err
|
||||
}
|
||||
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)}
|
||||
|
||||
// Table ID extension(16)
|
||||
@ -247,21 +81,6 @@ func ReadPSI(r io.Reader) (self PSI, lr *io.LimitedReader, cr *Crc32Reader, err
|
||||
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)
|
||||
if self.SecNum, err = ReadUInt(lr, 1); err != nil {
|
||||
return
|
||||
@ -272,15 +91,6 @@ func ReadPSI(r io.Reader) (self PSI, lr *io.LimitedReader, cr *Crc32Reader, err
|
||||
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
|
||||
return
|
||||
}
|
||||
@ -322,20 +132,6 @@ func ReadPMT(r io.Reader) (self PMT, err error) {
|
||||
}
|
||||
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(2)=0x0
|
||||
// Program info length(10)
|
||||
@ -344,10 +140,6 @@ func ReadPMT(r io.Reader) (self PMT, err error) {
|
||||
}
|
||||
length = flags & 0x3ff
|
||||
|
||||
if DebugReader {
|
||||
fmt.Fprintf(DebugOutput, "pmt: ProgramDescriptorsLen=%d\n", length)
|
||||
}
|
||||
|
||||
if length > 0 {
|
||||
lr := &io.LimitedReader{R: lr, N: int64(length)}
|
||||
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
|
||||
|
||||
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)
|
||||
// ES Info length(10)
|
||||
if flags, err = ReadUInt(lr, 2); err != nil {
|
||||
@ -389,20 +167,6 @@ func ReadPMT(r io.Reader) (self PMT, err error) {
|
||||
}
|
||||
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 {
|
||||
lr := &io.LimitedReader{R: lr, N: int64(length)}
|
||||
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)
|
||||
}
|
||||
|
||||
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 DebugReader {
|
||||
fmt.Fprintf(DebugOutput, "pmt: %s\n", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -456,16 +212,9 @@ func ReadPAT(r io.Reader) (self PAT, err error) {
|
||||
}
|
||||
|
||||
if err = cr.ReadCrc32UIntAndCheck(); err != nil {
|
||||
if DebugReader {
|
||||
fmt.Fprintf(DebugOutput, "pat: %s\n", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if DebugReader {
|
||||
fmt.Fprintf(DebugOutput, "pat: %v\n", self)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@ -491,9 +240,6 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
|
||||
if length, err = ReadUInt(r, 2); err != nil {
|
||||
return
|
||||
}
|
||||
if DebugReader {
|
||||
fmt.Fprintf(DebugOutput, "pes: StreamId=%x length=%d\n", self.StreamId, length)
|
||||
}
|
||||
|
||||
if length == 0 {
|
||||
length = 1 << 31
|
||||
@ -511,23 +257,6 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
|
||||
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)
|
||||
// ESCR flag(1)
|
||||
// ES rate flag(1)
|
||||
@ -539,25 +268,6 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
|
||||
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)
|
||||
if length, err = ReadUInt(lr, 1); err != nil {
|
||||
return
|
||||
@ -570,10 +280,6 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
|
||||
return
|
||||
}
|
||||
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 {
|
||||
@ -582,9 +288,6 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
|
||||
return
|
||||
}
|
||||
self.DTS = PESUIntToTs(v)
|
||||
if DebugReader {
|
||||
fmt.Fprintf(DebugOutput, "pes: dts %d %f\n", self.DTS, float32(self.DTS)/float32(PTS_HZ))
|
||||
}
|
||||
}
|
||||
|
||||
// ESCR flag
|
||||
|
@ -11,7 +11,6 @@ type Stream struct {
|
||||
|
||||
buf bytes.Buffer
|
||||
peshdr *PESHeader
|
||||
tshdr TSHeader
|
||||
|
||||
demuxer *Demuxer
|
||||
muxer *Muxer
|
||||
|
@ -1,8 +1,7 @@
|
||||
package ts
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"io"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -10,17 +9,6 @@ const (
|
||||
ElementaryStreamTypeAdtsAAC = 0x0F
|
||||
)
|
||||
|
||||
type TSHeader struct {
|
||||
PID uint
|
||||
PCR uint64
|
||||
OPCR uint64
|
||||
ContinuityCounter uint
|
||||
PayloadUnitStart bool
|
||||
DiscontinuityIndicator bool
|
||||
RandomAccessIndicator bool
|
||||
HeaderLength uint
|
||||
}
|
||||
|
||||
type PATEntry struct {
|
||||
ProgramNumber uint
|
||||
NetworkPID uint
|
||||
@ -96,27 +84,9 @@ func PCRToUInt(pcr uint64) uint64 {
|
||||
return base<<15 | 0x3f<<9 | ext
|
||||
}
|
||||
|
||||
var DebugOutput = os.Stdout
|
||||
var DebugReader = false
|
||||
var DebugWriter = false
|
||||
|
||||
type FieldsDumper struct {
|
||||
Fields []struct {
|
||||
Length int
|
||||
Desc string
|
||||
}
|
||||
Val uint
|
||||
Length uint
|
||||
type TSWriter struct {
|
||||
w io.Writer
|
||||
ContinuityCounter uint
|
||||
tshdr []byte
|
||||
}
|
||||
|
||||
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 (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
@ -22,12 +21,6 @@ func WriteUInt(w io.Writer, val uint, n int) (err error) {
|
||||
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) {
|
||||
// pointer(8)
|
||||
// table_id(8)
|
||||
@ -59,10 +52,6 @@ func WritePSI(w io.Writer, self PSI, data []byte) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if DebugWriter {
|
||||
fmt.Fprintf(DebugOutput, "psiw: length=%d\n", length)
|
||||
}
|
||||
|
||||
// Table ID extension(16)
|
||||
if err = WriteUInt(cw, self.TableIdExtension, 2); err != nil {
|
||||
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