@@ -12,6 +12,7 @@ import (
1212	"time" 
1313
1414	"github.com/pion/interceptor" 
15+ 	"github.com/pion/srtp/v3" 
1516	"github.com/pion/transport/v3/test" 
1617	"github.com/pion/webrtc/v4/pkg/media" 
1718	"github.com/stretchr/testify/assert" 
@@ -64,3 +65,238 @@ func Test_RTPReceiver_SetReadDeadline(t *testing.T) {
6465	assert .NoError (t , wan .Stop ())
6566	closePairNow (t , sender , receiver )
6667}
68+ 
69+ func  Test_configureStreams (t  * testing.T ) {
70+ 	t .Run ("with RTX" , func (t  * testing.T ) {
71+ 		trackStreams  :=  & trackStreams {}
72+ 		decodingParams  :=  RTPDecodingParameters {
73+ 			RTPCodingParameters : RTPCodingParameters {
74+ 				RID :         "" ,
75+ 				SSRC :        0x89b82af4 ,
76+ 				PayloadType : 0x0 ,
77+ 				RTX :         RTPRtxParameters {SSRC : 0x35c9eefc },
78+ 				FEC :         RTPFecParameters {SSRC : 0x0 },
79+ 			},
80+ 		}
81+ 		codec  :=  RTPCodecCapability {
82+ 			MimeType :    "video/AV1" ,
83+ 			ClockRate :   0x15f90 ,
84+ 			Channels :    0x0 ,
85+ 			SDPFmtpLine : "level-idx=5;profile=0;tier=0" ,
86+ 			RTCPFeedback : []RTCPFeedback {
87+ 				{Type : "nack" , Parameter : "" },
88+ 				{Type : "nack" , Parameter : "pli" },
89+ 				{Type : "transport-cc" , Parameter : "" },
90+ 			},
91+ 		}
92+ 		globalParams  :=  RTPParameters {
93+ 			HeaderExtensions : []RTPHeaderExtensionParameter {
94+ 				{
95+ 					URI : "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01" ,
96+ 					ID :  4 ,
97+ 				},
98+ 			},
99+ 			Codecs : []RTPCodecParameters {
100+ 				{
101+ 					RTPCodecCapability : RTPCodecCapability {
102+ 						MimeType :    "video/AV1" ,
103+ 						ClockRate :   0x15f90 ,
104+ 						Channels :    0x0 ,
105+ 						SDPFmtpLine : "level-idx=5;profile=0;tier=0" ,
106+ 						RTCPFeedback : []RTCPFeedback {
107+ 							{Type : "nack" , Parameter : "" },
108+ 							{Type : "nack" , Parameter : "pli" },
109+ 							{Type : "transport-cc" , Parameter : "" },
110+ 						},
111+ 					},
112+ 					PayloadType : 0x2d ,
113+ 					statsID :     "" ,
114+ 				},
115+ 				{
116+ 					RTPCodecCapability : RTPCodecCapability {
117+ 						MimeType :     "video/rtx" ,
118+ 						ClockRate :    0x15f90 ,
119+ 						Channels :     0x0 ,
120+ 						SDPFmtpLine :  "apt=45" ,
121+ 						RTCPFeedback : nil ,
122+ 					},
123+ 					PayloadType : 0x2e ,
124+ 					statsID :     "" ,
125+ 				},
126+ 			},
127+ 		}
128+ 		expectedMediaStreamInfo  :=  & interceptor.StreamInfo {
129+ 			ID :                                "" ,
130+ 			Attributes :                        interceptor.Attributes {},
131+ 			SSRC :                              0x89b82af4 ,
132+ 			SSRCRetransmission :                0x35c9eefc ,
133+ 			SSRCForwardErrorCorrection :        0x0 ,
134+ 			PayloadType :                       0x2d ,
135+ 			PayloadTypeRetransmission :         0x2e ,
136+ 			PayloadTypeForwardErrorCorrection : 0x0 ,
137+ 			RTPHeaderExtensions : []interceptor.RTPHeaderExtension {
138+ 				{URI : "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01" , ID : 4 },
139+ 			},
140+ 			MimeType :    "video/AV1" ,
141+ 			ClockRate :   0x15f90 ,
142+ 			Channels :    0x0 ,
143+ 			SDPFmtpLine : "level-idx=5;profile=0;tier=0" ,
144+ 			RTCPFeedback : []interceptor.RTCPFeedback {
145+ 				{Type : "nack" , Parameter : "" },
146+ 				{Type : "nack" , Parameter : "pli" },
147+ 				{Type : "transport-cc" , Parameter : "" },
148+ 			},
149+ 		}
150+ 		expectedRTXStreamInfo  :=  & interceptor.StreamInfo {
151+ 			ID :                                "" ,
152+ 			Attributes :                        interceptor.Attributes {},
153+ 			SSRC :                              0x35c9eefc ,
154+ 			SSRCRetransmission :                0x0 ,
155+ 			SSRCForwardErrorCorrection :        0x0 ,
156+ 			PayloadType :                       0x2e ,
157+ 			PayloadTypeRetransmission :         0x0 ,
158+ 			PayloadTypeForwardErrorCorrection : 0x0 ,
159+ 			RTPHeaderExtensions : []interceptor.RTPHeaderExtension {
160+ 				{URI : "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01" , ID : 4 },
161+ 			},
162+ 			MimeType :    "video/AV1" ,
163+ 			ClockRate :   0x15f90 ,
164+ 			Channels :    0x0 ,
165+ 			SDPFmtpLine : "level-idx=5;profile=0;tier=0" ,
166+ 			RTCPFeedback : []interceptor.RTCPFeedback {
167+ 				{Type : "nack" , Parameter : "" },
168+ 				{Type : "nack" , Parameter : "pli" },
169+ 				{Type : "transport-cc" , Parameter : "" },
170+ 			},
171+ 		}
172+ 		callCount  :=  0 
173+ 		haveRTX , err  :=  trackStreams .configureStreams (
174+ 			decodingParams ,
175+ 			codec ,
176+ 			globalParams ,
177+ 			// Mock DTLSTransport.streamsForSSRC here, DTLSTransport.streamsForSSRC calls interceptor.BindRemoteStream, 
178+ 			// so the interceptor.StreamInfo here is exactly the StreamInfo that will be passed into interceptors. 
179+ 			func (s  SSRC , si  interceptor.StreamInfo ) (
180+ 				* srtp.ReadStreamSRTP ,
181+ 				interceptor.RTPReader ,
182+ 				* srtp.ReadStreamSRTCP ,
183+ 				interceptor.RTCPReader ,
184+ 				error ,
185+ 			) {
186+ 				switch  callCount  {
187+ 				case  0 :
188+ 					assert .Equal (t , s , SSRC (0x89b82af4 ))
189+ 					assert .Equal (t , si , * expectedMediaStreamInfo )
190+ 				case  1 :
191+ 					assert .Equal (t , s , SSRC (0x35c9eefc ))
192+ 					assert .Equal (t , si , * expectedRTXStreamInfo )
193+ 				default :
194+ 					assert .Fail (t , "streamsForSSRC called more than twice when only video track and rtx track existed" )
195+ 				}
196+ 				callCount ++ 
197+ 
198+ 				return  nil , nil , nil , nil , nil 
199+ 			},
200+ 		)
201+ 		assert .NoError (t , err )
202+ 		assert .True (t , haveRTX )
203+ 		assert .Equal (t , trackStreams .mediaStream .streamInfo , expectedMediaStreamInfo )
204+ 		assert .Equal (t , trackStreams .rtxStream .streamInfo , expectedRTXStreamInfo )
205+ 	})
206+ 
207+ 	t .Run ("no RTX" , func (t  * testing.T ) {
208+ 		trackStreams  :=  & trackStreams {}
209+ 		decodingParams  :=  RTPDecodingParameters {
210+ 			RTPCodingParameters : RTPCodingParameters {
211+ 				RID :         "" ,
212+ 				SSRC :        0x89b82af4 ,
213+ 				PayloadType : 0x0 ,
214+ 				RTX :         RTPRtxParameters {SSRC : 0x0 },
215+ 				FEC :         RTPFecParameters {SSRC : 0x0 },
216+ 			},
217+ 		}
218+ 		codec  :=  RTPCodecCapability {
219+ 			MimeType :    "video/AV1" ,
220+ 			ClockRate :   0x15f90 ,
221+ 			Channels :    0x0 ,
222+ 			SDPFmtpLine : "level-idx=5;profile=0;tier=0" ,
223+ 			RTCPFeedback : []RTCPFeedback {
224+ 				{Type : "transport-cc" , Parameter : "" },
225+ 			},
226+ 		}
227+ 		globalParams  :=  RTPParameters {
228+ 			HeaderExtensions : []RTPHeaderExtensionParameter {
229+ 				{
230+ 					URI : "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01" ,
231+ 					ID :  4 ,
232+ 				},
233+ 			},
234+ 			Codecs : []RTPCodecParameters {
235+ 				{
236+ 					RTPCodecCapability : RTPCodecCapability {
237+ 						MimeType :    "video/AV1" ,
238+ 						ClockRate :   0x15f90 ,
239+ 						Channels :    0x0 ,
240+ 						SDPFmtpLine : "level-idx=5;profile=0;tier=0" ,
241+ 						RTCPFeedback : []RTCPFeedback {
242+ 							{Type : "transport-cc" , Parameter : "" },
243+ 						},
244+ 					},
245+ 					PayloadType : 0x2d ,
246+ 					statsID :     "" ,
247+ 				},
248+ 			},
249+ 		}
250+ 		expectedMediaStreamInfo  :=  & interceptor.StreamInfo {
251+ 			ID :                                "" ,
252+ 			Attributes :                        interceptor.Attributes {},
253+ 			SSRC :                              0x89b82af4 ,
254+ 			SSRCRetransmission :                0x0 ,
255+ 			SSRCForwardErrorCorrection :        0x0 ,
256+ 			PayloadType :                       0x2d ,
257+ 			PayloadTypeRetransmission :         0x0 ,
258+ 			PayloadTypeForwardErrorCorrection : 0x0 ,
259+ 			RTPHeaderExtensions : []interceptor.RTPHeaderExtension {
260+ 				{URI : "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01" , ID : 4 },
261+ 			},
262+ 			MimeType :    "video/AV1" ,
263+ 			ClockRate :   0x15f90 ,
264+ 			Channels :    0x0 ,
265+ 			SDPFmtpLine : "level-idx=5;profile=0;tier=0" ,
266+ 			RTCPFeedback : []interceptor.RTCPFeedback {
267+ 				{Type : "transport-cc" , Parameter : "" },
268+ 			},
269+ 		}
270+ 		var  expectedRTXStreamInfo  * interceptor.StreamInfo 
271+ 		callCount  :=  0 
272+ 		haveRTX , err  :=  trackStreams .configureStreams (
273+ 			decodingParams ,
274+ 			codec ,
275+ 			globalParams ,
276+ 			// Mock DTLSTransport.streamsForSSRC here, DTLSTransport.streamsForSSRC calls interceptor.BindRemoteStream, 
277+ 			// so the interceptor.StreamInfo here is exactly the StreamInfo that will be passed into interceptors. 
278+ 			func (s  SSRC , si  interceptor.StreamInfo ) (
279+ 				* srtp.ReadStreamSRTP ,
280+ 				interceptor.RTPReader ,
281+ 				* srtp.ReadStreamSRTCP ,
282+ 				interceptor.RTCPReader ,
283+ 				error ,
284+ 			) {
285+ 				switch  callCount  {
286+ 				case  0 :
287+ 					assert .Equal (t , s , SSRC (0x89b82af4 ))
288+ 					assert .Equal (t , si , * expectedMediaStreamInfo )
289+ 				default :
290+ 					assert .Fail (t , "streamsForSSRC called more than once when only video track existed" )
291+ 				}
292+ 				callCount ++ 
293+ 
294+ 				return  nil , nil , nil , nil , nil 
295+ 			},
296+ 		)
297+ 		assert .NoError (t , err )
298+ 		assert .False (t , haveRTX )
299+ 		assert .Equal (t , trackStreams .mediaStream .streamInfo , expectedMediaStreamInfo )
300+ 		assert .Equal (t , trackStreams .rtxStream .streamInfo , expectedRTXStreamInfo )
301+ 	})
302+ }
0 commit comments