improve sdp

This commit is contained in:
nareix 2016-06-11 19:46:43 +08:00
parent 0bfb3c6cf0
commit 2f1caf9151
3 changed files with 42 additions and 29 deletions

View File

@ -61,7 +61,7 @@ func Connect(uri string) (self *Client, err error) {
return return
} }
if strings.IndexByte(URL.Host, ':') == -1 { if _, _, err := net.SplitHostPort(URL.Host); err != nil {
URL.Host = URL.Host + ":554" URL.Host = URL.Host + ":554"
} }
@ -342,18 +342,24 @@ func (self *Client) Describe() (streams []av.CodecData, err error) {
} }
self.streams = []*Stream{} self.streams = []*Stream{}
for _, info := range sdp.Decode(body) { sess, medias := sdp.Parse(body)
stream := &Stream{Sdp: info}
if sess.Uri != "" {
self.requestUri = sess.Uri
}
for _, media := range medias {
stream := &Stream{Sdp: media}
if false { if false {
fmt.Println("sdp:", info.TimeScale) fmt.Println("sdp:", media.TimeScale)
} }
if info.PayloadType >= 96 && info.PayloadType <= 127 { if media.PayloadType >= 96 && media.PayloadType <= 127 {
switch info.Type { switch media.Type {
case av.H264: case av.H264:
var sps, pps []byte var sps, pps []byte
for _, nalu := range info.SpropParameterSets { for _, nalu := range media.SpropParameterSets {
if len(nalu) > 0 { if len(nalu) > 0 {
switch nalu[0]&0x1f { switch nalu[0]&0x1f {
case 7: case 7:
@ -374,22 +380,22 @@ func (self *Client) Describe() (streams []av.CodecData, err error) {
} }
case av.AAC: case av.AAC:
if len(info.Config) == 0 { if len(media.Config) == 0 {
err = fmt.Errorf("rtsp: aac sdp config missing") err = fmt.Errorf("rtsp: aac sdp config missing")
return 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) err = fmt.Errorf("rtsp: aac sdp config invalid: %s", err)
return return
} }
} }
} else { } else {
switch info.PayloadType { switch media.PayloadType {
case 0: case 0:
stream.CodecData = codec.NewPCMMulawCodecData() stream.CodecData = codec.NewPCMMulawCodecData()
default: default:
err = fmt.Errorf("rtsp: PayloadType=%d unsupported", info.PayloadType) err = fmt.Errorf("rtsp: PayloadType=%d unsupported", media.PayloadType)
return return
} }
} }

View File

@ -9,7 +9,11 @@ import (
"github.com/nareix/av" "github.com/nareix/av"
) )
type Info struct { type Session struct {
Uri string
}
type Media struct {
AVType string AVType string
Type int Type int
TimeScale int TimeScale int
@ -22,8 +26,8 @@ type Info struct {
IndexLength int IndexLength int
} }
func Decode(content string) (infos []Info) { func Parse(content string) (sess Session, medias []Media) {
var info *Info var media *Media
for _, line := range strings.Split(content, "\n") { for _, line := range strings.Split(content, "\n") {
line = strings.TrimSpace(line) line = strings.TrimSpace(line)
@ -36,17 +40,20 @@ func Decode(content string) (infos []Info) {
if len(fields) > 0 { if len(fields) > 0 {
switch fields[0] { switch fields[0] {
case "audio", "video": case "audio", "video":
infos = append(infos, Info{AVType: fields[0]}) medias = append(medias, Media{AVType: fields[0]})
info = &infos[len(infos)-1] media = &medias[len(medias)-1]
mfields := strings.Split(fields[1], " ") mfields := strings.Split(fields[1], " ")
if len(mfields) >= 3 { if len(mfields) >= 3 {
info.PayloadType, _ = strconv.Atoi(mfields[2]) media.PayloadType, _ = strconv.Atoi(mfields[2])
} }
} }
} }
case "u":
sess.Uri = typeval[1]
case "a": case "a":
if info != nil { if media != nil {
for _, field := range fields { for _, field := range fields {
keyval := strings.SplitN(field, ":", 2) keyval := strings.SplitN(field, ":", 2)
if len(keyval) >= 2 { if len(keyval) >= 2 {
@ -54,9 +61,9 @@ func Decode(content string) (infos []Info) {
val := keyval[1] val := keyval[1]
switch key { switch key {
case "control": case "control":
info.Control = val media.Control = val
case "rtpmap": case "rtpmap":
info.Rtpmap, _ = strconv.Atoi(val) media.Rtpmap, _ = strconv.Atoi(val)
} }
} }
keyval = strings.Split(field, "/") keyval = strings.Split(field, "/")
@ -64,15 +71,15 @@ func Decode(content string) (infos []Info) {
key := keyval[0] key := keyval[0]
switch key { switch key {
case "MPEG4-GENERIC": case "MPEG4-GENERIC":
info.Type = av.AAC media.Type = av.AAC
case "H264": case "H264":
info.Type = av.H264 media.Type = av.H264
} }
if i, err := strconv.Atoi(keyval[1]); err == nil { if i, err := strconv.Atoi(keyval[1]); err == nil {
info.TimeScale = i media.TimeScale = i
} }
if false { if false {
fmt.Println("sdp:", keyval[1], info.TimeScale) fmt.Println("sdp:", keyval[1], media.TimeScale)
} }
} }
keyval = strings.Split(field, ";") keyval = strings.Split(field, ";")
@ -84,16 +91,16 @@ func Decode(content string) (infos []Info) {
val := keyval[1] val := keyval[1]
switch key { switch key {
case "config": case "config":
info.Config, _ = hex.DecodeString(val) media.Config, _ = hex.DecodeString(val)
case "sizelength": case "sizelength":
info.SizeLength, _ = strconv.Atoi(val) media.SizeLength, _ = strconv.Atoi(val)
case "indexlength": case "indexlength":
info.IndexLength, _ = strconv.Atoi(val) media.IndexLength, _ = strconv.Atoi(val)
case "sprop-parameter-sets": case "sprop-parameter-sets":
fields := strings.Split(val, ",") fields := strings.Split(val, ",")
for _, field := range fields { for _, field := range fields {
val, _ := base64.StdEncoding.DecodeString(field) val, _ := base64.StdEncoding.DecodeString(field)
info.SpropParameterSets = append(info.SpropParameterSets, val) media.SpropParameterSets = append(media.SpropParameterSets, val)
} }
} }
} }

View File

@ -7,7 +7,7 @@ import (
type Stream struct { type Stream struct {
av.CodecData av.CodecData
Sdp sdp.Info Sdp sdp.Media
// h264 // h264
fuBuffer []byte fuBuffer []byte