blob: cd48560617d87fef3ac77fb2f928d9043e0046c0 [file] [log] [blame]
Soares Chen0042ebb2017-06-05 13:42:061<!doctype html>
2<meta charset=utf-8>
3<title>RTCPeerConnection.prototype.addTransceiver</title>
4<script src="/resources/testharness.js"></script>
5<script src="/resources/testharnessreport.js"></script>
Soares Chen607f71c2017-06-27 15:23:376<script src="RTCPeerConnection-helper.js"></script>
Soares Chen0042ebb2017-06-05 13:42:067<script>
8 'use strict';
9
10 // Test is based on the following editor draft:
Soares Chen7d2c2d72017-06-21 05:09:3611 // https://rawgit.com/w3c/webrtc-pc/cc8d80f455b86c8041d63bceb8b457f45c72aa89/webrtc.html
Soares Chen607f71c2017-06-27 15:23:3712
Soares Chen7d2c2d72017-06-21 05:09:3613 // The following helper functions are called from RTCPeerConnection-helper.js:
14 // generateMediaStreamTrack()
Soares Chen0042ebb2017-06-05 13:42:0615
16 /*
Soares Chen7d2c2d72017-06-21 05:09:3617 5.1. RTCPeerConnection Interface Extensions
18
19 partial interface RTCPeerConnection {
20 sequence<RTCRtpSender> getSenders();
21 sequence<RTCRtpReceiver> getReceivers();
22 sequence<RTCRtpTransceiver> getTransceivers();
23 RTCRtpTransceiver addTransceiver((MediaStreamTrack or DOMString) trackOrKind,
24 optional RTCRtpTransceiverInit init);
25 ...
26 };
27
28 dictionary RTCRtpTransceiverInit {
29 RTCRtpTransceiverDirection direction = "sendrecv";
30 sequence<MediaStream> streams;
31 sequence<RTCRtpEncodingParameters> sendEncodings;
32 };
33
34 5.2. RTCRtpSender Interface
35
36 interface RTCRtpSender {
37 readonly attribute MediaStreamTrack? track;
38 ...
39 };
40
41 5.3. RTCRtpReceiver Interface
42
43 interface RTCRtpReceiver {
44 readonly attribute MediaStreamTrack track;
45 ...
46 };
47
48 5.4. RTCRtpTransceiver Interface
49
50 interface RTCRtpTransceiver {
51 readonly attribute DOMString? mid;
52 [SameObject]
53 readonly attribute RTCRtpSender sender;
54 [SameObject]
55 readonly attribute RTCRtpReceiver receiver;
56 readonly attribute boolean stopped;
57 readonly attribute RTCRtpTransceiverDirection direction;
58 readonly attribute RTCRtpTransceiverDirection? currentDirection;
59 ...
60 };
Soares Chen607f71c2017-06-27 15:23:3761
62 Note
63 While addTrack checks if the MediaStreamTrack given as an argument is
64 already being sent to avoid sending the same MediaStreamTrack twice,
65 the other ways do not, allowing the same MediaStreamTrack to be sent
66 several times simultaneously.
Soares Chen0042ebb2017-06-05 13:42:0667 */
68
69 /*
Soares Chen7d2c2d72017-06-21 05:09:3670 5.1. addTransceiver
71 3. If the first argument is a string, let it be kind and run the following steps:
72 1. If kind is not a legal MediaStreamTrack kind, throw a TypeError.
73 */
74 test(t => {
75 const pc = new RTCPeerConnection();
76 assert_own_property(pc, 'addTransceiver');
77 assert_throws(new TypeError(), () => pc.addTransceiver('invalid'));
78 }, 'addTransceiver() with string argument as invalid kind should throw TypeError');
79
80 /*
81 5.1. addTransceiver
82 The initial value of mid is null.
83
84 3. If the dictionary argument is present, let direction be the value of the
85 direction member. Otherwise let direction be sendrecv.
86 4. If the first argument is a string, let it be kind and run the following steps:
87 2. Let track be null.
88 8. Create an RTCRtpSender with track, streams and sendEncodings and let
89 sender be the result.
90 9. Create an RTCRtpReceiver with kind and let receiver be the result.
91 10. Create an RTCRtpTransceiver with sender, receiver and direction, and let
92 transceiver be the result.
93 11. Add transceiver to connection's set of transceivers.
94
95 5.2. RTCRtpSender Interface
96 Create an RTCRtpSender
97 2. Set sender.track to track.
98
99 5.3. RTCRtpReceiver Interface
100 Create an RTCRtpReceiver
101 2. Let track be a new MediaStreamTrack object [GETUSERMEDIA]. The source of
102 track is a remote source provided by receiver.
103 3. Initialize track.kind to kind.
104 5. Initialize track.label to the result of concatenating the string "remote "
105 with kind.
106 6. Initialize track.readyState to live.
107 7. Initialize track.muted to true.
108 8. Set receiver.track to track.
109
110 5.4. RTCRtpTransceiver Interface
111 Create an RTCRtpTransceiver
112 2. Set transceiver.sender to sender.
113 3. Set transceiver.receiver to receiver.
114 4. Let transceiver have a [[Direction]] internal slot, initialized to direction.
115 5. Let transceiver have a [[CurrentDirection]] internal slot, initialized
116 to null.
117 6. Set transceiver.stopped to false.
Soares Chen0042ebb2017-06-05 13:42:06118 */
119 test(t => {
120 const pc = new RTCPeerConnection();
121
122 assert_own_property(pc, 'addTransceiver');
123
124 const transceiver = pc.addTransceiver('audio');
125 assert_true(transceiver instanceof RTCRtpTransceiver,
126 'Expect transceiver to be instance of RTCRtpTransceiver');
127
128 assert_equals(transceiver.mid, null);
129 assert_equals(transceiver.stopped, false);
130 assert_equals(transceiver.direction, 'sendrecv');
Soares Chen7d2c2d72017-06-21 05:09:36131 assert_equals(transceiver.currentDirection, null);
Soares Chen0042ebb2017-06-05 13:42:06132
133 assert_array_equals([transceiver], pc.getTransceivers(),
134 `Expect added transceiver to be the only element in connection's list of transceivers`);
135
136 const sender = transceiver.sender;
137
138 assert_true(sender instanceof RTCRtpSender,
139 'Expect sender to be instance of RTCRtpSender');
140
141 assert_equals(sender.track, null);
142
143 assert_array_equals([sender], pc.getSenders(),
144 `Expect added sender to be the only element in connection's list of senders`);
145
146 const receiver = transceiver.receiver;
147 assert_true(receiver instanceof RTCRtpReceiver,
148 'Expect receiver to be instance of RTCRtpReceiver');
149
150 const track = receiver.track
151 assert_true(track instanceof MediaStreamTrack,
152 'Expect receiver.track to be instance of MediaStreamTrack');
153
154 assert_equals(track.kind, 'audio');
155 assert_equals(track.label, 'remote audio');
156 assert_equals(track.readyState, 'live');
157 assert_equals(track.muted, true);
158
159 assert_array_equals([receiver], pc.getReceivers(),
160 `Expect added receiver to be the only element in connection's list of receivers`);
161
162 }, `addTransceiver('audio') should return an audio transceiver`);
163
164 test(t => {
165 const pc = new RTCPeerConnection();
166
167 assert_own_property(pc, 'addTransceiver');
168
169 const transceiver = pc.addTransceiver('video');
170 assert_true(transceiver instanceof RTCRtpTransceiver,
171 'Expect transceiver to be instance of RTCRtpTransceiver');
172
173 assert_equals(transceiver.mid, null);
174 assert_equals(transceiver.stopped, false);
175 assert_equals(transceiver.direction, 'sendrecv');
176
177 assert_array_equals([transceiver], pc.getTransceivers(),
178 `Expect added transceiver to be the only element in connection's list of transceivers`);
179
180 const sender = transceiver.sender;
181
182 assert_true(sender instanceof RTCRtpSender,
183 'Expect sender to be instance of RTCRtpSender');
184
185 assert_equals(sender.track, null);
186
187 assert_array_equals([sender], pc.getSenders(),
188 `Expect added sender to be the only element in connection's list of senders`);
189
190 const receiver = transceiver.receiver;
191 assert_true(receiver instanceof RTCRtpReceiver,
192 'Expect receiver to be instance of RTCRtpReceiver');
193
194 const track = receiver.track
195 assert_true(track instanceof MediaStreamTrack,
196 'Expect receiver.track to be instance of MediaStreamTrack');
197
198 assert_equals(track.kind, 'video');
199 assert_equals(track.label, 'remote video');
200 assert_equals(track.readyState, 'live');
201 assert_equals(track.muted, true);
202
203 assert_array_equals([receiver], pc.getReceivers(),
204 `Expect added receiver to be the only element in connection's list of receivers`);
205
206 }, `addTransceiver('video') should return a video transceiver`);
207
208 /*
Soares Chen607f71c2017-06-27 15:23:37209 5.1. addTransceiver
Soares Chen7d2c2d72017-06-21 05:09:36210 5. If the first argument is a MediaStreamTrack , let it be track and let
Soares Chen607f71c2017-06-27 15:23:37211 kind be track.kind.
Soares Chen607f71c2017-06-27 15:23:37212 */
213 test(t => {
214 const pc = new RTCPeerConnection();
215 const track = generateMediaStreamTrack('audio');
216
217 const transceiver = pc.addTransceiver(track);
218 const { sender, receiver } = transceiver;
219
220 assert_true(sender instanceof RTCRtpSender,
221 'Expect sender to be instance of RTCRtpSender');
222
223 assert_true(receiver instanceof RTCRtpReceiver,
224 'Expect receiver to be instance of RTCRtpReceiver');
225
226 assert_equals(sender.track, track,
227 'Expect sender.track should be the track that is added');
228
229 const receiverTrack = receiver.track
230 assert_true(receiverTrack instanceof MediaStreamTrack,
231 'Expect receiver.track to be instance of MediaStreamTrack');
232
233 assert_equals(receiverTrack.kind, 'audio',
234 `receiver.track should have the same kind as added track's kind`);
235
236 assert_equals(receiverTrack.label, 'remote audio');
237 assert_equals(receiverTrack.readyState, 'live');
238 assert_equals(receiverTrack.muted, true);
239
240 assert_array_equals([transceiver], pc.getTransceivers(),
241 `Expect added transceiver to be the only element in connection's list of transceivers`);
242
243 assert_array_equals([sender], pc.getSenders(),
244 `Expect added sender to be the only element in connection's list of senders`);
245
246 assert_array_equals([receiver], pc.getReceivers(),
247 `Expect added receiver to be the only element in connection's list of receivers`);
248
249 }, 'addTransceiver(track) should have result with sender.track be given track');
250
251 test(t => {
252 const pc = new RTCPeerConnection();
253 const track = generateMediaStreamTrack('audio');
254
255 const transceiver1 = pc.addTransceiver(track);
256 const transceiver2 = pc.addTransceiver(track);
257
258 assert_not_equals(transceiver1, transceiver2);
259
260 const sender1 = transceiver1.sender;
261 const sender2 = transceiver2.sender;
262
263 assert_not_equals(sender1, sender2);
264 assert_equals(transceiver1.sender.track, track);
265 assert_equals(transceiver2.sender.track, track);
266
267 const transceivers = pc.getTransceivers();
268 assert_equals(transceivers.length, 2);
269 assert_true(transceivers.includes(transceiver1));
270 assert_true(transceivers.includes(transceiver2));
271
272 const senders = pc.getSenders();
273 assert_equals(senders.length, 2);
274 assert_true(senders.includes(sender1));
275 assert_true(senders.includes(sender2));
276
277 }, 'addTransceiver(track) multiple times should create multiple transceivers');
278
279 /*
280 TODO
281 5.1. addTransceiver
Soares Chen7d2c2d72017-06-21 05:09:36282 - Adding a transceiver will cause future calls to createOffer to add a media
283 description for the corresponding transceiver, as defined in [JSEP]
284 (section 5.2.2.).
Soares Chen607f71c2017-06-27 15:23:37285
Soares Chen7d2c2d72017-06-21 05:09:36286 - Setting a new RTCSessionDescription may change mid to a non-null value,
287 as defined in [JSEP] (section 5.5. and section 5.6.).
288
289 - The sendEncodings argument can be used to specify the number of offered
290 simulcast encodings, and optionally their RIDs and encoding parameters.
291 Aside from rid , all read-only parameters in the RTCRtpEncodingParameters
292 dictionaries, such as ssrc, must be left unset, or an error will be thrown.
Soares Chen607f71c2017-06-27 15:23:37293
294 1. If the dictionary argument is present, and it has a streams member, let
295 streams be that list of MediaStream objects.
Soares Chen7d2c2d72017-06-21 05:09:36296
Soares Chen607f71c2017-06-27 15:23:37297 2. If the dictionary argument is present, and it has a sendEncodings member,
298 let sendEncodings be that list of RTCRtpEncodingParameters objects.
Soares Chen7d2c2d72017-06-21 05:09:36299
300 6. Verify that each rid value in sendEncodings is composed only of
301 case-sensitive alphanumeric characters (a-z, A-Z, 0-9) up to a maximum
302 of 16 characters. If one of the RIDs does not meet these requirements,
303 throw a TypeError.
304
305 7. If any RTCRtpEncodingParameters dictionary in sendEncodings contains
306 a read-only parameter other than rid , throw an InvalidAccessError.
307
308 5.2. RTCRtpSender Interface
309 Create an RTCRtpSender
310 3. Let sender have an [[associated MediaStreams]] internal slot, representing
311 a list of MediaStream objects that the MediaStreamTrack object of this
312 sender is associated with.
313
314 4. Set sender's [[associated MediaStreams]] slot to streams.
315
316 5. Let sender have a [[send encodings]] internal slot, representing a list
317 of RTCRtpEncodingParameters dictionaries.
318
319 6. If sendEncodings is given as input to this algorithm, and is non-empty,
320 set the [[send encodings]] slot to sendEncodings. Otherwise, set it to a
321 list containing a single RTCRtpEncodingParameters with active set to true.
322
323 5.3. RTCRtpReceiver Interface
324 Create an RTCRtpReceiver
325 4. If an id string, id, was given as input to this algorithm, initialize
326 track.id to id. (Otherwise the value generated when track was created
327 will be used.)
328
329 Tested in RTCPeerConnection-onnegotiationneeded.html
330 5.1. addTransceiver
331 12. Update the negotiation-needed flag for connection.
332
333 Out of Scope
334 5.1. addTransceiver
335 8. If sendEncodings is set, then subsequent calls to createOffer will be
Soares Chen607f71c2017-06-27 15:23:37336 configured to send multiple RTP encodings as defined in [JSEP]
Soares Chen7d2c2d72017-06-21 05:09:36337 (section 5.2.2. and section 5.2.1.).
338
339 When setRemoteDescription is called with a corresponding remote
340 description that is able to receive multiple RTP encodings as defined
341 in [JSEP] (section 3.7.), the RTCRtpSender may send multiple RTP
342 encodings and the parameters retrieved via the transceiver's
343 sender.getParameters() will reflect the encodings negotiated.
344
345 9. This specification does not define how to configure createOffer to
Soares Chen607f71c2017-06-27 15:23:37346 receive multiple RTP encodings. However when setRemoteDescription is
347 called with a corresponding remote description that is able to send
348 multiple RTP encodings as defined in [JSEP], the RTCRtpReceiver may
349 receive multiple RTP encodings and the parameters retrieved via the
350 transceiver's receiver.getParameters() will reflect the encodings
351 negotiated.
Soares Chen607f71c2017-06-27 15:23:37352
Soares Chen7d2c2d72017-06-21 05:09:36353 Coverage Report
354 Tested Not-Tested Non-Testable Total
355 addTransceiver 11 4 3 18
356 Create Sender 3 4 0 7
357 Create Receiver 8 1 0 9
358 Create Transceiver 7 0 0 7
Soares Chen607f71c2017-06-27 15:23:37359
Soares Chen7d2c2d72017-06-21 05:09:36360 Total 29 9 3 41
Soares Chen607f71c2017-06-27 15:23:37361 */
Soares Chen0042ebb2017-06-05 13:42:06362</script>