Files
gortsplib/track.go
2022-02-12 17:03:24 +01:00

104 lines
2.5 KiB
Go

package gortsplib
import (
"fmt"
"strconv"
"strings"
psdp "github.com/pion/sdp/v3"
"github.com/aler9/gortsplib/pkg/base"
)
// Track is a RTSP track.
type Track interface {
// ClockRate returns the track clock rate.
ClockRate() int
// GetControl returns the track control.
GetControl() string
// SetControl sets the track control.
SetControl(string)
// MediaDescription returns the media description in SDP format.
MediaDescription() *psdp.MediaDescription
clone() Track
url(*base.URL) (*base.URL, error)
}
func newTrackFromMediaDescription(md *psdp.MediaDescription) (Track, error) {
if rtpmap, ok := md.Attribute("rtpmap"); ok {
rtpmap = strings.TrimSpace(rtpmap)
if rtpmapParts := strings.Split(rtpmap, " "); len(rtpmapParts) == 2 {
tmp, err := strconv.ParseInt(rtpmapParts[0], 10, 64)
if err == nil {
payloadType := uint8(tmp)
switch {
case md.MediaName.Media == "video":
if rtpmapParts[1] == "H264/90000" {
return newTrackH264FromMediaDescription(payloadType, md)
}
case md.MediaName.Media == "audio":
switch {
case strings.HasPrefix(strings.ToLower(rtpmapParts[1]), "mpeg4-generic/"):
return newTrackAACFromMediaDescription(payloadType, md)
case strings.HasPrefix(rtpmapParts[1], "opus/"):
return newTrackOpusFromMediaDescription(payloadType, rtpmapParts[1], md)
}
}
}
}
}
return newTrackGenericFromMediaDescription(md)
}
func trackFindControl(md *psdp.MediaDescription) string {
for _, attr := range md.Attributes {
if attr.Key == "control" {
return attr.Value
}
}
return ""
}
func trackURL(t Track, contentBase *base.URL) (*base.URL, error) {
if contentBase == nil {
return nil, fmt.Errorf("Content-Base header not provided")
}
control := t.GetControl()
// no control attribute, use base URL
if control == "" {
return contentBase, nil
}
// control attribute contains an absolute path
if strings.HasPrefix(control, "rtsp://") {
ur, err := base.ParseURL(control)
if err != nil {
return nil, err
}
// copy host and credentials
ur.Host = contentBase.Host
ur.User = contentBase.User
return ur, nil
}
// control attribute contains a relative control attribute
// insert the control attribute at the end of the URL
// if there's a query, insert it after the query
// otherwise insert it after the path
strURL := contentBase.String()
if control[0] != '?' && !strings.HasSuffix(strURL, "/") {
strURL += "/"
}
ur, _ := base.ParseURL(strURL + control)
return ur, nil
}