mirror of
				https://github.com/aler9/gortsplib
				synced 2025-11-01 02:52:36 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			907 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			907 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package description
 | |
| 
 | |
| import (
 | |
| 	"testing"
 | |
| 
 | |
| 	"github.com/stretchr/testify/require"
 | |
| 
 | |
| 	"github.com/bluenviron/gortsplib/v4/pkg/format"
 | |
| 	"github.com/bluenviron/gortsplib/v4/pkg/sdp"
 | |
| )
 | |
| 
 | |
| var casesSession = []struct {
 | |
| 	name string
 | |
| 	in   string
 | |
| 	out  string
 | |
| 	desc Session
 | |
| }{
 | |
| 	{
 | |
| 		"one format for each media, absolute",
 | |
| 		"v=0\r\n" +
 | |
| 			"o=- 0 0 IN IP4 10.0.0.131\r\n" +
 | |
| 			"s=Media Presentation\r\n" +
 | |
| 			"i=samsung\r\n" +
 | |
| 			"c=IN IP4 0.0.0.0\r\n" +
 | |
| 			"b=AS:2632\r\n" +
 | |
| 			"t=0 0\r\n" +
 | |
| 			"a=control:rtsp://10.0.100.50/profile5/media.smp\r\n" +
 | |
| 			"a=range:npt=now-\r\n" +
 | |
| 			"m=video 42504 RTP/AVP 97\r\n" +
 | |
| 			"b=AS:2560\r\n" +
 | |
| 			"a=rtpmap:97 H264/90000\r\n" +
 | |
| 			"a=control:rtsp://10.0.100.50/profile5/media.smp/trackID=v\r\n" +
 | |
| 			"a=cliprect:0,0,1080,1920\r\n" +
 | |
| 			"a=framesize:97 1920-1080\r\n" +
 | |
| 			"a=framerate:30.0\r\n" +
 | |
| 			"a=fmtp:97 packetization-mode=1;profile-level-id=640028;sprop-parameter-sets=Z2QAKKy0A8ARPyo=,aO4Bniw=\r\n" +
 | |
| 			"m=audio 42506 RTP/AVP 0\r\n" +
 | |
| 			"b=AS:64\r\n" +
 | |
| 			"a=rtpmap:0 PCMU/8000\r\n" +
 | |
| 			"a=control:rtsp://10.0.100.50/profile5/media.smp/trackID=a\r\n" +
 | |
| 			"a=recvonly\r\n" +
 | |
| 			"m=application 42508 RTP/AVP 107\r\n" +
 | |
| 			"b=AS:8\r\n",
 | |
| 		"v=0\r\n" +
 | |
| 			"o=- 0 0 IN IP4 127.0.0.1\r\n" +
 | |
| 			"s=Media Presentation\r\n" +
 | |
| 			"c=IN IP4 0.0.0.0\r\n" +
 | |
| 			"t=0 0\r\n" +
 | |
| 			"m=video 0 RTP/AVP 97\r\n" +
 | |
| 			"a=control:rtsp://10.0.100.50/profile5/media.smp/trackID=v\r\n" +
 | |
| 			"a=rtpmap:97 H264/90000\r\n" +
 | |
| 			"a=fmtp:97 packetization-mode=1; profile-level-id=640028; sprop-parameter-sets=Z2QAKKy0A8ARPyo=,aO4Bniw=\r\n" +
 | |
| 			"m=audio 0 RTP/AVP 0\r\n" +
 | |
| 			"a=control:rtsp://10.0.100.50/profile5/media.smp/trackID=a\r\n" +
 | |
| 			"a=rtpmap:0 PCMU/8000\r\n" +
 | |
| 			"m=application 0 RTP/AVP 107\r\n" +
 | |
| 			"a=control\r\n",
 | |
| 		Session{
 | |
| 			Title: `Media Presentation`,
 | |
| 			Medias: []*Media{
 | |
| 				{
 | |
| 					Type:    MediaTypeVideo,
 | |
| 					Control: "rtsp://10.0.100.50/profile5/media.smp/trackID=v",
 | |
| 					Formats: []format.Format{&format.H264{
 | |
| 						PayloadTyp:        97,
 | |
| 						PacketizationMode: 1,
 | |
| 						SPS:               []byte{0x67, 0x64, 0x00, 0x28, 0xac, 0xb4, 0x03, 0xc0, 0x11, 0x3f, 0x2a},
 | |
| 						PPS:               []byte{0x68, 0xee, 0x01, 0x9e, 0x2c},
 | |
| 					}},
 | |
| 				},
 | |
| 				{
 | |
| 					Type:    MediaTypeAudio,
 | |
| 					Control: "rtsp://10.0.100.50/profile5/media.smp/trackID=a",
 | |
| 					Formats: []format.Format{&format.G711{
 | |
| 						PayloadTyp:   0,
 | |
| 						MULaw:        true,
 | |
| 						SampleRate:   8000,
 | |
| 						ChannelCount: 1,
 | |
| 					}},
 | |
| 				},
 | |
| 				{
 | |
| 					Type: MediaTypeApplication,
 | |
| 					Formats: []format.Format{&format.Generic{
 | |
| 						PayloadTyp: 107,
 | |
| 					}},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	},
 | |
| 	{
 | |
| 		"one format for each media, relative",
 | |
| 		"v=0\r\n" +
 | |
| 			"o=- 0 0 IN IP4 10.0.0.131\r\n" +
 | |
| 			"s=Media Presentation\r\n" +
 | |
| 			"i=samsung\r\n" +
 | |
| 			"c=IN IP4 0.0.0.0\r\n" +
 | |
| 			"b=AS:2632\r\n" +
 | |
| 			"t=0 0\r\n" +
 | |
| 			"a=range:npt=now-\r\n" +
 | |
| 			"m=video 42504 RTP/AVP 97\r\n" +
 | |
| 			"b=AS:2560\r\n" +
 | |
| 			"a=rtpmap:97 H264/90000\r\n" +
 | |
| 			"a=control:trackID=1\r\n" +
 | |
| 			"a=cliprect:0,0,1080,1920\r\n" +
 | |
| 			"a=framesize:97 1920-1080\r\n" +
 | |
| 			"a=framerate:30.0\r\n" +
 | |
| 			"a=fmtp:97 packetization-mode=1;profile-level-id=640028;sprop-parameter-sets=Z2QAKKy0A8ARPyo=,aO4Bniw=\r\n" +
 | |
| 			"m=audio 42506 RTP/AVP 0\r\n" +
 | |
| 			"b=AS:64\r\n" +
 | |
| 			"a=rtpmap:0 PCMU/8000\r\n" +
 | |
| 			"a=control:trackID=2\r\n" +
 | |
| 			"a=recvonly\r\n" +
 | |
| 			"m=application 42508 RTP/AVP 107\r\n" +
 | |
| 			"b=AS:8\r\n",
 | |
| 		"v=0\r\n" +
 | |
| 			"o=- 0 0 IN IP4 127.0.0.1\r\n" +
 | |
| 			"s=Media Presentation\r\n" +
 | |
| 			"c=IN IP4 0.0.0.0\r\n" +
 | |
| 			"t=0 0\r\n" +
 | |
| 			"m=video 0 RTP/AVP 97\r\n" +
 | |
| 			"a=control:trackID=1\r\n" +
 | |
| 			"a=rtpmap:97 H264/90000\r\n" +
 | |
| 			"a=fmtp:97 packetization-mode=1; profile-level-id=640028; sprop-parameter-sets=Z2QAKKy0A8ARPyo=,aO4Bniw=\r\n" +
 | |
| 			"m=audio 0 RTP/AVP 0\r\n" +
 | |
| 			"a=control:trackID=2\r\n" +
 | |
| 			"a=rtpmap:0 PCMU/8000\r\n" +
 | |
| 			"m=application 0 RTP/AVP 107\r\n" +
 | |
| 			"a=control\r\n",
 | |
| 		Session{
 | |
| 			Title: `Media Presentation`,
 | |
| 			Medias: []*Media{
 | |
| 				{
 | |
| 					Type:    MediaTypeVideo,
 | |
| 					Control: "trackID=1",
 | |
| 					Formats: []format.Format{&format.H264{
 | |
| 						PayloadTyp:        97,
 | |
| 						PacketizationMode: 1,
 | |
| 						SPS:               []byte{0x67, 0x64, 0x00, 0x28, 0xac, 0xb4, 0x03, 0xc0, 0x11, 0x3f, 0x2a},
 | |
| 						PPS:               []byte{0x68, 0xee, 0x01, 0x9e, 0x2c},
 | |
| 					}},
 | |
| 				},
 | |
| 				{
 | |
| 					Type:    MediaTypeAudio,
 | |
| 					Control: "trackID=2",
 | |
| 					Formats: []format.Format{&format.G711{
 | |
| 						PayloadTyp:   0,
 | |
| 						MULaw:        true,
 | |
| 						SampleRate:   8000,
 | |
| 						ChannelCount: 1,
 | |
| 					}},
 | |
| 				},
 | |
| 				{
 | |
| 					Type: MediaTypeApplication,
 | |
| 					Formats: []format.Format{&format.Generic{
 | |
| 						PayloadTyp: 107,
 | |
| 					}},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	},
 | |
| 	{
 | |
| 		"multiple formats for each media",
 | |
| 		"v=0\r\n" +
 | |
| 			"o=- 4158123474391860926 2 IN IP4 127.0.0.1\r\n" +
 | |
| 			"s= \r\n" +
 | |
| 			"t=0 0\r\n" +
 | |
| 			"a=group:BUNDLE audio video\r\n" +
 | |
| 			"a=msid-semantic: WMS mediaSessionLocal\r\n" +
 | |
| 			"m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 102 0 8 106 105 13 110 112 113 126\r\n" +
 | |
| 			"c=IN IP4 0.0.0.0\r\n" +
 | |
| 			"a=rtcp:9 IN IP4 0.0.0.0\r\n" +
 | |
| 			"a=ice-ufrag:0D6Y\r\n" +
 | |
| 			"a=ice-pwd:V3YEqLGAJJhUDUa13C/pKbWe\r\n" +
 | |
| 			"a=ice-options:trickle renomination\r\n" +
 | |
| 			"a=fingerprint:sha-256" +
 | |
| 			" 5E:B5:97:8B:B4:D8:AE:2B:89:F6:82:44:47:69:77:83:05:29:C5:C8:EE:67:50:C3:77:6B:A7:BA:10:E3:08:B8\r\n" +
 | |
| 			"a=setup:actpass\r\n" +
 | |
| 			"a=mid:audio\r\n" +
 | |
| 			"a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n" +
 | |
| 			"a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\n" +
 | |
| 			"a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\n" +
 | |
| 			"a=sendonly\r\n" +
 | |
| 			"a=rtcp-mux\r\n" +
 | |
| 			"a=rtpmap:111 opus/48000/2\r\n" +
 | |
| 			"a=rtcp-fb:111 transport-cc\r\n" +
 | |
| 			"a=fmtp:111 minptime=10;useinbandfec=1\r\n" +
 | |
| 			"a=rtpmap:103 ISAC/16000\r\n" +
 | |
| 			"a=rtpmap:104 ISAC/32000\r\n" +
 | |
| 			"a=rtpmap:9 G722/8000\r\n" +
 | |
| 			"a=rtpmap:102 ILBC/8000\r\n" +
 | |
| 			"a=rtpmap:0 PCMU/8000\r\n" +
 | |
| 			"a=rtpmap:8 PCMA/8000\r\n" +
 | |
| 			"a=rtpmap:106 CN/32000\r\n" +
 | |
| 			"a=rtpmap:105 CN/16000\r\n" +
 | |
| 			"a=rtpmap:13 CN/8000\r\n" +
 | |
| 			"a=rtpmap:110 telephone-event/48000\r\n" +
 | |
| 			"a=rtpmap:112 telephone-event/32000\r\n" +
 | |
| 			"a=rtpmap:113 telephone-event/16000\r\n" +
 | |
| 			"a=rtpmap:126 telephone-event/8000\r\n" +
 | |
| 			"a=ssrc:3754810229 cname:CvU1TYqkVsjj5XOt\r\n" +
 | |
| 			"a=ssrc:3754810229 msid:mediaSessionLocal 101\r\n" +
 | |
| 			"a=ssrc:3754810229 mslabel:mediaSessionLocal\r\n" +
 | |
| 			"a=ssrc:3754810229 label:101\r\n" +
 | |
| 			"m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 127 124 125\r\n" +
 | |
| 			"c=IN IP4 0.0.0.0\r\n" +
 | |
| 			"a=rtcp:9 IN IP4 0.0.0.0\r\n" +
 | |
| 			"a=ice-ufrag:0D6Y\r\n" +
 | |
| 			"a=ice-pwd:V3YEqLGAJJhUDUa13C/pKbWe\r\n" +
 | |
| 			"a=ice-options:trickle renomination\r\n" +
 | |
| 			"a=fingerprint:sha-256" +
 | |
| 			" 5E:B5:97:8B:B4:D8:AE:2B:89:F6:82:44:47:69:77:83:05:29:C5:C8:EE:67:50:C3:77:6B:A7:BA:10:E3:08:B8\r\n" +
 | |
| 			"a=setup:actpass\r\n" +
 | |
| 			"a=mid:video\r\n" +
 | |
| 			"a=extmap:14 urn:ietf:params:rtp-hdrext:toffset\r\n" +
 | |
| 			"a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\n" +
 | |
| 			"a=extmap:13 urn:3gpp:video-orientation\r\n" +
 | |
| 			"a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\n" +
 | |
| 			"a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\r\n" +
 | |
| 			"a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type\r\n" +
 | |
| 			"a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing\r\n" +
 | |
| 			"a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space\r\n" +
 | |
| 			"a=sendonly\r\n" +
 | |
| 			"a=rtcp-mux\r\n" +
 | |
| 			"a=rtcp-rsize\r\n" +
 | |
| 			"a=rtpmap:96 VP8/90000\r\n" +
 | |
| 			"a=rtcp-fb:96 goog-remb\r\n" +
 | |
| 			"a=rtcp-fb:96 transport-cc\r\n" +
 | |
| 			"a=rtcp-fb:96 ccm fir\r\n" +
 | |
| 			"a=rtcp-fb:96 nack\r\n" +
 | |
| 			"a=rtcp-fb:96 nack pli\r\n" +
 | |
| 			"a=rtpmap:97 rtx/90000\r\n" +
 | |
| 			"a=fmtp:97 apt=96\r\n" +
 | |
| 			"a=rtpmap:98 VP9/90000\r\n" +
 | |
| 			"a=rtcp-fb:98 goog-remb\r\n" +
 | |
| 			"a=rtcp-fb:98 transport-cc\r\n" +
 | |
| 			"a=rtcp-fb:98 ccm fir\r\n" +
 | |
| 			"a=rtcp-fb:98 nack\r\n" +
 | |
| 			"a=rtcp-fb:98 nack pli\r\n" +
 | |
| 			"a=rtpmap:99 rtx/90000\r\n" +
 | |
| 			"a=fmtp:99 apt=98\r\n" +
 | |
| 			"a=rtpmap:100 H264/90000\r\n" +
 | |
| 			"a=rtcp-fb:100 goog-remb\r\n" +
 | |
| 			"a=rtcp-fb:100 transport-cc\r\n" +
 | |
| 			"a=rtcp-fb:100 ccm fir\r\n" +
 | |
| 			"a=rtcp-fb:100 nack\r\n" +
 | |
| 			"a=rtcp-fb:100 nack pli\r\n" +
 | |
| 			"a=fmtp:100 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f\r\n" +
 | |
| 			"a=rtpmap:101 rtx/90000\r\n" +
 | |
| 			"a=fmtp:101 apt=100\r\n" +
 | |
| 			"a=rtpmap:127 red/90000\r\n" +
 | |
| 			"a=rtpmap:124 rtx/90000\r\n" +
 | |
| 			"a=fmtp:124 apt=127\r\n" +
 | |
| 			"a=rtpmap:125 ulpfec/90000\r\n" +
 | |
| 			"a=ssrc-group:FID 2712436124 1733091158\r\n" +
 | |
| 			"a=ssrc:2712436124 cname:CvU1TYqkVsjj5XOt\r\n" +
 | |
| 			"a=ssrc:2712436124 msid:mediaSessionLocal 100\r\n" +
 | |
| 			"a=ssrc:2712436124 mslabel:mediaSessionLocal\r\n" +
 | |
| 			"a=ssrc:2712436124 label:100\r\n" +
 | |
| 			"a=ssrc:1733091158 cname:CvU1TYqkVsjj5XOt\r\n" +
 | |
| 			"a=ssrc:1733091158 msid:mediaSessionLocal 100\r\n" +
 | |
| 			"a=ssrc:1733091158 mslabel:mediaSessionLocal\r\n" +
 | |
| 			"a=ssrc:1733091158 label:100\r\n",
 | |
| 		"v=0\r\n" +
 | |
| 			"o=- 0 0 IN IP4 127.0.0.1\r\n" +
 | |
| 			"s= \r\n" +
 | |
| 			"c=IN IP4 0.0.0.0\r\n" +
 | |
| 			"t=0 0\r\n" +
 | |
| 			"m=audio 0 RTP/AVP 111 103 104 9 102 0 8 106 105 13 110 112 113 126\r\n" +
 | |
| 			"a=mid:audio\r\n" +
 | |
| 			"a=sendonly\r\n" +
 | |
| 			"a=control\r\n" +
 | |
| 			"a=rtpmap:111 opus/48000/2\r\n" +
 | |
| 			"a=fmtp:111 sprop-stereo=0\r\n" +
 | |
| 			"a=rtpmap:103 ISAC/16000\r\n" +
 | |
| 			"a=rtpmap:104 ISAC/32000\r\n" +
 | |
| 			"a=rtpmap:9 G722/8000\r\n" +
 | |
| 			"a=rtpmap:102 ILBC/8000\r\n" +
 | |
| 			"a=rtpmap:0 PCMU/8000\r\n" +
 | |
| 			"a=rtpmap:8 PCMA/8000\r\n" +
 | |
| 			"a=rtpmap:106 CN/32000\r\n" +
 | |
| 			"a=rtpmap:105 CN/16000\r\n" +
 | |
| 			"a=rtpmap:13 CN/8000\r\n" +
 | |
| 			"a=rtpmap:110 telephone-event/48000\r\n" +
 | |
| 			"a=rtpmap:112 telephone-event/32000\r\n" +
 | |
| 			"a=rtpmap:113 telephone-event/16000\r\n" +
 | |
| 			"a=rtpmap:126 telephone-event/8000\r\n" +
 | |
| 			"m=video 0 RTP/AVP 96 97 98 99 100 101 127 124 125\r\n" +
 | |
| 			"a=mid:video\r\n" +
 | |
| 			"a=sendonly\r\n" +
 | |
| 			"a=control\r\n" +
 | |
| 			"a=rtpmap:96 VP8/90000\r\n" +
 | |
| 			"a=rtpmap:97 rtx/90000\r\n" +
 | |
| 			"a=fmtp:97 apt=96\r\n" +
 | |
| 			"a=rtpmap:98 VP9/90000\r\n" +
 | |
| 			"a=rtpmap:99 rtx/90000\r\n" +
 | |
| 			"a=fmtp:99 apt=98\r\n" +
 | |
| 			"a=rtpmap:100 H264/90000\r\n" +
 | |
| 			"a=fmtp:100 packetization-mode=1\r\n" +
 | |
| 			"a=rtpmap:101 rtx/90000\r\n" +
 | |
| 			"a=fmtp:101 apt=100\r\n" +
 | |
| 			"a=rtpmap:127 red/90000\r\n" +
 | |
| 			"a=rtpmap:124 rtx/90000\r\n" +
 | |
| 			"a=fmtp:124 apt=127\r\na=rtpmap:125 ulpfec/90000\r\n",
 | |
| 		Session{
 | |
| 			Title: ``,
 | |
| 			Medias: []*Media{
 | |
| 				{
 | |
| 					ID:            "audio",
 | |
| 					Type:          MediaTypeAudio,
 | |
| 					IsBackChannel: true,
 | |
| 					Formats: []format.Format{
 | |
| 						&format.Opus{
 | |
| 							PayloadTyp:   111,
 | |
| 							IsStereo:     false,
 | |
| 							ChannelCount: 1,
 | |
| 						},
 | |
| 						&format.Generic{
 | |
| 							PayloadTyp: 103,
 | |
| 							RTPMa:      "ISAC/16000",
 | |
| 							ClockRat:   16000,
 | |
| 						},
 | |
| 						&format.Generic{
 | |
| 							PayloadTyp: 104,
 | |
| 							RTPMa:      "ISAC/32000",
 | |
| 							ClockRat:   32000,
 | |
| 						},
 | |
| 						&format.G722{},
 | |
| 						&format.Generic{
 | |
| 							PayloadTyp: 102,
 | |
| 							RTPMa:      "ILBC/8000",
 | |
| 							ClockRat:   8000,
 | |
| 						},
 | |
| 						&format.G711{
 | |
| 							PayloadTyp:   0,
 | |
| 							MULaw:        true,
 | |
| 							SampleRate:   8000,
 | |
| 							ChannelCount: 1,
 | |
| 						},
 | |
| 						&format.G711{
 | |
| 							PayloadTyp:   8,
 | |
| 							MULaw:        false,
 | |
| 							SampleRate:   8000,
 | |
| 							ChannelCount: 1,
 | |
| 						},
 | |
| 						&format.Generic{
 | |
| 							PayloadTyp: 106,
 | |
| 							RTPMa:      "CN/32000",
 | |
| 							ClockRat:   32000,
 | |
| 						},
 | |
| 						&format.Generic{
 | |
| 							PayloadTyp: 105,
 | |
| 							RTPMa:      "CN/16000",
 | |
| 							ClockRat:   16000,
 | |
| 						},
 | |
| 						&format.Generic{
 | |
| 							PayloadTyp: 13,
 | |
| 							RTPMa:      "CN/8000",
 | |
| 							ClockRat:   8000,
 | |
| 						},
 | |
| 						&format.Generic{
 | |
| 							PayloadTyp: 110,
 | |
| 							RTPMa:      "telephone-event/48000",
 | |
| 							ClockRat:   48000,
 | |
| 						},
 | |
| 						&format.Generic{
 | |
| 							PayloadTyp: 112,
 | |
| 							RTPMa:      "telephone-event/32000",
 | |
| 							ClockRat:   32000,
 | |
| 						},
 | |
| 						&format.Generic{
 | |
| 							PayloadTyp: 113,
 | |
| 							RTPMa:      "telephone-event/16000",
 | |
| 							ClockRat:   16000,
 | |
| 						},
 | |
| 						&format.Generic{
 | |
| 							PayloadTyp: 126,
 | |
| 							RTPMa:      "telephone-event/8000",
 | |
| 							ClockRat:   8000,
 | |
| 						},
 | |
| 					},
 | |
| 				},
 | |
| 				{
 | |
| 					ID:            "video",
 | |
| 					Type:          MediaTypeVideo,
 | |
| 					IsBackChannel: true,
 | |
| 					Formats: []format.Format{
 | |
| 						&format.VP8{
 | |
| 							PayloadTyp: 96,
 | |
| 						},
 | |
| 						&format.Generic{
 | |
| 							PayloadTyp: 97,
 | |
| 							RTPMa:      "rtx/90000",
 | |
| 							FMT: map[string]string{
 | |
| 								"apt": "96",
 | |
| 							},
 | |
| 							ClockRat: 90000,
 | |
| 						},
 | |
| 						&format.VP9{
 | |
| 							PayloadTyp: 98,
 | |
| 						},
 | |
| 						&format.Generic{
 | |
| 							PayloadTyp: 99,
 | |
| 							RTPMa:      "rtx/90000",
 | |
| 							FMT: map[string]string{
 | |
| 								"apt": "98",
 | |
| 							},
 | |
| 							ClockRat: 90000,
 | |
| 						},
 | |
| 						&format.H264{
 | |
| 							PayloadTyp:        100,
 | |
| 							PacketizationMode: 1,
 | |
| 						},
 | |
| 						&format.Generic{
 | |
| 							PayloadTyp: 101,
 | |
| 							RTPMa:      "rtx/90000",
 | |
| 							FMT: map[string]string{
 | |
| 								"apt": "100",
 | |
| 							},
 | |
| 							ClockRat: 90000,
 | |
| 						},
 | |
| 						&format.Generic{
 | |
| 							PayloadTyp: 127,
 | |
| 							RTPMa:      "red/90000",
 | |
| 							ClockRat:   90000,
 | |
| 						},
 | |
| 						&format.Generic{
 | |
| 							PayloadTyp: 124,
 | |
| 							RTPMa:      "rtx/90000",
 | |
| 							FMT: map[string]string{
 | |
| 								"apt": "127",
 | |
| 							},
 | |
| 							ClockRat: 90000,
 | |
| 						},
 | |
| 						&format.Generic{
 | |
| 							PayloadTyp: 125,
 | |
| 							RTPMa:      "ulpfec/90000",
 | |
| 							ClockRat:   90000,
 | |
| 						},
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	},
 | |
| 	{
 | |
| 		"multiple formats for each media 2",
 | |
| 		"v=0\r\n" +
 | |
| 			"o=- 4158123474391860926 2 IN IP4 127.0.0.1\r\n" +
 | |
| 			"s=-\r\n" +
 | |
| 			"t=0 0\r\n" +
 | |
| 			"m=video 42504 RTP/AVP 96 98\r\n" +
 | |
| 			"a=rtpmap:96 H264/90000\r\n" +
 | |
| 			"a=rtpmap:98 MetaData\r\n" +
 | |
| 			"a=rtcp-mux\r\n" +
 | |
| 			"a=fmtp:96 packetization-mode=1;profile-level-id=4d002a;" +
 | |
| 			"sprop-parameter-sets=Z00AKp2oHgCJ+WbgICAgQA==,aO48gA==\r\n",
 | |
| 		"v=0\r\n" +
 | |
| 			"o=- 0 0 IN IP4 127.0.0.1\r\n" +
 | |
| 			"s=-\r\n" +
 | |
| 			"c=IN IP4 0.0.0.0\r\n" +
 | |
| 			"t=0 0\r\n" +
 | |
| 			"m=video 0 RTP/AVP 96 98\r\n" +
 | |
| 			"a=control\r\n" +
 | |
| 			"a=rtpmap:96 H264/90000\r\n" +
 | |
| 			"a=fmtp:96 packetization-mode=1; profile-level-id=4D002A; " +
 | |
| 			"sprop-parameter-sets=Z00AKp2oHgCJ+WbgICAgQA==,aO48gA==\r\n" +
 | |
| 			"a=rtpmap:98 MetaData\r\n",
 | |
| 		Session{
 | |
| 			Title: `-`,
 | |
| 			Medias: []*Media{
 | |
| 				{
 | |
| 					Type: MediaTypeVideo,
 | |
| 					Formats: []format.Format{
 | |
| 						&format.H264{
 | |
| 							PayloadTyp: 96,
 | |
| 							SPS: []byte{
 | |
| 								0x67, 0x4d, 0x00, 0x2a, 0x9d, 0xa8, 0x1e, 0x00,
 | |
| 								0x89, 0xf9, 0x66, 0xe0, 0x20, 0x20, 0x20, 0x40,
 | |
| 							},
 | |
| 							PPS:               []byte{0x68, 0xee, 0x3c, 0x80},
 | |
| 							PacketizationMode: 1,
 | |
| 						},
 | |
| 						&format.Generic{
 | |
| 							PayloadTyp: 98,
 | |
| 							RTPMa:      "MetaData",
 | |
| 						},
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	},
 | |
| 	{
 | |
| 		"onvif back channel",
 | |
| 		"v=0\r\n" +
 | |
| 			"o= 2890842807 IN IP4 192.168.0.1\r\n" +
 | |
| 			"s=RTSP Session with audiobackchannel\r\n" +
 | |
| 			"m=video 0 RTP/AVP 26\r\n" +
 | |
| 			"a=control:rtsp://192.168.0.1/video\r\n" +
 | |
| 			"a=recvonly\r\n" +
 | |
| 			"m=audio 0 RTP/AVP 0\r\n" +
 | |
| 			"a=control:rtsp://192.168.0.1/audio\r\n" +
 | |
| 			"a=recvonly\r\n" +
 | |
| 			"m=audio 0 RTP/AVP 0\r\n" +
 | |
| 			"a=control:rtsp://192.168.0.1/audioback\r\n" +
 | |
| 			"a=rtpmap:0 PCMU/8000\r\n" +
 | |
| 			"a=sendonly\r\n",
 | |
| 		"v=0\r\n" +
 | |
| 			"o=- 0 0 IN IP4 127.0.0.1\r\n" +
 | |
| 			"s=RTSP Session with audiobackchannel\r\n" +
 | |
| 			"c=IN IP4 0.0.0.0\r\n" +
 | |
| 			"t=0 0\r\n" +
 | |
| 			"m=video 0 RTP/AVP 26\r\n" +
 | |
| 			"a=control:rtsp://192.168.0.1/video\r\n" +
 | |
| 			"a=rtpmap:26 JPEG/90000\r\n" +
 | |
| 			"m=audio 0 RTP/AVP 0\r\n" +
 | |
| 			"a=control:rtsp://192.168.0.1/audio\r\n" +
 | |
| 			"a=rtpmap:0 PCMU/8000\r\n" +
 | |
| 			"m=audio 0 RTP/AVP 0\r\n" +
 | |
| 			"a=sendonly\r\n" +
 | |
| 			"a=control:rtsp://192.168.0.1/audioback\r\n" +
 | |
| 			"a=rtpmap:0 PCMU/8000\r\n",
 | |
| 		Session{
 | |
| 			Title: `RTSP Session with audiobackchannel`,
 | |
| 			Medias: []*Media{
 | |
| 				{
 | |
| 					Type:    MediaTypeVideo,
 | |
| 					Control: "rtsp://192.168.0.1/video",
 | |
| 					Formats: []format.Format{&format.MJPEG{}},
 | |
| 				},
 | |
| 				{
 | |
| 					Type:    MediaTypeAudio,
 | |
| 					Control: "rtsp://192.168.0.1/audio",
 | |
| 					Formats: []format.Format{&format.G711{
 | |
| 						PayloadTyp:   0,
 | |
| 						MULaw:        true,
 | |
| 						SampleRate:   8000,
 | |
| 						ChannelCount: 1,
 | |
| 					}},
 | |
| 				},
 | |
| 				{
 | |
| 					Type:          MediaTypeAudio,
 | |
| 					IsBackChannel: true,
 | |
| 					Control:       "rtsp://192.168.0.1/audioback",
 | |
| 					Formats: []format.Format{&format.G711{
 | |
| 						PayloadTyp:   0,
 | |
| 						MULaw:        true,
 | |
| 						SampleRate:   8000,
 | |
| 						ChannelCount: 1,
 | |
| 					}},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	},
 | |
| 	{
 | |
| 		"issue mediamtx/1267 (tp-link)",
 | |
| 		"v=0\r\n" +
 | |
| 			"o=- 4158123474391860926 2 IN IP4 127.0.0.1\r\n" +
 | |
| 			"s=-\r\n" +
 | |
| 			"t=0 0\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=-\r\n" +
 | |
| 			"c=IN IP4 0.0.0.0\r\n" +
 | |
| 			"t=0 0\r\n" +
 | |
| 			"m=application/TP-LINK 0 RTP/AVP 95\r\n" +
 | |
| 			"a=control\r\n" +
 | |
| 			"a=rtpmap:95 TP-LINK/90000\r\n",
 | |
| 		Session{
 | |
| 			Title: `-`,
 | |
| 			Medias: []*Media{
 | |
| 				{
 | |
| 					Type: "application/TP-LINK",
 | |
| 					Formats: []format.Format{&format.Generic{
 | |
| 						PayloadTyp: 95,
 | |
| 						RTPMa:      "TP-LINK/90000",
 | |
| 						ClockRat:   90000,
 | |
| 					}},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	},
 | |
| 	{
 | |
| 		"issue gortsplib/509 (tp-link)",
 | |
| 		"v=0\n" +
 | |
| 			"o=- 14665860 31787219 1 IN IP4 192.168.1.102\n" +
 | |
| 			"s=Session streamed by \"TP-LINK RTSP Server\"\n" +
 | |
| 			"t=0 0\n" +
 | |
| 			"a=smart_encoder:virtualIFrame=1\n" +
 | |
| 			"m=application/tp-link 0 RTP/AVP smart/0/25000\n" +
 | |
| 			"a=rtpmap:95 tp-link/25000\n" +
 | |
| 			"a=control:track3\n",
 | |
| 		"v=0\r\n" +
 | |
| 			"o=- 0 0 IN IP4 127.0.0.1\r\n" +
 | |
| 			"s=Session streamed by \"TP-LINK RTSP Server\"\r\n" +
 | |
| 			"c=IN IP4 0.0.0.0\r\n" +
 | |
| 			"t=0 0\r\n" +
 | |
| 			"m=application/tp-link 0 RTP/AVP 95\r\n" +
 | |
| 			"a=control:track3\r\n" +
 | |
| 			"a=rtpmap:95 tp-link/25000\r\n",
 | |
| 		Session{
 | |
| 			Title: `Session streamed by "TP-LINK RTSP Server"`,
 | |
| 			Medias: []*Media{
 | |
| 				{
 | |
| 					Type: "application/tp-link",
 | |
| 					Formats: []format.Format{&format.Generic{
 | |
| 						PayloadTyp: 95,
 | |
| 						RTPMa:      "tp-link/25000",
 | |
| 						ClockRat:   25000,
 | |
| 					}},
 | |
| 					Control: "track3",
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	},
 | |
| 	{
 | |
| 		"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=Session streamed by \"MERCURY RTSP Server\"\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",
 | |
| 		Session{
 | |
| 			Title: `Session streamed by "MERCURY RTSP Server"`,
 | |
| 			Medias: []*Media{
 | |
| 				{
 | |
| 					Type: "application/MERCURY",
 | |
| 					Formats: []format.Format{&format.Generic{
 | |
| 						PayloadTyp: 95,
 | |
| 						RTPMa:      "MERCURY/90000",
 | |
| 						ClockRat:   90000,
 | |
| 					}},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	},
 | |
| 	{
 | |
| 		"h264 with space at end",
 | |
| 		"v=0\r\n" +
 | |
| 			"o=- 4158123474391860926 2 IN IP4 127.0.0.1\r\n" +
 | |
| 			"s=-\r\n" +
 | |
| 			"t=0 0\r\n" +
 | |
| 			"m=video 42504 RTP/AVP 96\r\n" +
 | |
| 			"a=rtpmap:96 H264/90000 \r\n" +
 | |
| 			"a=fmtp:96 packetization-mode=1\r\n",
 | |
| 		"v=0\r\n" +
 | |
| 			"o=- 0 0 IN IP4 127.0.0.1\r\n" +
 | |
| 			"s=-\r\n" +
 | |
| 			"c=IN IP4 0.0.0.0\r\n" +
 | |
| 			"t=0 0\r\n" +
 | |
| 			"m=video 0 RTP/AVP 96\r\n" +
 | |
| 			"a=control\r\n" +
 | |
| 			"a=rtpmap:96 H264/90000\r\n" +
 | |
| 			"a=fmtp:96 packetization-mode=1\r\n",
 | |
| 		Session{
 | |
| 			Title: "-",
 | |
| 			Medias: []*Media{
 | |
| 				{
 | |
| 					Type: MediaTypeVideo,
 | |
| 					Formats: []format.Format{
 | |
| 						&format.H264{
 | |
| 							PayloadTyp:        96,
 | |
| 							PacketizationMode: 1,
 | |
| 						},
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	},
 | |
| 	{
 | |
| 		"ulpfec rfc5109",
 | |
| 		"v=0\r\n" +
 | |
| 			"o=adam 289083124 289083124 IN IP4 host.example.com\r\n" +
 | |
| 			"s=ULP FEC Seminar\r\n" +
 | |
| 			"t=0 0\r\n" +
 | |
| 			"c=IN IP4 224.2.17.12/127\r\n" +
 | |
| 			"a=group:FEC 1 2\r\n" +
 | |
| 			"a=group:FEC 3 4\r\n" +
 | |
| 			"m=audio 30000 RTP/AVP 0\r\n" +
 | |
| 			"a=mid:1\r\n" +
 | |
| 			"m=application 30002 RTP/AVP 100\r\n" +
 | |
| 			"a=rtpmap:100 ulpfec/8000\r\n" +
 | |
| 			"a=mid:2\r\n" +
 | |
| 			"m=video 30004 RTP/AVP 31\r\n" +
 | |
| 			"a=mid:3\r\n" +
 | |
| 			"m=application 30004 RTP/AVP 101\r\n" +
 | |
| 			"c=IN IP4 224.2.17.13/127\r\n" +
 | |
| 			"a=rtpmap:101 ulpfec/8000\r\n" +
 | |
| 			"a=mid:4\r\n",
 | |
| 		"v=0\r\n" +
 | |
| 			"o=- 0 0 IN IP4 127.0.0.1\r\n" +
 | |
| 			"s=ULP FEC Seminar\r\n" +
 | |
| 			"c=IN IP4 0.0.0.0\r\n" +
 | |
| 			"t=0 0\r\n" +
 | |
| 			"a=group:FEC 1 2\r\n" +
 | |
| 			"a=group:FEC 3 4\r\n" +
 | |
| 			"m=audio 0 RTP/AVP 0\r\n" +
 | |
| 			"a=mid:1\r\n" +
 | |
| 			"a=control\r\n" +
 | |
| 			"a=rtpmap:0 PCMU/8000\r\n" +
 | |
| 			"m=application 0 RTP/AVP 100\r\n" +
 | |
| 			"a=mid:2\r\n" +
 | |
| 			"a=control\r\n" +
 | |
| 			"a=rtpmap:100 ulpfec/8000\r\n" +
 | |
| 			"m=video 0 RTP/AVP 31\r\n" +
 | |
| 			"a=mid:3\r\n" +
 | |
| 			"a=control\r\n" +
 | |
| 			"m=application 0 RTP/AVP 101\r\n" +
 | |
| 			"a=mid:4\r\n" +
 | |
| 			"a=control\r\n" +
 | |
| 			"a=rtpmap:101 ulpfec/8000\r\n",
 | |
| 		Session{
 | |
| 			Title: "ULP FEC Seminar",
 | |
| 			FECGroups: []SessionFECGroup{
 | |
| 				{"1", "2"},
 | |
| 				{"3", "4"},
 | |
| 			},
 | |
| 			Medias: []*Media{
 | |
| 				{
 | |
| 					ID:   "1",
 | |
| 					Type: MediaTypeAudio,
 | |
| 					Formats: []format.Format{&format.G711{
 | |
| 						PayloadTyp:   0,
 | |
| 						MULaw:        true,
 | |
| 						SampleRate:   8000,
 | |
| 						ChannelCount: 1,
 | |
| 					}},
 | |
| 				},
 | |
| 				{
 | |
| 					ID:   "2",
 | |
| 					Type: MediaTypeApplication,
 | |
| 					Formats: []format.Format{&format.Generic{
 | |
| 						PayloadTyp: 100,
 | |
| 						RTPMa:      "ulpfec/8000",
 | |
| 						ClockRat:   8000,
 | |
| 					}},
 | |
| 				},
 | |
| 				{
 | |
| 					ID:   "3",
 | |
| 					Type: MediaTypeVideo,
 | |
| 					Formats: []format.Format{&format.Generic{
 | |
| 						PayloadTyp: 31,
 | |
| 						ClockRat:   90000,
 | |
| 					}},
 | |
| 				},
 | |
| 				{
 | |
| 					ID:   "4",
 | |
| 					Type: MediaTypeApplication,
 | |
| 					Formats: []format.Format{&format.Generic{
 | |
| 						PayloadTyp: 101,
 | |
| 						RTPMa:      "ulpfec/8000",
 | |
| 						ClockRat:   8000,
 | |
| 					}},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	},
 | |
| }
 | |
| 
 | |
| func TestSessionUnmarshal(t *testing.T) {
 | |
| 	for _, ca := range casesSession {
 | |
| 		t.Run(ca.name, func(t *testing.T) {
 | |
| 			var sdp sdp.SessionDescription
 | |
| 			err := sdp.Unmarshal([]byte(ca.in))
 | |
| 			require.NoError(t, err)
 | |
| 
 | |
| 			var desc Session
 | |
| 			err = desc.Unmarshal(&sdp)
 | |
| 			require.NoError(t, err)
 | |
| 			require.Equal(t, ca.desc, desc)
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestSessionMarshal(t *testing.T) {
 | |
| 	for _, ca := range casesSession {
 | |
| 		t.Run(ca.name, func(t *testing.T) {
 | |
| 			byts, err := ca.desc.Marshal(false)
 | |
| 			require.NoError(t, err)
 | |
| 			require.Equal(t, ca.out, string(byts))
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestSessionFindFormat(t *testing.T) {
 | |
| 	tr := &format.Generic{
 | |
| 		PayloadTyp: 97,
 | |
| 		RTPMa:      "rtx/90000",
 | |
| 		FMT: map[string]string{
 | |
| 			"apt": "96",
 | |
| 		},
 | |
| 		ClockRat: 90000,
 | |
| 	}
 | |
| 
 | |
| 	md := &Media{
 | |
| 		Type: MediaTypeVideo,
 | |
| 		Formats: []format.Format{
 | |
| 			&format.VP8{
 | |
| 				PayloadTyp: 96,
 | |
| 			},
 | |
| 			tr,
 | |
| 			&format.VP9{
 | |
| 				PayloadTyp: 98,
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	desc := &Session{
 | |
| 		Medias: []*Media{
 | |
| 			{
 | |
| 				Type: MediaTypeAudio,
 | |
| 				Formats: []format.Format{
 | |
| 					&format.Opus{
 | |
| 						PayloadTyp:   111,
 | |
| 						IsStereo:     true,
 | |
| 						ChannelCount: 2,
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 			md,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	var forma *format.Generic
 | |
| 	me := desc.FindFormat(&forma)
 | |
| 	require.Equal(t, md, me)
 | |
| 	require.Equal(t, tr, forma)
 | |
| }
 | |
| 
 | |
| func FuzzSessionUnmarshal(f *testing.F) {
 | |
| 	for _, ca := range casesSession {
 | |
| 		f.Add(ca.in)
 | |
| 	}
 | |
| 
 | |
| 	f.Add("v=0\r\n" +
 | |
| 		"o=jdoe 2890844526 2890842807 IN IP4 10.47.16.5\r\n" +
 | |
| 		"s=SDP Seminar\r\n" +
 | |
| 		"m=video 0 RTP/AVP/TCP 96\r\n" +
 | |
| 		"a=rtpmap:96 H265/90000\r\n" +
 | |
| 		"a=fmtp:96 sprop-vps=QAEMAf//AWAAAAMAsAAAAwAAAwB4FwJA; " +
 | |
| 		"sprop-sps=QgEBAWAAAAMAsAAAAwAAAwB4oAKggC8c1YgXuRZFL/y5/E/qbgQEBAE=; sprop-pps=RAHAcvBTJA==;\r\n" +
 | |
| 		"a=control:streamid=0\r\n" +
 | |
| 		"m=audio 0 RTP/AVP/TCP 97\r\n" +
 | |
| 		"a=rtpmap:97 mpeg4-generic/44100/2\r\n" +
 | |
| 		"a=fmtp:97 profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3;config=zzz1210\r\n" +
 | |
| 		"a=control:streamid=1\r\n")
 | |
| 
 | |
| 	f.Add("v=0\r\n" +
 | |
| 		"o=- 4158123474391860926 2 IN IP4 127.0.0.1\r\n" +
 | |
| 		"s=-\r\n" +
 | |
| 		"t=0 0\r\n" +
 | |
| 		"m=video 42504 RTP/AVP 96\r\n" +
 | |
| 		"a=rtpmap:96 H264/90000\r\n" +
 | |
| 		"a=fmtp:96 packetization-mode=1\r\n" +
 | |
| 		"m=audio 0 RTP/AVP/TCP 0\r\n" +
 | |
| 		"a=mid:2\r\n")
 | |
| 
 | |
| 	f.Add("v=0\r\n" +
 | |
| 		"o=- 4158123474391860926 2 IN IP4 127.0.0.1\r\n" +
 | |
| 		"s=-\r\n" +
 | |
| 		"t=0 0\r\n" +
 | |
| 		"m=video 42504 RTP/AVP 96\r\n" +
 | |
| 		"a=mid:2\r\n" +
 | |
| 		"a=rtpmap:96 H264/90000\r\n" +
 | |
| 		"a=fmtp:96 packetization-mode=1\r\n" +
 | |
| 		"m=audio 0 RTP/AVP/TCP 0\r\n" +
 | |
| 		"a=mid:2\r\n")
 | |
| 
 | |
| 	f.Add("v=0\r\n" +
 | |
| 		"o=adam 289083124 289083124 IN IP4 host.example.com\r\n" +
 | |
| 		"s=ULP FEC Seminar\r\n" +
 | |
| 		"t=0 0\r\n" +
 | |
| 		"c=IN IP4 224.2.17.12/127\r\n" +
 | |
| 		"a=group:FEC 1 2\r\n" +
 | |
| 		"a=group:FEC 3 4\r\n" +
 | |
| 		"m=audio 30000 RTP/AVP 0\r\n" +
 | |
| 		"a=mid:1\r\n" +
 | |
| 		"m=application 30002 RTP/AVP 100\r\n" +
 | |
| 		"a=rtpmap:100 ulpfec/8000\r\n" +
 | |
| 		"a=mid:2\r\n" +
 | |
| 		"m=video 30004 RTP/AVP 31\r\n" +
 | |
| 		"a=mid:3\r\n" +
 | |
| 		"m=application 30004 RTP/AVP 101\r\n" +
 | |
| 		"c=IN IP4 224.2.17.13/127\r\n" +
 | |
| 		"a=rtpmap:101 ulpfec/8000\r\n" +
 | |
| 		"a=mid:4\r\n")
 | |
| 
 | |
| 	f.Fuzz(func(_ *testing.T, enc string) {
 | |
| 		var sd sdp.SessionDescription
 | |
| 		err := sd.Unmarshal([]byte(enc))
 | |
| 		if err == nil {
 | |
| 			var desc Session
 | |
| 			desc.Unmarshal(&sd) //nolint:errcheck
 | |
| 		}
 | |
| 	})
 | |
| }
 | 
