diff --git a/client.go b/client.go index dc60ac9..f4d81d8 100644 --- a/client.go +++ b/client.go @@ -61,7 +61,7 @@ func Connect(uri string) (self *Client, err error) { return } - if strings.IndexByte(URL.Host, ':') == -1 { + if _, _, err := net.SplitHostPort(URL.Host); err != nil { URL.Host = URL.Host + ":554" } @@ -342,18 +342,24 @@ func (self *Client) Describe() (streams []av.CodecData, err error) { } self.streams = []*Stream{} - for _, info := range sdp.Decode(body) { - stream := &Stream{Sdp: info} + sess, medias := sdp.Parse(body) + + if sess.Uri != "" { + self.requestUri = sess.Uri + } + + for _, media := range medias { + stream := &Stream{Sdp: media} if false { - fmt.Println("sdp:", info.TimeScale) + fmt.Println("sdp:", media.TimeScale) } - if info.PayloadType >= 96 && info.PayloadType <= 127 { - switch info.Type { + if media.PayloadType >= 96 && media.PayloadType <= 127 { + switch media.Type { case av.H264: var sps, pps []byte - for _, nalu := range info.SpropParameterSets { + for _, nalu := range media.SpropParameterSets { if len(nalu) > 0 { switch nalu[0]&0x1f { case 7: @@ -374,22 +380,22 @@ func (self *Client) Describe() (streams []av.CodecData, err error) { } case av.AAC: - if len(info.Config) == 0 { + if len(media.Config) == 0 { err = fmt.Errorf("rtsp: aac sdp config missing") return } - if stream.CodecData, err = aacparser.NewCodecDataFromMPEG4AudioConfigBytes(info.Config); err != nil { + if stream.CodecData, err = aacparser.NewCodecDataFromMPEG4AudioConfigBytes(media.Config); err != nil { err = fmt.Errorf("rtsp: aac sdp config invalid: %s", err) return } } } else { - switch info.PayloadType { + switch media.PayloadType { case 0: stream.CodecData = codec.NewPCMMulawCodecData() default: - err = fmt.Errorf("rtsp: PayloadType=%d unsupported", info.PayloadType) + err = fmt.Errorf("rtsp: PayloadType=%d unsupported", media.PayloadType) return } } diff --git a/sdp/parser.go b/sdp/parser.go index 6b83b46..f171d80 100644 --- a/sdp/parser.go +++ b/sdp/parser.go @@ -9,7 +9,11 @@ import ( "github.com/nareix/av" ) -type Info struct { +type Session struct { + Uri string +} + +type Media struct { AVType string Type int TimeScale int @@ -22,8 +26,8 @@ type Info struct { IndexLength int } -func Decode(content string) (infos []Info) { - var info *Info +func Parse(content string) (sess Session, medias []Media) { + var media *Media for _, line := range strings.Split(content, "\n") { line = strings.TrimSpace(line) @@ -36,17 +40,20 @@ func Decode(content string) (infos []Info) { if len(fields) > 0 { switch fields[0] { case "audio", "video": - infos = append(infos, Info{AVType: fields[0]}) - info = &infos[len(infos)-1] + medias = append(medias, Media{AVType: fields[0]}) + media = &medias[len(medias)-1] mfields := strings.Split(fields[1], " ") if len(mfields) >= 3 { - info.PayloadType, _ = strconv.Atoi(mfields[2]) + media.PayloadType, _ = strconv.Atoi(mfields[2]) } } } + case "u": + sess.Uri = typeval[1] + case "a": - if info != nil { + if media != nil { for _, field := range fields { keyval := strings.SplitN(field, ":", 2) if len(keyval) >= 2 { @@ -54,9 +61,9 @@ func Decode(content string) (infos []Info) { val := keyval[1] switch key { case "control": - info.Control = val + media.Control = val case "rtpmap": - info.Rtpmap, _ = strconv.Atoi(val) + media.Rtpmap, _ = strconv.Atoi(val) } } keyval = strings.Split(field, "/") @@ -64,15 +71,15 @@ func Decode(content string) (infos []Info) { key := keyval[0] switch key { case "MPEG4-GENERIC": - info.Type = av.AAC + media.Type = av.AAC case "H264": - info.Type = av.H264 + media.Type = av.H264 } if i, err := strconv.Atoi(keyval[1]); err == nil { - info.TimeScale = i + media.TimeScale = i } if false { - fmt.Println("sdp:", keyval[1], info.TimeScale) + fmt.Println("sdp:", keyval[1], media.TimeScale) } } keyval = strings.Split(field, ";") @@ -84,16 +91,16 @@ func Decode(content string) (infos []Info) { val := keyval[1] switch key { case "config": - info.Config, _ = hex.DecodeString(val) + media.Config, _ = hex.DecodeString(val) case "sizelength": - info.SizeLength, _ = strconv.Atoi(val) + media.SizeLength, _ = strconv.Atoi(val) case "indexlength": - info.IndexLength, _ = strconv.Atoi(val) + media.IndexLength, _ = strconv.Atoi(val) case "sprop-parameter-sets": fields := strings.Split(val, ",") for _, field := range fields { val, _ := base64.StdEncoding.DecodeString(field) - info.SpropParameterSets = append(info.SpropParameterSets, val) + media.SpropParameterSets = append(media.SpropParameterSets, val) } } } diff --git a/stream.go b/stream.go index 0654958..c983e78 100644 --- a/stream.go +++ b/stream.go @@ -7,7 +7,7 @@ import ( type Stream struct { av.CodecData - Sdp sdp.Info + Sdp sdp.Media // h264 fuBuffer []byte