add ReadHeader

This commit is contained in:
nareix 2016-06-26 20:59:49 +08:00
parent 7d9968dd5d
commit 57541c0a59

148
server.go
View File

@ -108,7 +108,9 @@ type Conn struct {
Host string Host string
Path string Path string
Debug bool Debug bool
streams []av.CodecData streams []av.CodecData
videostreamidx, audiostreamidx int
br *pio.Reader br *pio.Reader
bw *pio.Writer bw *pio.Writer
@ -138,6 +140,7 @@ type Conn struct {
gotmsg bool gotmsg bool
msgdata []byte msgdata []byte
msgtypeid uint8 msgtypeid uint8
datamsgvals []interface{}
eventtype uint16 eventtype uint16
} }
@ -363,6 +366,34 @@ func (self *Conn) checkCreateStreamResult() (ok bool, avmsgsid uint32) {
return return
} }
func (self *Conn) parseMetaData(metadata flvio.AMFMap) (atype, vtype av.CodecType, err error) {
if v, ok := metadata["videocodecid"].(float64); ok {
codecid := int(v)
switch codecid {
case flvio.VIDEO_H264:
vtype = av.H264
default:
err = fmt.Errorf("rtmp: videocodecid=%d unspported", codecid)
return
}
}
if v, ok := metadata["audiocodecid"].(float64); ok {
codecid := int(v)
switch codecid {
case flvio.SOUND_AAC:
atype = av.AAC
default:
err = fmt.Errorf("rtmp: audiocodecid=%d unspported", codecid)
return
}
}
return
}
func (self *Conn) connectPlay() (err error) { func (self *Conn) connectPlay() (err error) {
var connectpath, playpath string var connectpath, playpath string
pathsegs := strings.Split(self.Path, "/") pathsegs := strings.Split(self.Path, "/")
@ -441,8 +472,103 @@ func (self *Conn) connectPlay() (err error) {
} }
} }
fmt.Println("rtmp: play", playpath) // > play('app')
fmt.Printf("rtmp: > play('%s')\n", playpath)
w = self.writeCommandMsgStart()
flvio.WriteAMF0Val(w, "play")
flvio.WriteAMF0Val(w, 0)
flvio.WriteAMF0Val(w, nil)
flvio.WriteAMF0Val(w, playpath)
self.writeCommandMsgEnd(8, self.avmsgsid)
var atype, vtype av.CodecType
for {
if err = self.pollMsg(); err != nil {
return
}
if self.msgtypeid == msgtypeidDataMsgAMF0 {
if len(self.datamsgvals) >= 2 {
name, _ := self.datamsgvals[0].(string)
data, _ := self.datamsgvals[1].(flvio.AMFMap)
if name == "onMetaData" {
if atype, vtype, err = self.parseMetaData(data); err != nil {
return
}
fmt.Printf("rtmp: < onMetaData()\n")
break
}
}
}
}
nrstreams := 0
if atype != 0 {
nrstreams++
}
if vtype != 0 {
nrstreams++
}
for i := 0; ; i++ {
if err = self.pollMsg(); err != nil {
return
}
switch {
case self.msgtypeid == msgtypeidVideoMsg && vtype != 0:
tag := &flvio.Videodata{}
r := pio.NewReaderBytes(self.msgdata)
r.LimitOn(int64(len(self.msgdata)))
if err = tag.Unmarshal(r); err != nil {
return
}
switch vtype {
case av.H264:
if tag.AVCPacketType == flvio.AVC_SEQHDR {
var codec h264parser.CodecData
if codec, err = h264parser.NewCodecDataFromAVCDecoderConfRecord(tag.Data); err != nil {
err = fmt.Errorf("rtmp: h264 codec data invalid")
return
}
self.videostreamidx = len(self.streams)
self.streams = append(self.streams, codec)
}
}
case self.msgtypeid == msgtypeidAudioMsg && atype != 0:
tag := &flvio.Audiodata{}
r := pio.NewReaderBytes(self.msgdata)
r.LimitOn(int64(len(self.msgdata)))
if err = tag.Unmarshal(r); err != nil {
return
}
switch atype {
case av.AAC:
if tag.AACPacketType == flvio.AAC_SEQHDR {
var codec aacparser.CodecData
if codec, err = aacparser.NewCodecDataFromMPEG4AudioConfigBytes(tag.Data); err != nil {
err = fmt.Errorf("rtmp: aac codec data invalid")
return
}
self.audiostreamidx = len(self.streams)
self.streams = append(self.streams, codec)
}
}
}
if nrstreams == len(self.streams) {
break
}
if i > 100 {
err = fmt.Errorf("rtmp: probe failed")
return
}
}
return
}
func (self *Conn) ReadPacket() (pkt av.Packet, err error) {
return return
} }
@ -982,7 +1108,6 @@ func (self *Conn) handleCommandMsgAMF0(r *pio.Reader) (err error) {
} }
func (self *Conn) handleMsg(msgsid uint32, msgtypeid uint8, msgdata []byte) (err error) { func (self *Conn) handleMsg(msgsid uint32, msgtypeid uint8, msgdata []byte) (err error) {
self.msgdata = msgdata
self.msgtypeid = msgtypeid self.msgtypeid = msgtypeid
switch msgtypeid { switch msgtypeid {
@ -1002,10 +1127,29 @@ func (self *Conn) handleMsg(msgsid uint32, msgtypeid uint8, msgdata []byte) (err
case msgtypeidUserControl: case msgtypeidUserControl:
if len(msgdata) >= 2 { if len(msgdata) >= 2 {
self.eventtype = pio.GetU16BE(msgdata) self.eventtype = pio.GetU16BE(msgdata)
self.msgdata = msgdata
} else { } else {
err = fmt.Errorf("rtmp: short packet of UserControl") err = fmt.Errorf("rtmp: short packet of UserControl")
return return
} }
case msgtypeidDataMsgAMF0:
r := pio.NewReaderBytes(msgdata)
self.datamsgvals = []interface{}{}
for {
if val, err := flvio.ReadAMF0Val(r); err != nil {
break
} else {
self.datamsgvals = append(self.datamsgvals, val)
}
}
case msgtypeidVideoMsg, msgtypeidAudioMsg:
self.msgdata = msgdata
case msgtypeidSetChunkSize:
self.readMaxChunkSize = int(pio.GetU32BE(msgdata))
return
} }
self.gotmsg = true self.gotmsg = true