From 900f4958ca77a8840460a1029e1a6c12ac1c7b3a Mon Sep 17 00:00:00 2001 From: Alessandro Ros Date: Sat, 26 Apr 2025 16:13:37 +0200 Subject: [PATCH] fix SDP compatibility with some Uniview cameras (#618) (#765) --- pkg/sdp/sdp.go | 8 ++++ pkg/sdp/sdp_test.go | 97 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/pkg/sdp/sdp.go b/pkg/sdp/sdp.go index 2a645a09..df93531c 100644 --- a/pkg/sdp/sdp.go +++ b/pkg/sdp/sdp.go @@ -89,6 +89,10 @@ func stringsReverseIndexByte(s string, b byte) int { func (s *SessionDescription) unmarshalOrigin(value string) error { value = strings.Replace(value, " IN IPV4 ", " IN IP4 ", 1) + if strings.HasSuffix(value, " IN") { + value += " IP4" + } + if strings.HasSuffix(value, "IN IP4") { value += " " } @@ -187,6 +191,10 @@ func (s *SessionDescription) unmarshalPhone(value string) error { } func unmarshalConnectionInformation(value string) (*psdp.ConnectionInformation, error) { + if value == "IN" { + return nil, nil + } + value = strings.Replace(value, "IN IPV4 ", "IN IP4 ", 1) if strings.HasPrefix(value, "IN c=IN") { diff --git a/pkg/sdp/sdp_test.go b/pkg/sdp/sdp_test.go index 1396bb74..4e72aa46 100644 --- a/pkg/sdp/sdp_test.go +++ b/pkg/sdp/sdp_test.go @@ -3101,6 +3101,103 @@ var cases = []struct { }, }, }, + + { + "issue gortsplib/618", + []byte("v=0\r\n" + + "o=- 1001 1 IN\r\n" + + "s=VCP IPC Realtime stream\r\n" + + "m=video 0 RTP/AVP 105\r\n" + + "c=IN\r\n" + + "a=control:rtsp://192.168.4.106:8554/media/video1\r\n" + + "a=rtpmap:105 H264/90000\r\n" + + "a=fmtp:105 profile-level-id=64001f; packetization-mode=1; " + + "sprop-parameter-sets=Z2QAH6w7QCgC3TcBAQFAAAD6AAAw1CU=,aOqPLA==\r\n" + + "a=recvonly\r\n" + + "m=application 0 RTP/AVP 107\r\n" + + "c=IN\r\n" + + "a=control:rtsp://192.168.4.106/media/video1/metadata\r\n" + + "a=rtpmap:107 vnd.onvif.metadata/90000\r\n" + + "a=fmtp:107 DecoderTag=h3c-v3 RTCP=0\r\n" + + "a=recvonly\r\n"), + []byte("v=0\r\n" + + "o=- 1001 1 IN IP4 \r\n" + + "s=VCP IPC Realtime stream\r\n" + + "m=video 0 RTP/AVP 105\r\n" + + "a=control:rtsp://192.168.4.106:8554/media/video1\r\n" + + "a=rtpmap:105 H264/90000\r\n" + + "a=fmtp:105 profile-level-id=64001f; packetization-mode=1; " + + "sprop-parameter-sets=Z2QAH6w7QCgC3TcBAQFAAAD6AAAw1CU=,aOqPLA==\r\n" + + "a=recvonly\r\n" + + "m=application 0 RTP/AVP 107\r\n" + + "a=control:rtsp://192.168.4.106/media/video1/metadata\r\n" + + "a=rtpmap:107 vnd.onvif.metadata/90000\r\n" + + "a=fmtp:107 DecoderTag=h3c-v3 RTCP=0\r\n" + + "a=recvonly\r\n"), + SessionDescription{ + Origin: psdp.Origin{ + Username: "-", + SessionID: 1001, + SessionVersion: 1, + NetworkType: "IN", + AddressType: "IP4", + }, + SessionName: "VCP IPC Realtime stream", + MediaDescriptions: []*psdp.MediaDescription{ + { + MediaName: psdp.MediaName{ + Media: "video", + Protos: []string{"RTP", "AVP"}, + Formats: []string{"105"}, + }, + Attributes: []psdp.Attribute{ + { + Key: "control", + Value: "rtsp://192.168.4.106:8554/media/video1", + }, + { + Key: "rtpmap", + Value: "105 H264/90000", + }, + { + Key: "fmtp", + Value: "105 profile-level-id=64001f; packetization-mode=1; " + + "sprop-parameter-sets=Z2QAH6w7QCgC3TcBAQFAAAD6AAAw1CU=,aOqPLA==", + }, + { + Key: "recvonly", + Value: "", + }, + }, + }, + { + MediaName: psdp.MediaName{ + Media: "application", + Protos: []string{"RTP", "AVP"}, + Formats: []string{"107"}, + }, + Attributes: []psdp.Attribute{ + { + Key: "control", + Value: "rtsp://192.168.4.106/media/video1/metadata", + }, + { + Key: "rtpmap", + Value: "107 vnd.onvif.metadata/90000", + }, + { + Key: "fmtp", + Value: "107 DecoderTag=h3c-v3 RTCP=0", + }, + { + Key: "recvonly", + Value: "", + }, + }, + }, + }, + }, + }, } func TestUnmarshal(t *testing.T) {