diff --git a/pkg/auth/validator.go b/pkg/auth/validator.go index 6e0ac38a..47511392 100644 --- a/pkg/auth/validator.go +++ b/pkg/auth/validator.go @@ -27,6 +27,7 @@ func sha256Base64(in string) string { } // Validator allows to validate credentials generated by a Sender. +// // Deprecated: Validator{} has been replaced by Validate() type Validator struct { user string @@ -40,6 +41,7 @@ type Validator struct { // NewValidator allocates a Validator. // If methods is nil, the Basic and Digest methods are used. +// // Deprecated: Validator{} has been replaced by Validate() func NewValidator(user string, pass string, methods []headers.AuthMethod) *Validator { if methods == nil { @@ -80,6 +82,7 @@ func NewValidator(user string, pass string, methods []headers.AuthMethod) *Valid // Header generates the WWW-Authenticate header needed by a client to // authenticate. +// // Deprecated: Validator{} has been replaced by Validate() func (va *Validator) Header() base.HeaderValue { var ret base.HeaderValue @@ -103,6 +106,7 @@ func (va *Validator) Header() base.HeaderValue { } // ValidateRequest validates a request sent by a client. +// // Deprecated: Validator{} has been replaced by Validate() func (va *Validator) ValidateRequest(req *base.Request, baseURL *url.URL) error { var auth headers.Authorization diff --git a/pkg/media/media.go b/pkg/media/media.go index 15197d12..20a0a73d 100644 --- a/pkg/media/media.go +++ b/pkg/media/media.go @@ -4,6 +4,7 @@ package media import ( "fmt" "reflect" + "regexp" "sort" "strconv" "strings" @@ -14,6 +15,8 @@ import ( "github.com/bluenviron/gortsplib/v3/pkg/url" ) +var smartRegexp = regexp.MustCompile("^([0-9]+) (.*?)/90000") + func getControlAttribute(attributes []psdp.Attribute) string { for _, attr := range attributes { if attr.Key == "control" { @@ -135,9 +138,9 @@ func (m *Media) unmarshal(md *psdp.MediaDescription) error { if payloadType == "smart/1/90000" { for _, attr := range md.Attributes { if attr.Key == "rtpmap" { - i := strings.Index(attr.Value, " TP-LINK/90000") - if i >= 0 { - payloadType = attr.Value[:i] + sm := smartRegexp.FindStringSubmatch(attr.Value) + if sm != nil { + payloadType = sm[1] break } } diff --git a/pkg/media/medias_test.go b/pkg/media/medias_test.go index 075b991b..1bebcc66 100644 --- a/pkg/media/medias_test.go +++ b/pkg/media/medias_test.go @@ -522,19 +522,19 @@ var casesMedias = []struct { "o=- 4158123474391860926 2 IN IP4 127.0.0.1\r\n" + "s=-\r\n" + "t=0 0\r\n" + - "m=application 42504 RTP/AVP smart/1/90000\r\n" + + "m=application/TP-LINK 0 RTP/AVP smart/1/90000\r\n" + "a=rtpmap:95 TP-LINK/90000\r\n", "v=0\r\n" + "o=- 0 0 IN IP4 127.0.0.1\r\n" + "s=Stream\r\n" + "c=IN IP4 0.0.0.0\r\n" + "t=0 0\r\n" + - "m=application 0 RTP/AVP 95\r\n" + + "m=application/TP-LINK 0 RTP/AVP 95\r\n" + "a=control\r\n" + "a=rtpmap:95 TP-LINK/90000\r\n", Medias{ { - Type: "application", + Type: "application/TP-LINK", Formats: []formats.Format{&formats.Generic{ PayloadTyp: 95, RTPMa: "TP-LINK/90000", @@ -543,6 +543,34 @@ var casesMedias = []struct { }, }, }, + { + "mercury", + "v=0\n" + + "o=- 14665860 31787219 1 IN IP4 192.168.0.60\n" + + "s=Session streamed by \"MERCURY RTSP Server\"\n" + + "t=0 0\n" + + "a=smart_encoder:virtualIFrame=1\n" + + "m=application/MERCURY 0 RTP/AVP smart/1/90000\n" + + "a=rtpmap:95 MERCURY/90000\n", + "v=0\r\n" + + "o=- 0 0 IN IP4 127.0.0.1\r\n" + + "s=Stream\r\n" + + "c=IN IP4 0.0.0.0\r\n" + + "t=0 0\r\n" + + "m=application/MERCURY 0 RTP/AVP 95\r\n" + + "a=control\r\n" + + "a=rtpmap:95 MERCURY/90000\r\n", + Medias{ + { + Type: "application/MERCURY", + Formats: []formats.Format{&formats.Generic{ + PayloadTyp: 95, + RTPMa: "MERCURY/90000", + ClockRat: 90000, + }}, + }, + }, + }, { "h264 with space at end", "v=0\r\n" + diff --git a/pkg/sdp/sdp.go b/pkg/sdp/sdp.go index 3b1e7c67..236e0898 100644 --- a/pkg/sdp/sdp.go +++ b/pkg/sdp/sdp.go @@ -406,14 +406,13 @@ func (s *SessionDescription) unmarshalMediaDescription(value string) error { newMediaDesc := &psdp.MediaDescription{} - if fields[0] == "application/TP-LINK" { - fields[0] = "application" - } - // // Set according to currently registered with IANA // https://tools.ietf.org/html/rfc4566#section-5.14 - if i := indexOf(fields[0], []string{"audio", "video", "text", "application", "message"}); i == -1 { + if fields[0] != "video" && + fields[0] != "audio" && + fields[0] != "application" && + !strings.HasPrefix(fields[0], "application/") { return fmt.Errorf("%w `%v`", errSDPInvalidValue, fields[0]) } newMediaDesc.MediaName.Media = fields[0] diff --git a/pkg/sdp/sdp_test.go b/pkg/sdp/sdp_test.go index 6c629b79..e5e6983f 100644 --- a/pkg/sdp/sdp_test.go +++ b/pkg/sdp/sdp_test.go @@ -1876,7 +1876,7 @@ var cases = []struct { "m=audio 0 RTP/AVP 8\r\n" + "a=rtpmap:8 PCMA/8000\r\n" + "a=control:track2\r\n" + - "m=application 0 RTP/AVP smart/1/90000\r\n" + + "m=application/TP-LINK 0 RTP/AVP smart/1/90000\r\n" + "a=rtpmap:95 TP-LINK/90000\r\n" + "a=control:track3\r\n"), SessionDescription{ @@ -1945,7 +1945,7 @@ var cases = []struct { }, { MediaName: psdp.MediaName{ - Media: "application", + Media: "application/TP-LINK", Protos: []string{"RTP", "AVP"}, Formats: []string{"smart/1/90000"}, }, @@ -2215,6 +2215,138 @@ var cases = []struct { }, }, }, + { + "mercury", + []byte("v=0\n" + + "o=- 14665860 31787219 1 IN IP4 192.168.0.60\n" + + "s=Session streamed by \"MERCURY RTSP Server\"\n" + + "t=0 0\n" + + "a=smart_encoder:virtualIFrame=1\n" + + "m=video 0 RTP/AVP 96\n" + + "c=IN IP4 0.0.0.0\n" + + "b=AS:4096\n" + + "a=range:npt=0-\n" + + "a=control:track1\n" + + "a=rtpmap:96 H264/90000\n" + + "a=fmtp:96 packetization-mode=1; profile-level-id=4D001F;" + + " sprop-parameter-sets=J00AH+dAKALdgKUFBQXwAAADABAAAAMCi2gD6AXf//wK,KO48gA==\n" + + "m=audio 0 RTP/AVP 8\n" + + "a=rtpmap:8 PCMA/8000\n" + + "a=control:track2\n" + + "m=application/MERCURY 0 RTP/AVP smart/1/90000\n" + + "a=rtpmap:95 MERCURY/90000\n" + + "a=control:track3\n"), + []byte("v=0\r\n" + + "o=- 14665860 31787219 1 IN IP4 192.168.0.60\r\n" + + "s=Session streamed by \"MERCURY RTSP Server\"\r\n" + + "t=0 0\r\n" + + "a=smart_encoder:virtualIFrame=1\r\n" + + "m=video 0 RTP/AVP 96\r\n" + + "c=IN IP4 0.0.0.0\r\n" + + "b=AS:4096\r\n" + + "a=range:npt=0-\r\n" + + "a=control:track1\r\n" + + "a=rtpmap:96 H264/90000\r\n" + + "a=fmtp:96 packetization-mode=1; profile-level-id=4D001F;" + + " sprop-parameter-sets=J00AH+dAKALdgKUFBQXwAAADABAAAAMCi2gD6AXf//wK,KO48gA==\r\n" + + "m=audio 0 RTP/AVP 8\r\n" + + "a=rtpmap:8 PCMA/8000\r\n" + + "a=control:track2\r\n" + + "m=application/MERCURY 0 RTP/AVP smart/1/90000\r\n" + + "a=rtpmap:95 MERCURY/90000\r\n" + + "a=control:track3\r\n"), + SessionDescription{ + Origin: psdp.Origin{ + Username: "- 14665860", + SessionID: 31787219, + SessionVersion: 1, + NetworkType: "IN", + AddressType: "IP4", + UnicastAddress: "192.168.0.60", + }, + SessionName: "Session streamed by \"MERCURY RTSP Server\"", + TimeDescriptions: []psdp.TimeDescription{{}}, + Attributes: []psdp.Attribute{ + { + Key: "smart_encoder", + Value: "virtualIFrame=1", + }, + }, + MediaDescriptions: []*psdp.MediaDescription{ + { + MediaName: psdp.MediaName{ + Media: "video", + Protos: []string{"RTP", "AVP"}, + Formats: []string{"96"}, + }, + ConnectionInformation: &psdp.ConnectionInformation{ + NetworkType: "IN", + AddressType: "IP4", + Address: &psdp.Address{ + Address: "0.0.0.0", + }, + }, + Bandwidth: []psdp.Bandwidth{{ + Type: "AS", + Bandwidth: 4096, + }}, + Attributes: []psdp.Attribute{ + { + Key: "range", + Value: "npt=0-", + }, + { + Key: "control", + Value: "track1", + }, + { + Key: "rtpmap", + Value: "96 H264/90000", + }, + { + Key: "fmtp", + Value: "96 packetization-mode=1; profile-level-id=4D001F;" + + " sprop-parameter-sets=J00AH+dAKALdgKUFBQXwAAADABAAAAMCi2gD6AXf//wK,KO48gA==", + }, + }, + }, + { + MediaName: psdp.MediaName{ + Media: "audio", + Protos: []string{"RTP", "AVP"}, + Formats: []string{"8"}, + }, + Attributes: []psdp.Attribute{ + { + Key: "rtpmap", + Value: "8 PCMA/8000", + }, + { + Key: "control", + Value: "track2", + }, + }, + }, + { + MediaName: psdp.MediaName{ + Media: "application/MERCURY", + Protos: []string{"RTP", "AVP"}, + Formats: []string{"smart/1/90000"}, + }, + Attributes: []psdp.Attribute{ + { + Key: "rtpmap", + Value: "95 MERCURY/90000", + }, + { + Key: "control", + Value: "track3", + }, + }, + }, + }, + }, + }, } func TestUnmarshal(t *testing.T) {