RTCRtpParameters-helper.js (8032B)
1 'use strict'; 2 3 // Test is based on the following editor draft: 4 // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html 5 6 // Helper function for testing RTCRtpParameters dictionary fields 7 8 // This file depends on dictionary-helper.js which should 9 // be loaded from the main HTML file. 10 11 // An offer/answer exchange is necessary for getParameters() to have any 12 // negotiated parameters to return. 13 async function doOfferAnswerExchange(t, caller) { 14 const callee = new RTCPeerConnection(); 15 t.add_cleanup(() => callee.close()); 16 const offer = await caller.createOffer(); 17 await caller.setLocalDescription(offer); 18 await callee.setRemoteDescription(offer); 19 const answer = await callee.createAnswer(); 20 await callee.setLocalDescription(answer); 21 await caller.setRemoteDescription(answer); 22 23 return callee; 24 } 25 26 /* 27 Validates the RTCRtpParameters returned from RTCRtpSender.prototype.getParameters 28 29 5.2. RTCRtpSender Interface 30 getParameters 31 - transactionId is set to a new unique identifier, used to match this getParameters 32 call to a setParameters call that may occur later. 33 34 - encodings is set to the value of the [[SendEncodings]] internal slot. 35 36 - The headerExtensions sequence is populated based on the header extensions that 37 have been negotiated for sending. 38 39 - The codecs sequence is populated based on the codecs that have been negotiated 40 for sending, and which the user agent is currently capable of sending. If 41 setParameters has removed or reordered codecs, getParameters MUST return the 42 shortened/reordered list. However, every time codecs are renegotiated by a 43 new offer/answer exchange, the list of codecs MUST be restored to the full 44 negotiated set, in the priority order indicated by the remote description, 45 in effect discarding the effects of setParameters. 46 47 - rtcp.cname is set to the CNAME of the associated RTCPeerConnection. rtcp.reducedSize 48 is set to true if reduced-size RTCP has been negotiated for sending, and false otherwise. 49 */ 50 function validateSenderRtpParameters(param) { 51 validateRtpParameters(param); 52 53 assert_array_field(param, 'encodings'); 54 for(const encoding of param.encodings) { 55 validateEncodingParameters(encoding); 56 } 57 58 assert_not_equals(param.transactionId, undefined, 59 'Expect sender param.transactionId to be set'); 60 61 assert_not_equals(param.rtcp.cname, undefined, 62 'Expect sender param.rtcp.cname to be set'); 63 64 assert_not_equals(param.rtcp.reducedSize, undefined, 65 'Expect sender param.rtcp.reducedSize to be set to either true or false'); 66 } 67 68 /* 69 Validates the RTCRtpParameters returned from RTCRtpReceiver.prototype.getParameters 70 71 5.3. RTCRtpReceiver Interface 72 getParameters 73 When getParameters is called, the RTCRtpParameters dictionary is constructed 74 as follows: 75 76 - The headerExtensions sequence is populated based on the header extensions that 77 the receiver is currently prepared to receive. 78 79 - The codecs sequence is populated based on the codecs that the receiver is currently 80 prepared to receive. 81 82 - rtcp.reducedSize is set to true if the receiver is currently prepared to receive 83 reduced-size RTCP packets, and false otherwise. rtcp.cname is left undefined. 84 85 - transactionId is left undefined. 86 */ 87 function validateReceiverRtpParameters(param) { 88 validateRtpParameters(param); 89 90 assert_equals(param.transactionId, undefined, 91 'Expect receiver param.transactionId to be unset'); 92 93 assert_not_equals(param.rtcp.reducedSize, undefined, 94 'Expect receiver param.rtcp.reducedSize to be set'); 95 96 assert_equals(param.rtcp.cname, undefined, 97 'Expect receiver param.rtcp.cname to be unset'); 98 } 99 100 /* 101 dictionary RTCRtpParameters { 102 DOMString transactionId; 103 sequence<RTCRtpEncodingParameters> encodings; 104 sequence<RTCRtpHeaderExtensionParameters> headerExtensions; 105 RTCRtcpParameters rtcp; 106 sequence<RTCRtpCodecParameters> codecs; 107 }; 108 109 */ 110 function validateRtpParameters(param) { 111 assert_optional_string_field(param, 'transactionId'); 112 113 assert_array_field(param, 'headerExtensions'); 114 for(const headerExt of param.headerExtensions) { 115 validateHeaderExtensionParameters(headerExt); 116 } 117 118 assert_dict_field(param, 'rtcp'); 119 validateRtcpParameters(param.rtcp); 120 121 assert_array_field(param, 'codecs'); 122 for(const codec of param.codecs) { 123 validateCodecParameters(codec); 124 } 125 } 126 127 /* 128 dictionary RTCRtpEncodingParameters { 129 boolean active; 130 unsigned long maxBitrate; 131 132 [readonly] 133 DOMString rid; 134 135 double scaleResolutionDownBy; 136 }; 137 138 */ 139 function validateEncodingParameters(encoding) { 140 assert_optional_boolean_field(encoding, 'active'); 141 assert_optional_unsigned_int_field(encoding, 'maxBitrate'); 142 143 assert_optional_string_field(encoding, 'rid'); 144 assert_optional_number_field(encoding, 'scaleResolutionDownBy'); 145 } 146 147 /* 148 dictionary RTCRtcpParameters { 149 [readonly] 150 DOMString cname; 151 152 [readonly] 153 boolean reducedSize; 154 }; 155 */ 156 function validateRtcpParameters(rtcp) { 157 assert_optional_string_field(rtcp, 'cname'); 158 assert_optional_boolean_field(rtcp, 'reducedSize'); 159 } 160 161 /* 162 dictionary RTCRtpHeaderExtensionParameters { 163 [readonly] 164 DOMString uri; 165 166 [readonly] 167 unsigned short id; 168 169 [readonly] 170 boolean encrypted; 171 }; 172 */ 173 function validateHeaderExtensionParameters(headerExt) { 174 assert_optional_string_field(headerExt, 'uri'); 175 assert_optional_unsigned_int_field(headerExt, 'id'); 176 assert_optional_boolean_field(headerExt, 'encrypted'); 177 } 178 179 /* 180 dictionary RTCRtpCodecParameters { 181 [readonly] 182 required unsigned short payloadType; 183 184 [readonly] 185 required DOMString mimeType; 186 187 [readonly] 188 required unsigned long clockRate; 189 190 [readonly] 191 unsigned short channels; 192 193 [readonly] 194 DOMString sdpFmtpLine; 195 }; 196 */ 197 function validateCodecParameters(codec) { 198 assert_unsigned_int_field(codec, 'payloadType'); 199 assert_string_field(codec, 'mimeType'); 200 assert_unsigned_int_field(codec, 'clockRate'); 201 assert_optional_unsigned_int_field(codec, 'channels'); 202 assert_optional_string_field(codec, 'sdpFmtpLine'); 203 } 204 205 // Helper function to test that modifying an encoding field should succeed 206 function test_modified_encoding(kind, field, value1, value2, desc) { 207 promise_test(async t => { 208 const pc = new RTCPeerConnection(); 209 t.add_cleanup(() => pc.close()); 210 const { 211 sender 212 } = pc.addTransceiver(kind, { 213 sendEncodings: [{ 214 [field]: value1 215 }] 216 }); 217 await doOfferAnswerExchange(t, pc); 218 219 const param1 = sender.getParameters(); 220 validateSenderRtpParameters(param1); 221 const encoding1 = param1.encodings[0]; 222 223 assert_equals(encoding1[field], value1); 224 encoding1[field] = value2; 225 226 await sender.setParameters(param1); 227 const param2 = sender.getParameters(); 228 validateSenderRtpParameters(param2); 229 const encoding2 = param2.encodings[0]; 230 assert_equals(encoding2[field], value2); 231 }, desc + ' with RTCRtpTransceiverInit'); 232 233 promise_test(async t => { 234 const pc = new RTCPeerConnection(); 235 t.add_cleanup(() => pc.close()); 236 const { 237 sender 238 } = pc.addTransceiver(kind); 239 await doOfferAnswerExchange(t, pc); 240 241 const initParam = sender.getParameters(); 242 validateSenderRtpParameters(initParam); 243 initParam.encodings[0][field] = value1; 244 await sender.setParameters(initParam); 245 246 const param1 = sender.getParameters(); 247 validateSenderRtpParameters(param1); 248 const encoding1 = param1.encodings[0]; 249 250 assert_equals(encoding1[field], value1); 251 encoding1[field] = value2; 252 253 await sender.setParameters(param1); 254 const param2 = sender.getParameters(); 255 validateSenderRtpParameters(param2); 256 const encoding2 = param2.encodings[0]; 257 assert_equals(encoding2[field], value2); 258 }, desc + ' without RTCRtpTransceiverInit'); 259 }