mirror of
https://github.com/aler9/gortsplib
synced 2025-09-27 03:25:52 +08:00
982 lines
26 KiB
Go
982 lines
26 KiB
Go
package description
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/bluenviron/gortsplib/v4/pkg/format"
|
|
"github.com/bluenviron/gortsplib/v4/pkg/headers"
|
|
"github.com/bluenviron/gortsplib/v4/pkg/mikey"
|
|
"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,
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
"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,
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
"key-mgmt in session",
|
|
"v=0\n" +
|
|
"o=actionmovie 2891092738 2891092738 IN IP4 movie.example.com\n" +
|
|
"s=Action Movie\n" +
|
|
"t=0 0\n" +
|
|
"c=IN IP4 movie.example.com\n" +
|
|
"a=key-mgmt:mikey AQAFAHojKV4BAACVjCMnAAAAAAsA6/mdTLBeokwKEGwcAuPrxj6/enyb+" +
|
|
"A2+rNcBAAAAFQABAQEBEAIBAQMBCgcBAQgBAQoBAQAAACIAIAAeX8XvOCzIMh0JTOWivWLxEflTUSp1fjj2i8xG7D9DAA==\r\n" +
|
|
"m=video 0 RTP/SAVP 96\n" +
|
|
"a=rtpmap:96 H264/90000\n" +
|
|
"a=control:trackID=0\n",
|
|
"v=0\r\n" +
|
|
"o=- 0 0 IN IP4 127.0.0.1\r\n" +
|
|
"s=Action Movie\r\n" +
|
|
"c=IN IP4 0.0.0.0\r\n" +
|
|
"t=0 0\r\n" +
|
|
"a=key-mgmt:mikey AQAFAHojKV4BAACVjCMnAAAAAAsA6/mdTLBeokwKEGwcAuPrxj6/enyb+" +
|
|
"A2+rNcBAAAAFQABAQEBEAIBAQMBCgcBAQgBAQoBAQAAACIAIAAeX8XvOCzIMh0JTOWivWLxEflTUSp1fjj2i8xG7D9DAA==\r\n" +
|
|
"m=video 0 RTP/SAVP 96\r\n" +
|
|
"a=control:trackID=0\r\n" +
|
|
"a=rtpmap:96 H264/90000\r\n",
|
|
Session{
|
|
Title: "Action Movie",
|
|
KeyMgmtMikey: &mikey.Message{ //nolint:dupl
|
|
Header: mikey.Header{
|
|
Version: 1,
|
|
CSBID: 2049124702,
|
|
CSIDMapInfo: []mikey.SRTPIDEntry{{
|
|
SSRC: 2508989223,
|
|
}},
|
|
},
|
|
Payloads: []mikey.Payload{
|
|
&mikey.PayloadT{
|
|
TSValue: 17003794820816085580,
|
|
},
|
|
&mikey.PayloadRAND{
|
|
Data: []byte{
|
|
0x6c, 0x1c, 0x02, 0xe3, 0xeb, 0xc6, 0x3e, 0xbf,
|
|
0x7a, 0x7c, 0x9b, 0xf8, 0x0d, 0xbe, 0xac, 0xd7,
|
|
},
|
|
},
|
|
&mikey.PayloadSP{
|
|
PolicyParams: []mikey.PayloadSPPolicyParam{
|
|
{
|
|
Type: 0, Value: []byte{1},
|
|
},
|
|
{
|
|
Type: 1, Value: []byte{0x10},
|
|
},
|
|
{
|
|
Type: 2, Value: []byte{1},
|
|
},
|
|
{
|
|
Type: 3, Value: []byte{0x0a},
|
|
},
|
|
{
|
|
Type: 7, Value: []byte{1},
|
|
},
|
|
{
|
|
Type: 8, Value: []byte{1},
|
|
},
|
|
{
|
|
Type: 10, Value: []byte{1},
|
|
},
|
|
},
|
|
},
|
|
&mikey.PayloadKEMAC{
|
|
SubPayloads: []*mikey.SubPayloadKeyData{
|
|
{
|
|
Type: 2,
|
|
KeyData: []byte{
|
|
0x5f, 0xc5, 0xef, 0x38, 0x2c, 0xc8, 0x32, 0x1d,
|
|
0x09, 0x4c, 0xe5, 0xa2, 0xbd, 0x62, 0xf1, 0x11,
|
|
0xf9, 0x53, 0x51, 0x2a, 0x75, 0x7e, 0x38, 0xf6,
|
|
0x8b, 0xcc, 0x46, 0xec, 0x3f, 0x43,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Medias: []*Media{
|
|
{
|
|
Type: "video",
|
|
Control: "trackID=0",
|
|
Secure: true,
|
|
Profile: headers.TransportProfileSAVP,
|
|
Formats: []format.Format{&format.H264{
|
|
PayloadTyp: 96,
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
"key-mgmt in media",
|
|
"v=0\n" +
|
|
"o=actionmovie 2891092738 2891092738 IN IP4 movie.example.com\n" +
|
|
"s=Action Movie\n" +
|
|
"t=0 0\n" +
|
|
"c=IN IP4 movie.example.com\n" +
|
|
"m=video 0 RTP/SAVP 96\n" +
|
|
"a=key-mgmt:mikey AQAFAHojKV4BAACVjCMnAAAAAAsA6/mdTLBeokwKEGwcAuPrxj6/enyb+" +
|
|
"A2+rNcBAAAAFQABAQEBEAIBAQMBCgcBAQgBAQoBAQAAACIAIAAeX8XvOCzIMh0JTOWivWLxEflTUSp1fjj2i8xG7D9DAA==\r\n" +
|
|
"a=rtpmap:96 H264/90000\n" +
|
|
"a=control:trackID=0\n",
|
|
"v=0\r\n" +
|
|
"o=- 0 0 IN IP4 127.0.0.1\r\n" +
|
|
"s=Action Movie\r\n" +
|
|
"c=IN IP4 0.0.0.0\r\n" +
|
|
"t=0 0\r\n" +
|
|
"m=video 0 RTP/SAVP 96\r\n" +
|
|
"a=key-mgmt:mikey AQAFAHojKV4BAACVjCMnAAAAAAsA6/mdTLBeokwKEGwcAuPrxj6/enyb+" +
|
|
"A2+rNcBAAAAFQABAQEBEAIBAQMBCgcBAQgBAQoBAQAAACIAIAAeX8XvOCzIMh0JTOWivWLxEflTUSp1fjj2i8xG7D9DAA==\r\n" +
|
|
"a=control:trackID=0\r\n" +
|
|
"a=rtpmap:96 H264/90000\r\n",
|
|
Session{
|
|
Title: "Action Movie",
|
|
Medias: []*Media{
|
|
{
|
|
Type: "video",
|
|
Control: "trackID=0",
|
|
Secure: true,
|
|
Profile: headers.TransportProfileSAVP,
|
|
KeyMgmtMikey: &mikey.Message{ //nolint:dupl
|
|
Header: mikey.Header{
|
|
Version: 1,
|
|
CSBID: 2049124702,
|
|
CSIDMapInfo: []mikey.SRTPIDEntry{{
|
|
SSRC: 2508989223,
|
|
}},
|
|
},
|
|
Payloads: []mikey.Payload{
|
|
&mikey.PayloadT{
|
|
TSValue: 17003794820816085580,
|
|
},
|
|
&mikey.PayloadRAND{
|
|
Data: []byte{
|
|
0x6c, 0x1c, 0x02, 0xe3, 0xeb, 0xc6, 0x3e, 0xbf,
|
|
0x7a, 0x7c, 0x9b, 0xf8, 0x0d, 0xbe, 0xac, 0xd7,
|
|
},
|
|
},
|
|
&mikey.PayloadSP{
|
|
PolicyParams: []mikey.PayloadSPPolicyParam{
|
|
{
|
|
Type: 0, Value: []byte{1},
|
|
},
|
|
{
|
|
Type: 1, Value: []byte{0x10},
|
|
},
|
|
{
|
|
Type: 2, Value: []byte{1},
|
|
},
|
|
{
|
|
Type: 3, Value: []byte{0x0a},
|
|
},
|
|
{
|
|
Type: 7, Value: []byte{1},
|
|
},
|
|
{
|
|
Type: 8, Value: []byte{1},
|
|
},
|
|
{
|
|
Type: 10, Value: []byte{1},
|
|
},
|
|
},
|
|
},
|
|
&mikey.PayloadKEMAC{
|
|
SubPayloads: []*mikey.SubPayloadKeyData{
|
|
{
|
|
Type: 2,
|
|
KeyData: []byte{
|
|
0x5f, 0xc5, 0xef, 0x38, 0x2c, 0xc8, 0x32, 0x1d,
|
|
0x09, 0x4c, 0xe5, 0xa2, 0xbd, 0x62, 0xf1, 0x11,
|
|
0xf9, 0x53, 0x51, 0x2a, 0x75, 0x7e, 0x38, 0xf6,
|
|
0x8b, 0xcc, 0x46, 0xec, 0x3f, 0x43,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Formats: []format.Format{&format.H264{
|
|
PayloadTyp: 96,
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
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(t *testing.T, enc string) {
|
|
var sd sdp.SessionDescription
|
|
err := sd.Unmarshal([]byte(enc))
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
var desc Session
|
|
err = desc.Unmarshal(&sd)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
require.NotZero(t, len(desc.Medias))
|
|
|
|
_, err = desc.Marshal(false)
|
|
require.NoError(t, err)
|
|
})
|
|
}
|