diff --git a/pkg/sdp/sdp.go b/pkg/sdp/sdp.go index 76215c50..fa44b382 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 IP4") { + value += " " + } + i := strings.Index(value, " IN IP4 ") if i < 0 { i = strings.Index(value, " IN IP6 ") diff --git a/pkg/sdp/sdp_test.go b/pkg/sdp/sdp_test.go index 41c6b119..77bd97d5 100644 --- a/pkg/sdp/sdp_test.go +++ b/pkg/sdp/sdp_test.go @@ -2657,6 +2657,144 @@ var cases = []struct { }}, }, }, + { + "issue mediamtx/2762", + []byte("v=0\r\n" + + "o=Channel1 3910280086 3910366486 IN IP4\r\n" + + "s=Channel1\r\n" + + "c=IN IP4 0.0.0.0\r\n" + + "t=3910280086 3910366486\r\n" + + "a=range:npt=0-\r\n" + + "a=control:*\r\n" + + "m=video 0 RTP/AVP 96\r\n" + + "a=control:0\r\n" + + "a=rtpmap:96 H264/90000\r\n" + + "a=recvonly\r\n" + + "a=fmtp:96 packetization-mode=1;profile-level-id=4D4016;" + + "sprop-parameter-sets=Z01AFo2NQFAX/L/4BDgEQ3AQEBQAAA+gAACcQ6GB9ACMq7y40MD6AEZV3lwo,aO44gA==\r\n" + + "m=audio 0 RTP/AVP 0\r\n" + + "a=control:1\r\n" + + "a=recvonly\r\n" + + "a=rtpmap:0 PCMU/8000\r\n" + + "m=application 0 RTP/AVP 107\r\n" + + "a=control:2\r\n" + + "a=recvonly\r\n" + + "a=rtpmap:107 METADATA/90000\r\n"), + []byte("v=0\r\n" + + "o=Channel1 3910280086 3910366486 IN IP4 \r\n" + + "s=Channel1\r\n" + + "c=IN IP4 0.0.0.0\r\n" + + "t=3910280086 3910366486\r\n" + + "a=range:npt=0-\r\n" + + "a=control:*\r\n" + + "m=video 0 RTP/AVP 96\r\n" + + "a=control:0\r\n" + + "a=rtpmap:96 H264/90000\r\n" + + "a=recvonly\r\n" + + "a=fmtp:96 packetization-mode=1;profile-level-id=4D4016;" + + "sprop-parameter-sets=Z01AFo2NQFAX/L/4BDgEQ3AQEBQAAA+gAACcQ6GB9ACMq7y40MD6AEZV3lwo,aO44gA==\r\n" + + "m=audio 0 RTP/AVP 0\r\n" + + "a=control:1\r\n" + + "a=recvonly\r\n" + + "a=rtpmap:0 PCMU/8000\r\n" + + "m=application 0 RTP/AVP 107\r\n" + + "a=control:2\r\na=recvonly\r\na=rtpmap:107 METADATA/90000\r\n"), + SessionDescription{ + Origin: psdp.Origin{ + Username: "Channel1", + SessionID: 3910280086, + SessionVersion: 3910366486, + NetworkType: "IN", + AddressType: "IP4", + }, + SessionName: "Channel1", + ConnectionInformation: &psdp.ConnectionInformation{ + NetworkType: "IN", + AddressType: "IP4", + Address: &psdp.Address{ + Address: "0.0.0.0", + }, + }, + TimeDescriptions: []psdp.TimeDescription{{Timing: psdp.Timing{StartTime: 3910280086, StopTime: 3910366486}}}, + Attributes: []psdp.Attribute{ + { + Key: "range", + Value: "npt=0-", + }, + { + Key: "control", + Value: "*", + }, + }, + MediaDescriptions: []*psdp.MediaDescription{ + { + MediaName: psdp.MediaName{ + Media: "video", + Protos: []string{"RTP", "AVP"}, + Formats: []string{"96"}, + }, + Attributes: []psdp.Attribute{ + { + Key: "control", + Value: "0", + }, + { + Key: "rtpmap", + Value: "96 H264/90000", + }, + { + Key: "recvonly", + }, + { + Key: "fmtp", + Value: "96 packetization-mode=1;profile-level-id=4D4016;" + + "sprop-parameter-sets=Z01AFo2NQFAX/L/4BDgEQ3AQEBQAAA+gAACcQ6GB9ACMq7y40MD6AEZV3lwo,aO44gA==", + }, + }, + }, + { + MediaName: psdp.MediaName{ + Media: "audio", + Protos: []string{"RTP", "AVP"}, + Formats: []string{"0"}, + }, + Attributes: []psdp.Attribute{ + { + Key: "control", + Value: "1", + }, + { + Key: "recvonly", + }, + { + Key: "rtpmap", + Value: "0 PCMU/8000", + }, + }, + }, + { + MediaName: psdp.MediaName{ + Media: "application", + Protos: []string{"RTP", "AVP"}, + Formats: []string{"107"}, + }, + Attributes: []psdp.Attribute{ + { + Key: "control", + Value: "2", + }, + { + Key: "recvonly", + }, + { + Key: "rtpmap", + Value: "107 METADATA/90000", + }, + }, + }, + }, + }, + }, } func TestUnmarshal(t *testing.T) {