index.html
156 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr">
<head>
<meta name="generator" content="HTML Tidy for Linux/x86 (vers 11 February 2007), see www.w3.org" />
<title>WebRTC 1.0: Real-time Communication Between Browsers</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
/*****************************************************************
* Styles specific to WebRTC spec
*****************************************************************/
pre { white-space: pre-wrap; }
table { border-collapse: collapse; border-style: hidden hidden none hidden; }
table thead, table tbody { border-bottom: solid #90B8DE; }
table tbody th { text-align: left; }
table tbody th:first-child { border-left: solid #90B8DE; }
table td, table th { border-left: solid #90B8DE; border-right: solid #90B8DE; border-bottom: solid thin #90B8DE; vertical-align: top; padding: 0.2em; }
.note { color: green; }
.example { display: block; color: #222222; background: #FCFCFC; border-left: double; margin-left: 2em; padding-left: 1em; }
/*****************************************************************
* ReSpec CSS
* Robin Berjon (robin at berjon dot com)
* v0.05 - 2009-07-31
*****************************************************************/
/* --- INLINES --- */
em.rfc2119 {
text-transform: lowercase;
font-variant: small-caps;
font-style: normal;
color: #900;
}
h1 acronym, h2 acronym, h3 acronym, h4 acronym, h5 acronym, h6 acronym, a acronym,
h1 abbr, h2 abbr, h3 abbr, h4 abbr, h5 abbr, h6 abbr, a abbr {
border: none;
}
dfn {
font-weight: bold;
}
a.internalDFN {
color: inherit;
border-bottom: 1px solid #99c;
text-decoration: none;
}
a.externalDFN {
color: inherit;
border-bottom: 1px dotted #ccc;
text-decoration: none;
}
a.bibref {
text-decoration: none;
}
code {
color: #ff4500;
}
/* --- WEB IDL --- */
pre.idl {
border-top: 1px solid #90b8de;
border-bottom: 1px solid #90b8de;
padding: 1em;
line-height: 120%;
}
pre.idl::before {
content: "WebIDL";
display: block;
width: 150px;
background: #90b8de;
color: #fff;
font-family: initial;
padding: 3px;
font-weight: bold;
margin: -1em 0 1em -1em;
}
.idlType {
color: #ff4500;
font-weight: bold;
text-decoration: none;
}
/*.idlModule*/
/*.idlModuleID*/
/*.idlInterface*/
.idlInterfaceID, .idlDictionaryID {
font-weight: bold;
color: #005a9c;
}
.idlSuperclass {
font-style: italic;
color: #005a9c;
}
/*.idlAttribute*/
.idlAttrType, .idlFieldType, .idlMemberType {
color: #005a9c;
}
.idlAttrName, .idlFieldName, .idlMemberName {
color: #ff4500;
}
.idlAttrName a, .idlFieldName a, .idlMemberName a {
color: #ff4500;
border-bottom: 1px dotted #ff4500;
text-decoration: none;
}
/*.idlMethod*/
.idlMethType {
color: #005a9c;
}
.idlMethName {
color: #ff4500;
}
.idlMethName a {
color: #ff4500;
border-bottom: 1px dotted #ff4500;
text-decoration: none;
}
/*.idlParam*/
.idlParamType {
color: #005a9c;
}
.idlParamName {
font-style: italic;
}
.extAttr {
color: #666;
}
/*.idlConst*/
.idlConstType {
color: #005a9c;
}
.idlConstName {
color: #ff4500;
}
.idlConstName a {
color: #ff4500;
border-bottom: 1px dotted #ff4500;
text-decoration: none;
}
/*.idlException*/
.idlExceptionID {
font-weight: bold;
color: #c00;
}
.idlTypedefID, .idlTypedefType {
color: #005a9c;
}
.idlRaises, .idlRaises a.idlType, .idlRaises a.idlType code, .excName a, .excName a code {
color: #c00;
font-weight: normal;
}
.excName a {
font-family: monospace;
}
.idlRaises a.idlType, .excName a.idlType {
border-bottom: 1px dotted #c00;
}
.excGetSetTrue, .excGetSetFalse, .prmNullTrue, .prmNullFalse, .prmOptTrue, .prmOptFalse {
width: 45px;
text-align: center;
}
.excGetSetTrue, .prmNullTrue, .prmOptTrue { color: #0c0; }
.excGetSetFalse, .prmNullFalse, .prmOptFalse { color: #c00; }
.idlImplements a {
font-weight: bold;
}
dl.attributes, dl.methods, dl.constants, dl.fields, dl.dictionary-members {
margin-left: 2em;
}
.attributes dt, .methods dt, .constants dt, .fields dt, .dictionary-members dt {
font-weight: normal;
}
.attributes dt code, .methods dt code, .constants dt code, .fields dt code, .dictionary-members dt code {
font-weight: bold;
color: #000;
font-family: monospace;
}
.attributes dt code, .fields dt code, .dictionary-members dt code {
background: #ffffd2;
}
.attributes dt .idlAttrType code, .fields dt .idlFieldType code, .dictionary-members dt .idlMemberType code {
color: #005a9c;
background: transparent;
font-family: inherit;
font-weight: normal;
font-style: italic;
}
.methods dt code {
background: #d9e6f8;
}
.constants dt code {
background: #ddffd2;
}
.attributes dd, .methods dd, .constants dd, .fields dd, .dictionary-members dd {
margin-bottom: 1em;
}
table.parameters, table.exceptions {
border-spacing: 0;
border-collapse: collapse;
margin: 0.5em 0;
width: 100%;
}
table.parameters { border-bottom: 1px solid #90b8de; }
table.exceptions { border-bottom: 1px solid #deb890; }
.parameters th, .exceptions th {
color: #fff;
padding: 3px 5px;
text-align: left;
font-family: initial;
font-weight: normal;
text-shadow: #666 1px 1px 0;
}
.parameters th { background: #90b8de; }
.exceptions th { background: #deb890; }
.parameters td, .exceptions td {
padding: 3px 10px;
border-top: 1px solid #ddd;
vertical-align: top;
}
.parameters tr:first-child td, .exceptions tr:first-child td {
border-top: none;
}
.parameters td.prmName, .exceptions td.excName, .exceptions td.excCodeName {
width: 100px;
}
.parameters td.prmType {
width: 120px;
}
table.exceptions table {
border-spacing: 0;
border-collapse: collapse;
width: 100%;
}
/* --- TOC --- */
.toc a {
text-decoration: none;
}
a .secno {
color: #000;
}
/* --- TABLE --- */
table.simple {
border-spacing: 0;
border-collapse: collapse;
border-bottom: 3px solid #005a9c;
}
.simple th {
background: #005a9c;
color: #fff;
padding: 3px 5px;
text-align: left;
}
.simple th[scope="row"] {
background: inherit;
color: inherit;
border-top: 1px solid #ddd;
}
.simple td {
padding: 3px 10px;
border-top: 1px solid #ddd;
}
.simple tr:nth-child(even) {
background: #f0f6ff;
}
/* --- DL --- */
.section dd > p:first-child {
margin-top: 0;
}
.section dd > p:last-child {
margin-bottom: 0;
}
.section dd {
margin-bottom: 1em;
}
.section dl.attrs dd, .section dl.eldef dd {
margin-bottom: 0;
}
/* --- EXAMPLES --- */
pre.example {
border-top: 1px solid #ff4500;
border-bottom: 1px solid #ff4500;
padding: 1em;
margin-top: 1em;
}
pre.example::before {
content: "Example";
display: block;
width: 150px;
background: #ff4500;
color: #fff;
font-family: initial;
padding: 3px;
font-weight: bold;
margin: -1em 0 1em -1em;
}
/* --- EDITORIAL NOTES --- */
.issue {
padding: 1em;
margin: 1em 0em 0em;
border: 1px solid #f00;
background: #ffc;
}
.issue::before {
content: "Issue";
display: block;
width: 150px;
margin: -1.5em 0 0.5em 0;
font-weight: bold;
border: 1px solid #f00;
background: #fff;
padding: 3px 1em;
}
.note {
margin: 1em 0em 0em;
padding: 1em;
border: 2px solid #cff6d9;
background: #e2fff0;
}
.note::before {
content: "Note";
display: block;
width: 150px;
margin: -1.5em 0 0.5em 0;
font-weight: bold;
border: 1px solid #cff6d9;
background: #fff;
padding: 3px 1em;
}
/* --- Best Practices --- */
div.practice {
border: solid #bebebe 1px;
margin: 2em 1em 1em 2em;
}
span.practicelab {
margin: 1.5em 0.5em 1em 1em;
font-weight: bold;
font-style: italic;
}
span.practicelab { background: #dfffff; }
span.practicelab {
position: relative;
padding: 0 0.5em;
top: -1.5em;
}
p.practicedesc {
margin: 1.5em 0.5em 1em 1em;
}
@media screen {
p.practicedesc {
position: relative;
top: -2em;
padding: 0;
margin: 1.5em 0.5em -1em 1em;
}
}
/* --- SYNTAX HIGHLIGHTING --- */
pre.sh_sourceCode {
background-color: white;
color: black;
font-style: normal;
font-weight: normal;
}
pre.sh_sourceCode .sh_keyword { color: #005a9c; font-weight: bold; } /* language keywords */
pre.sh_sourceCode .sh_type { color: #666; } /* basic types */
pre.sh_sourceCode .sh_usertype { color: teal; } /* user defined types */
pre.sh_sourceCode .sh_string { color: red; font-family: monospace; } /* strings and chars */
pre.sh_sourceCode .sh_regexp { color: orange; font-family: monospace; } /* regular expressions */
pre.sh_sourceCode .sh_specialchar { color: #ffc0cb; font-family: monospace; } /* e.g., \n, \t, \\ */
pre.sh_sourceCode .sh_comment { color: #A52A2A; font-style: italic; } /* comments */
pre.sh_sourceCode .sh_number { color: purple; } /* literal numbers */
pre.sh_sourceCode .sh_preproc { color: #00008B; font-weight: bold; } /* e.g., #include, import */
pre.sh_sourceCode .sh_symbol { color: blue; } /* e.g., *, + */
pre.sh_sourceCode .sh_function { color: black; font-weight: bold; } /* function calls and declarations */
pre.sh_sourceCode .sh_cbracket { color: red; } /* block brackets (e.g., {, }) */
pre.sh_sourceCode .sh_todo { font-weight: bold; background-color: #00FFFF; } /* TODO and FIXME */
/* Predefined variables and functions (for instance glsl) */
pre.sh_sourceCode .sh_predef_var { color: #00008B; }
pre.sh_sourceCode .sh_predef_func { color: #00008B; font-weight: bold; }
/* for OOP */
pre.sh_sourceCode .sh_classname { color: teal; }
/* line numbers (not yet implemented) */
pre.sh_sourceCode .sh_linenum { display: none; }
/* Internet related */
pre.sh_sourceCode .sh_url { color: blue; text-decoration: underline; font-family: monospace; }
/* for ChangeLog and Log files */
pre.sh_sourceCode .sh_date { color: blue; font-weight: bold; }
pre.sh_sourceCode .sh_time, pre.sh_sourceCode .sh_file { color: #00008B; font-weight: bold; }
pre.sh_sourceCode .sh_ip, pre.sh_sourceCode .sh_name { color: #006400; }
/* for Prolog, Perl... */
pre.sh_sourceCode .sh_variable { color: #006400; }
/* for LaTeX */
pre.sh_sourceCode .sh_italics { color: #006400; font-style: italic; }
pre.sh_sourceCode .sh_bold { color: #006400; font-weight: bold; }
pre.sh_sourceCode .sh_underline { color: #006400; text-decoration: underline; }
pre.sh_sourceCode .sh_fixed { color: green; font-family: monospace; }
pre.sh_sourceCode .sh_argument { color: #006400; }
pre.sh_sourceCode .sh_optionalargument { color: purple; }
pre.sh_sourceCode .sh_math { color: orange; }
pre.sh_sourceCode .sh_bibtex { color: blue; }
/* for diffs */
pre.sh_sourceCode .sh_oldfile { color: orange; }
pre.sh_sourceCode .sh_newfile { color: #006400; }
pre.sh_sourceCode .sh_difflines { color: blue; }
/* for css */
pre.sh_sourceCode .sh_selector { color: purple; }
pre.sh_sourceCode .sh_property { color: blue; }
pre.sh_sourceCode .sh_value { color: #006400; font-style: italic; }
/* other */
pre.sh_sourceCode .sh_section { color: black; font-weight: bold; }
pre.sh_sourceCode .sh_paren { color: red; }
pre.sh_sourceCode .sh_attribute { color: #006400; }
</style><link href="http://www.w3.org/StyleSheets/TR/W3C-WD" rel="stylesheet" type="text/css" charset="utf-8" /></head>
<body style="display: inherit; "><div class="head"><p><a href="http://www.w3.org/"><img width="72" height="48" src="http://www.w3.org/Icons/w3c_home" alt="W3C" /></a></p><h1 class="title" id="title">WebRTC 1.0: Real-time Communication Between Browsers</h1><h2 id="w3c-working-draft-27-october-2011">W3C Working Draft 27 October 2011</h2><dl><dt>This version:</dt><dd><a href="http://www.w3.org/TR/2011/WD-webrtc-20111027/">http://www.w3.org/TR/2011/WD-webrtc-20111027/</a></dd><dt>Latest published version:</dt><dd><a href="http://www.w3.org/TR/webrtc/">http://www.w3.org/TR/webrtc/</a></dd><dt>Latest editor's draft:</dt><dd><a href="http://dev.w3.org/2011/webrtc/editor/webrtc.html">http://dev.w3.org/2011/webrtc/editor/webrtc.html</a></dd><dt>Previous version:</dt><dd>none</dd><dt>Editors:</dt><dd><span>Adam Bergkvist</span>, Ericsson</dd>
<dd><span>Daniel C. Burnett</span>, Voxeo</dd>
<dd><span>Cullen Jennings</span>, Cisco</dd>
<dd><span>Anant Narayanan</span>, Mozilla</dd>
</dl><p class="copyright">Initial Author of this Specification was Ian Hickson, Google Inc., with the following copyright statement:<br /> © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and Opera Software ASA. You are granted a license to use, reproduce and create derivative works of this document.</p> <p class="copyright">All subsequent changes since 26 July 2011 done by the W3C WebRTC Working Group are under the following <a href="http://www.w3.org/Consortium/Legal/ipr-notice#Copyright">Copyright</a>:<br />© 2011 <a href="http://www.w3.org/"><acronym title="World Wide Web Consortium">W3C</acronym></a><sup>®</sup> (<a href="http://www.csail.mit.edu/"><acronym title="Massachusetts Institute of Technology">MIT</acronym></a>, <a href="http://www.ercim.eu/"><acronym title="European Research Consortium for Informatics and Mathematics">ERCIM</acronym></a>, <a href="http://www.keio.ac.jp/">Keio</a>), All Rights Reserved. <a href="http://www.w3.org/Consortium/Legal/copyright-documents">Document use</a> rules apply.</p> <p class="copyright">For the entire publication on the W3C site the <a href="http://www.w3.org/Consortium/Legal/ipr-notice#Legal_Disclaimer">liability</a> and <a href="http://www.w3.org/Consortium/Legal/ipr-notice#W3C_Trademarks">trademark</a> rules apply.</p><hr /></div>
<div id="abstract" class="introductory section"><h2>Abstract</h2>
<p>This document defines a set of APIs that allow local media, including audio and video, to be requested from a platform, media to be sent over the network to another browser or device implementing the appropriate set of real-time protocols, and media received from another browser or device to be processed and displayed locally. This specification is being developed in conjunction with a protocol specification developed by the IETF RTCWEB group.</p>
</div><div id="sotd" class="introductory section"><h2>Status of This Document</h2><p><em>This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the <a href="http://www.w3.org/TR/">W3C technical reports index</a> at http://www.w3.org/TR/.</em></p>
<p>This document is a First Public Working Draft and is not complete.
It is subject to major changes and, while early experimentations are
encouraged, it is therefore not intended for implementation. The API
is based on preliminary work done in the WHATWG. The Web Real-Time
Communications Working Group expects this specification to evolve
significantly based on:</p>
<ul>
<li>The outcomes of ongoing exchanges in the companion RTCWEB group
at IETF to define the set of protocols that, together with this
document, will enable real-time communications in Web browsers.</li>
<li>Privacy issues that arise when exposing local capabilities and
local streams.</li>
<li>Technical discussions within the group, on the data channel in
particular.</li>
<li>Experience gained through early experimentations.</li>
<li>Feedback received from other groups and individuals.</li>
</ul>
<p>As the specification matures, the group hopes to strike the right
balance between a low-level API that would enable interested parties
to tweak potentially complex system parameters, and a more high-level
API that Web developers can use without <em>a priori</em> technical
knowledge about real-time communications.</p>
<p>This document was published by the <a href="http://www.w3.org/2011/04/webrtc/">Web Real-Time Communications Working Group</a> as a Working Draft. This document is intended to become a W3C Recommendation. If you wish to make comments regarding this document, please send them to <a href="mailto:public-webrtc@w3.org">public-webrtc@w3.org</a> (<a href="mailto:public-webrtc-request@w3.org?subject=subscribe">subscribe</a>, <a href="http://lists.w3.org/Archives/Public/public-webrtc/">archives</a>). All feedback is welcome.</p><p>Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.</p><p>This document was produced by a group operating under the <a href="http://www.w3.org/Consortium/Patent-Policy-20040205/">5 February 2004 W3C Patent Policy</a>. W3C maintains a <a href="http://www.w3.org/2004/01/pp-impl/47318/status" rel="disclosure">public list of any patent disclosures</a> made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains <a href="http://www.w3.org/Consortium/Patent-Policy-20040205/#def-essential">Essential Claim(s)</a> must disclose the information in accordance with <a href="http://www.w3.org/Consortium/Patent-Policy-20040205/#sec-Disclosure">section 6 of the W3C Patent Policy</a>.</p></div><div id="toc" class="section"><h2 class="introductory">Table of Contents</h2><ul class="toc"><li class="tocline"><a href="#intro" class="tocxref"><span class="secno">1. </span>Introduction</a></li><li class="tocline"><a href="#local-content" class="tocxref"><span class="secno">2. </span>Obtaining local multimedia content</a><ul class="toc"><li class="tocline"><a href="#local-content-definition" class="tocxref"><span class="secno">2.1 </span>Definition</a><ul class="toc"><li class="tocline"><a href="#navigatorusermedia" class="tocxref"><span class="secno">2.1.1 </span>NavigatorUserMedia</a><ul class="toc"><li class="tocline"><a href="#methods" class="tocxref"><span class="secno">2.1.1.1 </span>Methods</a></li></ul></li><li class="tocline"><a href="#mediastreamoptions" class="tocxref"><span class="secno">2.1.2 </span>MediaStreamOptions</a><ul class="toc"><li class="tocline"><a href="#attributes" class="tocxref"><span class="secno">2.1.2.1 </span>Attributes</a></li></ul></li><li class="tocline"><a href="#navigatorusermediasuccesscallback" class="tocxref"><span class="secno">2.1.3 </span>NavigatorUserMediaSuccessCallback</a><ul class="toc"><li class="tocline"><a href="#methods-1" class="tocxref"><span class="secno">2.1.3.1 </span>Methods</a></li></ul></li><li class="tocline"><a href="#navigatorusermediaerror-and-navigatorusermediaerrorcallback" class="tocxref"><span class="secno">2.1.4 </span>NavigatorUserMediaError and NavigatorUserMediaErrorCallback</a><ul class="toc"><li class="tocline"><a href="#attributes-1" class="tocxref"><span class="secno">2.1.4.1 </span>Attributes</a></li><li class="tocline"><a href="#constants" class="tocxref"><span class="secno">2.1.4.2 </span>Constants</a></li><li class="tocline"><a href="#methods-2" class="tocxref"><span class="secno">2.1.4.3 </span>Methods</a></li></ul></li></ul></li><li class="tocline"><a href="#examples" class="tocxref"><span class="secno">2.2 </span>Examples</a></li></ul></li><li class="tocline"><a href="#stream-api" class="tocxref"><span class="secno">3. </span>Stream API</a><ul class="toc"><li class="tocline"><a href="#introduction" class="tocxref"><span class="secno">3.1 </span>Introduction</a></li><li class="tocline"><a href="#interface-definitions" class="tocxref"><span class="secno">3.2 </span>Interface definitions</a><ul class="toc"><li class="tocline"><a href="#mediastream" class="tocxref"><span class="secno">3.2.1 </span>MediaStream</a><ul class="toc"><li class="tocline"><a href="#attributes-2" class="tocxref"><span class="secno">3.2.1.1 </span>Attributes</a></li><li class="tocline"><a href="#methods-3" class="tocxref"><span class="secno">3.2.1.2 </span>Methods</a></li><li class="tocline"><a href="#constants-1" class="tocxref"><span class="secno">3.2.1.3 </span>Constants</a></li></ul></li><li class="tocline"><a href="#localmediastream" class="tocxref"><span class="secno">3.2.2 </span>LocalMediaStream</a><ul class="toc"><li class="tocline"><a href="#methods-4" class="tocxref"><span class="secno">3.2.2.1 </span>Methods</a></li></ul></li><li class="tocline"><a href="#mediastreamtrack" class="tocxref"><span class="secno">3.2.3 </span>MediaStreamTrack</a><ul class="toc"><li class="tocline"><a href="#attributes-3" class="tocxref"><span class="secno">3.2.3.1 </span>Attributes</a></li></ul></li><li class="tocline"><a href="#mediastreamrecorder" class="tocxref"><span class="secno">3.2.4 </span>MediaStreamRecorder</a><ul class="toc"><li class="tocline"><a href="#methods-5" class="tocxref"><span class="secno">3.2.4.1 </span>Methods</a></li></ul></li><li class="tocline"><a href="#blobcallback" class="tocxref"><span class="secno">3.2.5 </span>BlobCallback</a><ul class="toc"><li class="tocline"><a href="#methods-6" class="tocxref"><span class="secno">3.2.5.1 </span>Methods</a></li></ul></li><li class="tocline"><a href="#url" class="tocxref"><span class="secno">3.2.6 </span>URL</a><ul class="toc"><li class="tocline"><a href="#methods-7" class="tocxref"><span class="secno">3.2.6.1 </span>Methods</a></li></ul></li></ul></li><li class="tocline"><a href="#examples-1" class="tocxref"><span class="secno">3.3 </span>Examples</a></li></ul></li><li class="tocline"><a href="#peer-to-peer-connections" class="tocxref"><span class="secno">4. </span>Peer-to-peer connections</a><ul class="toc"><li class="tocline"><a href="#peerconnection" class="tocxref"><span class="secno">4.1 </span>PeerConnection</a><ul class="toc"><li class="tocline"><a href="#attributes-4" class="tocxref"><span class="secno">4.1.1 </span>Attributes</a></li><li class="tocline"><a href="#methods-8" class="tocxref"><span class="secno">4.1.2 </span>Methods</a></li><li class="tocline"><a href="#constants-2" class="tocxref"><span class="secno">4.1.3 </span>Constants</a></li></ul></li><li class="tocline"><a href="#signalingcallback" class="tocxref"><span class="secno">4.2 </span>SignalingCallback</a><ul class="toc"><li class="tocline"><a href="#methods-9" class="tocxref"><span class="secno">4.2.1 </span>Methods</a></li></ul></li><li class="tocline"><a href="#examples-2" class="tocxref"><span class="secno">4.3 </span>Examples</a></li></ul></li><li class="tocline"><a href="#the-data-stream" class="tocxref"><span class="secno">5. </span>The data stream</a></li><li class="tocline"><a href="#garbage-collection" class="tocxref"><span class="secno">6. </span>Garbage collection</a></li><li class="tocline"><a href="#event-definitions" class="tocxref"><span class="secno">7. </span>Event definitions</a><ul class="toc"><li class="tocline"><a href="#mediastreamevent" class="tocxref"><span class="secno">7.1 </span>MediaStreamEvent</a><ul class="toc"><li class="tocline"><a href="#attributes-5" class="tocxref"><span class="secno">7.1.1 </span>Attributes</a></li><li class="tocline"><a href="#methods-10" class="tocxref"><span class="secno">7.1.2 </span>Methods</a></li></ul></li></ul></li><li class="tocline"><a href="#event-summary" class="tocxref"><span class="secno">8. </span>Event summary</a></li><li class="tocline"><a href="#application-html-peer-connection-data" class="tocxref"><span class="secno">9. </span>application/html-peer-connection-data</a></li><li class="tocline"><a href="#acknowledgements" class="tocxref"><span class="secno">A. </span>Acknowledgements</a></li><li class="tocline"><a href="#references" class="tocxref"><span class="secno">B. </span>References</a><ul class="toc"><li class="tocline"><a href="#normative-references" class="tocxref"><span class="secno">B.1 </span>Normative references</a></li><li class="tocline"><a href="#informative-references" class="tocxref"><span class="secno">B.2 </span>Informative references</a></li></ul></li></ul></div>
<div id="intro" class="informative section">
<!-- OddPage -->
<h2><span class="secno">1. </span>Introduction</h2><p><em>This section is non-normative.</em></p>
<p>There are a number of facets to video-conferencing in HTML:</p>
<ul>
<li>Getting a multimedia stream (video, audio, or both) from local devices (video
cameras, microphones, Web cams) or from prerecorded files provided by the user.</li>
<li>Recording such streams locally.</li>
<li>Connecting to remote peers using NAT-traversal technologies such as ICE, STUN,
and TURN.</li>
<li>Sending the locally-produced streams to remote peers and receiving streams from
remote peers.</li>
<li>Displaying such streams (both the locally-produced ones and the remotely-obtained
ones) locally using the <code>video</code> or <code>audio</code> elements.</li>
<li>Sending arbitrary data to remote peers.</li>
</ul>
<p>This document defines the APIs used for these features. This specification is being developed in conjunction with a protocol specification developed by the <a href="http://datatracker.ietf.org/wg/rtcweb/">IETF RTCWEB group</a>.</p>
</div>
<div id="local-content" class="section">
<!-- OddPage -->
<h2><span class="secno">2. </span>Obtaining local multimedia content</h2>
<div id="local-content-definition" class="section">
<h3><span class="secno">2.1 </span>Definition</h3>
<div id="navigatorusermedia" class="section">
<h4><span class="secno">2.1.1 </span>NavigatorUserMedia</h4>
<pre class="idl"><span class="idlInterface" id="idl-def-NavigatorUserMedia">[<span class="extAttr">NoInterfaceObject</span>]
interface <span class="idlInterfaceID">NavigatorUserMedia</span> {
<span class="idlMethod"> <span class="idlMethType"><a>void</a></span> <span class="idlMethName"><a href="#widl-NavigatorUserMedia-getUserMedia-void-MediaStreamOptions-options-NavigatorUserMediaSuccessCallback-successCallback-NavigatorUserMediaErrorCallback-errorCallback">getUserMedia</a></span> (<span class="idlParam"><span class="idlParamType"><a href="#idl-def-MediaStreamOptions" class="idlType"><code>MediaStreamOptions</code></a>?</span> <span class="idlParamName">options</span></span>, <span class="idlParam"><span class="idlParamType"><a href="#idl-def-NavigatorUserMediaSuccessCallback" class="idlType"><code>NavigatorUserMediaSuccessCallback</code></a>?</span> <span class="idlParamName">successCallback</span></span>, <span class="idlParam">optional <span class="idlParamType"><a href="#idl-def-NavigatorUserMediaErrorCallback" class="idlType"><code>NavigatorUserMediaErrorCallback</code></a>?</span> <span class="idlParamName">errorCallback</span></span>);</span>
};</span>
</pre><div id="methods" class="section"><h5><span class="secno">2.1.1.1 </span>Methods</h5><dl class="methods"><dt id="widl-NavigatorUserMedia-getUserMedia-void-MediaStreamOptions-options-NavigatorUserMediaSuccessCallback-successCallback-NavigatorUserMediaErrorCallback-errorCallback"><code>getUserMedia</code></dt><dd>
<p>Prompts the user for permission to use their Web cam or other video or audio
input.</p>
<p>The <var title="">options</var> argument is an object of type
<code title="">MediaStreamOptions</code>. The object can contain
the following boolean properties:
</p>
<dl>
<dt>"<code title="">audio</code>"</dt>
<dd>The provided media needs to include audio data.</dd>
<dt>"<code title="">video</code>"</dt>
<dd>The provided media needs to include video data.</dd>
</dl>
<p>If the user accepts, the <var title="">successCallback</var> is invoked, with a
suitable <code><a href="#localmediastream">LocalMediaStream</a></code> object as
its argument.</p>
<p>If the user declines, the <var title="">errorCallback</var> (if any) is
invoked.</p>
<p>When the <a href="#widl-NavigatorUserMedia-getUserMedia-void-MediaStreamOptions-options-NavigatorUserMediaSuccessCallback-successCallback-NavigatorUserMediaErrorCallback-errorCallback">
<code>getUserMedia()</code></a> method is called, the user agent must run the
following steps:</p>
<ol>
<li>
<p>Let <var title="">options</var> be the method's first argument.</p>
</li>
<li>
<p>Let <var title="">successCallback</var> be the callback indicated by the
method's second argument.</p>
</li>
<li>
<p>Let <var title="">errorCallback</var> be the callback indicated by the
method's third argument, if any, or null otherwise.</p>
</li>
<li>
<p>If <var title="">successCallback</var> is null, abort these steps.</p>
</li>
<!-- we could throw an exception instead (that's
why the method doesn't return until later: so that we can add an
exception here, or for /options/ below, without changing the
algorithm) -->
<li>
<p>Let <var title="">audio</var> be true.</p>
</li>
<li>
<p>Let <var title="">video</var> be true.</p>
</li>
<li>
<p>If the <var title="">audio</var> property in <var title="">options</var>
is present and set to false, let <var title="">audio</var> be false.</p>
</li>
<li>
<p>If the <var title="">video</var> property in <var title="">options</var>
is present and set to false, let <var title="">video</var> be false.</p>
</li>
<li>
<p>If both <var title="">audio</var> and <var title="">video</var> are still
false, then throw a <code>NOT_SUPPORTED_ERR</code> exception and abort these
steps.</p>
</li>
<li>
<p>Return, and run the remaining steps asynchronously.</p>
</li>
<li>
<p>Optionally, e.g. based on a previously-established user preference, for
security reasons, or due to platform limitations, jump to the step labeled
<em>failure</em> below.</p>
</li>
<li>
<p>Prompt the user in a user-agent-specific manner for permission to provide
the entry script's origin with a <code><a href="#localmediastream">LocalMediaStream</a></code> object representing a media
stream.</p>
<p>If <var title="">audio</var> is true, then the provided media should include
an audio track. If <var title="">audio</var> is false, then the provided media
must not include an audio track.</p>
<p>If <var title="">video</var> is true, then the provided media should include
a video track. If <var title="">video</var> is false, then the provided media
must not include a video track.</p>
<p>User agents are encouraged to default to using the user's primary or system
default camera and/or microphone (as appropriate) to generate the media stream.
User agents may allow users to use any media source, including pre-recorded
media files.</p>
<p>User agents may wish to offer the user more control over the provided media.
For example, a user agent could offer to enable a camera light or flash, or to
change settings such as the frame rate or shutter speed.</p>
<p>If the user grants permission to use local recording devices, user agents
are encouraged to include a prominent indicator that the devices are "hot"
(i.e. an "on-air" or "recording" indicator).</p>
<p>If the user denies permission, jump to the step labeled <em>failure</em>
below. If the user never responds, this algorithm stalls on this step.</p>
</li>
<li>
<p>Let <var title="">stream</var> be the <code><a href="#localmediastream">LocalMediaStream</a></code> object for which the user
granted permission.</p>
</li>
<li>
<p>Queue a task to invoke <var title="">successCallback</var> with
<var title="">stream</var> as its argument.</p>
</li>
<li>
<p>Abort these steps.</p>
</li>
<li>
<p><em>Failure</em>: If <var title="">errorCallback</var> is null, abort these
steps.</p>
</li>
<li>
<p>Let <var title="">error</var> be a new <code><a href="#navigatorusermediaerror-and-navigatorusermediaerrorcallback">NavigatorUserMediaError</a></code> object whose
<code title="dom-NavigatorUserMediaError-code"><a href="#widl-NavigatorUserMediaError-code">code</a></code> attribute has the numeric
value 1 (<code title="dom-NavigatorUserMediaError-PERMISSION_DENIED"><a href="#widl-NavigatorUserMediaError-PERMISSION_DENIED">PERMISSION_DENIED</a></code>).</p>
</li>
<li>
<p>Queue a task to invoke <var title="">errorCallback</var> with
<var title="">error</var> as its argument.</p>
</li>
</ol>
<p>The task source for these <span title="concept-task">tasks</span>
is the user interaction task source.</p>
<table class="parameters"><tr><th>Parameter</th><th>Type</th><th>Nullable</th><th>Optional</th><th>Description</th></tr><tr><td class="prmName">options</td><td class="prmType"><code><a href="#idl-def-MediaStreamOptions" class="idlType"><code>MediaStreamOptions</code></a></code></td><td class="prmNullTrue">✔</td><td class="prmOptFalse">✘</td><td class="prmDesc"></td></tr><tr><td class="prmName">successCallback</td><td class="prmType"><code><a href="#idl-def-NavigatorUserMediaSuccessCallback" class="idlType"><code>NavigatorUserMediaSuccessCallback</code></a></code></td><td class="prmNullTrue">✔</td><td class="prmOptFalse">✘</td><td class="prmDesc"></td></tr><tr><td class="prmName">errorCallback</td><td class="prmType"><code><a href="#idl-def-NavigatorUserMediaErrorCallback" class="idlType"><code>NavigatorUserMediaErrorCallback</code></a></code></td><td class="prmNullTrue">✔</td><td class="prmOptTrue">✔</td><td class="prmDesc"></td></tr></table><div><em>No exceptions.</em></div><div><em>Return type: </em><code><a>void</a></code></div></dd></dl></div>
<pre class="idl"><span class="idlImplements"><a>Navigator</a> implements <a href="#idl-def-NavigatorUserMedia" class="idlType"><code>NavigatorUserMedia</code></a>;</span></pre><div class="idlImplementsDesc"><p>All instances of the <code><a>Navigator</a></code> type are defined to also implement the <a href="#idl-def-NavigatorUserMedia" class="idlType"><code>NavigatorUserMedia</code></a> interface.</p></div>
</div>
<div id="mediastreamoptions" class="section">
<h4><span class="secno">2.1.2 </span>MediaStreamOptions</h4>
<pre class="idl"><span class="idlInterface" id="idl-def-MediaStreamOptions">[<span class="extAttr">NoInterfaceObject</span>]
interface <span class="idlInterfaceID">MediaStreamOptions</span> {
<span class="idlAttribute"> attribute <span class="idlAttrType"><a>boolean</a></span> <span class="idlAttrName"><a href="#widl-MediaStreamOptions-audio">audio</a></span>;</span>
<span class="idlAttribute"> attribute <span class="idlAttrType"><a>boolean</a></span> <span class="idlAttrName"><a href="#widl-MediaStreamOptions-video">video</a></span>;</span>
};</span>
</pre><div id="attributes" class="section"><h5><span class="secno">2.1.2.1 </span>Attributes</h5><dl class="attributes"><dt id="widl-MediaStreamOptions-audio"><code>audio</code> of type <span class="idlAttrType"><a>boolean</a></span></dt><dd>Set to false if an audio track is not required, default is true<div><em>No exceptions.</em></div></dd><dt id="widl-MediaStreamOptions-video"><code>video</code> of type <span class="idlAttrType"><a>boolean</a></span></dt><dd>Set to false if a video track is not required, default is true<div><em>No exceptions.</em></div></dd></dl></div>
</div>
<div id="navigatorusermediasuccesscallback" class="section">
<h4><span class="secno">2.1.3 </span>NavigatorUserMediaSuccessCallback</h4>
<pre class="idl"><span class="idlInterface" id="idl-def-NavigatorUserMediaSuccessCallback">[<span class="extAttr">Callback=FunctionOnly, NoInterfaceObject</span>]
interface <span class="idlInterfaceID">NavigatorUserMediaSuccessCallback</span> {
<span class="idlMethod"> <span class="idlMethType"><a>void</a></span> <span class="idlMethName"><a href="#widl-NavigatorUserMediaSuccessCallback-handleEvent-void-LocalMediaStream-stream">handleEvent</a></span> (<span class="idlParam"><span class="idlParamType"><a href="#idl-def-LocalMediaStream" class="idlType"><code>LocalMediaStream</code></a></span> <span class="idlParamName">stream</span></span>);</span>
};</span>
</pre><div id="methods-1" class="section"><h5><span class="secno">2.1.3.1 </span>Methods</h5><dl class="methods"><dt id="widl-NavigatorUserMediaSuccessCallback-handleEvent-void-LocalMediaStream-stream"><code>handleEvent</code></dt><dd>(Explanation of handleEvent TBD)<table class="parameters"><tr><th>Parameter</th><th>Type</th><th>Nullable</th><th>Optional</th><th>Description</th></tr><tr><td class="prmName">stream</td><td class="prmType"><code><a href="#idl-def-LocalMediaStream" class="idlType"><code>LocalMediaStream</code></a></code></td><td class="prmNullFalse">✘</td><td class="prmOptFalse">✘</td><td class="prmDesc"></td></tr></table><div><em>No exceptions.</em></div><div><em>Return type: </em><code><a>void</a></code></div></dd></dl></div>
</div>
<div id="navigatorusermediaerror-and-navigatorusermediaerrorcallback" class="section">
<h4><span class="secno">2.1.4 </span>NavigatorUserMediaError and NavigatorUserMediaErrorCallback</h4>
<pre class="idl"><span class="idlInterface" id="idl-def-NavigatorUserMediaError">[<span class="extAttr">NoInterfaceObject</span>]
interface <span class="idlInterfaceID">NavigatorUserMediaError</span> {
<span class="idlConst"> const <span class="idlConstType"><a>unsigned short</a></span> <span class="idlConstName"><a href="#widl-NavigatorUserMediaError-PERMISSION_DENIED">PERMISSION_DENIED</a></span> = <span class="idlConstValue">1</span>;</span>
<span class="idlAttribute"> readonly attribute <span class="idlAttrType"><a>unsigned short</a></span> <span class="idlAttrName"><a href="#widl-NavigatorUserMediaError-code">code</a></span>;</span>
};</span>
</pre><div id="attributes-1" class="section"><h5><span class="secno">2.1.4.1 </span>Attributes</h5><dl class="attributes"><dt id="widl-NavigatorUserMediaError-code"><code>code</code> of type <span class="idlAttrType"><a>unsigned short</a></span>, readonly</dt><dd>Returns the current error's error code. At this time, this will always be 1, for
which the constant <code title="dom-NavigatorUserMediaError-PERMISSION_DENIED"><a href="#widl-NavigatorUserMediaError-PERMISSION_DENIED">PERMISSION_DENIED</a></code> is
defined.<div><em>No exceptions.</em></div></dd></dl></div><div id="constants" class="section"><h5><span class="secno">2.1.4.2 </span>Constants</h5><dl class="constants"><dt id="widl-NavigatorUserMediaError-PERMISSION_DENIED"><code>PERMISSION_DENIED</code> of type <span class="idlConstType"><a>unsigned short</a></span></dt><dd>The user denied the page permission to use the user's media devices.</dd></dl></div>
<pre class="idl"><span class="idlInterface" id="idl-def-NavigatorUserMediaErrorCallback">[<span class="extAttr">Callback=FunctionOnly, NoInterfaceObject</span>]
interface <span class="idlInterfaceID">NavigatorUserMediaErrorCallback</span> {
<span class="idlMethod"> <span class="idlMethType"><a>void</a></span> <span class="idlMethName"><a href="#widl-NavigatorUserMediaErrorCallback-handleEvent-void-NavigatorUserMediaError-error">handleEvent</a></span> (<span class="idlParam"><span class="idlParamType"><a href="#idl-def-NavigatorUserMediaError" class="idlType"><code>NavigatorUserMediaError</code></a></span> <span class="idlParamName">error</span></span>);</span>
};</span>
</pre><div id="methods-2" class="section"><h5><span class="secno">2.1.4.3 </span>Methods</h5><dl class="methods"><dt id="widl-NavigatorUserMediaErrorCallback-handleEvent-void-NavigatorUserMediaError-error"><code>handleEvent</code></dt><dd>(Explanation of handleEvent TBD)<table class="parameters"><tr><th>Parameter</th><th>Type</th><th>Nullable</th><th>Optional</th><th>Description</th></tr><tr><td class="prmName">error</td><td class="prmType"><code><a href="#idl-def-NavigatorUserMediaError" class="idlType"><code>NavigatorUserMediaError</code></a></code></td><td class="prmNullFalse">✘</td><td class="prmOptFalse">✘</td><td class="prmDesc"></td></tr></table><div><em>No exceptions.</em></div><div><em>Return type: </em><code><a>void</a></code></div></dd></dl></div>
</div>
</div>
<div id="examples" class="section">
<h3><span class="secno">2.2 </span>Examples</h3>
<div class="example">
<p>A voice chat feature in a game could attempt to get access to the user's
microphone by calling the API as follows:</p>
<pre><script>
navigator.getUserMedia('audio', gotAudio);
function gotAudio(stream) {
// ... use 'stream' ...
}
</script>
</pre>
</div>
<div class="example">
<p>A video-conferencing system would ask for both audio and video:</p>
<pre><script>
function beginCall() {
navigator.getUserMedia('audio,video user', gotStream);
}
function gotStream(stream) {
// ... use 'stream' ...
}
</script>
</pre>
</div>
</div>
</div>
<div id="stream-api" class="section">
<!-- OddPage -->
<h2><span class="secno">3. </span>Stream API</h2>
<div id="introduction" class="section">
<h3><span class="secno">3.1 </span>Introduction</h3>
<p>The <code><a href="#mediastream">MediaStream</a></code> interface is used to
represent streams of media data, typically (but not necessarily) of audio and/or video
content, e.g. from a local camera or a remote site. The data from a <code><a href="#mediastream">MediaStream</a></code> object does not necessarily have a canonical
binary form; for example, it could just be "the video currently coming from the user's
video camera". This allows user agents to manipulate media streams in whatever fashion
is most suitable on the user's platform.</p>
<p>Each <code><a href="#mediastream">MediaStream</a></code> object can represent zero
or more tracks, in particular audio and video tracks. Tracks can contain multiple
channels of parallel data; for example a single audio track could have nine channels of
audio data to represent a 7.2 surround sound audio track.</p>
<p>Each track represented by a <code><a href="#mediastream">MediaStream</a></code>
object has a corresponding <code><a href="#mediastreamtrack">MediaStreamTrack</a></code> object.</p>
<p>A <code><a href="#mediastream">MediaStream</a></code> object has an input and an
output. The input depends on how the object was created: a <code><a href="#localmediastream">LocalMediaStream</a></code> object generated by a <code title="dom-navigator-getUserMedia"><a href="#widl-NavigatorUserMedia-getUserMedia-void-MediaStreamOptions-options-NavigatorUserMediaSuccessCallback-successCallback-NavigatorUserMediaErrorCallback-errorCallback">getUserMedia()</a></code> call, for instance, might take
its input from the user's local camera, while a <code><a href="#mediastream">MediaStream</a></code> created by a <code><a href="#peerconnection">PeerConnection</a></code> object will take as input the data received
from a remote peer. The output of the object controls how the object is used, e.g. what
is saved if the object is written to a file, what is displayed if the object is used in
a <code>video</code> element, or indeed what is transmitted to a remote peer if the
object is used with a <code><a href="#peerconnection">PeerConnection</a></code>
object.</p>
<p>Each track in a <code><a href="#mediastream">MediaStream</a></code> object can be
disabled, meaning that it is muted in the object's output. All tracks are initially
enabled.</p>
<p id="finishedMute">A <code><a href="#mediastream">MediaStream</a></code> can be
<a href="#concept-stream-finished" title="concept-stream-finished">finished</a>,
indicating that its inputs have forever stopped providing data. When a <code><a href="#mediastream">MediaStream</a></code> object is finished, all its tracks are muted
regardless of whether they are enabled or disabled.</p>
<p>The output of a <code><a href="#mediastream">MediaStream</a></code> object must
correspond to the tracks in its input. Muted audio tracks must be replaced with
silence. Muted video tracks must be replaced with blackness.</p>
<p>A new <code><a href="#mediastream">MediaStream</a></code> object can be created
from a list of <code><a href="#mediastreamtrack">MediaStreamTrack</a></code> objects
using the <code title="dom-MediaStream"><a href="#dom-mediastream">MediaStream()</a>
</code> constructor. The list of <code><a href="#mediastreamtrack">MediaStreamTrack</a>
</code> objects can be the track list of another stream, a subset of the track list of
a stream or a composition of <code><a href="#mediastreamtrack">MediaStreamTrack</a>
</code> objects from different <code><a href="#mediastream">MediaStream</a></code> objects.
</p><p><img alt="" src="images/media-stream-1.png" /></p>
<!-- no alt since
it's all described in the previous paragraphs: this is just a
summary -->
<!--
c.clearRect(0, 0, 640, 480);
c.save();
try {
with (c) {
save();
strokeStyle = '#AA0000';
lineWidth = 20;
beginPath();
moveTo(50,98);
lineTo(550, 98);
stroke();
}
mediaStream(c,50,10, true);
} finally {
c.restore();
}
function cameraIcon(c,x,y) {
with (c) { save(); try {
translate(x,y);
fillRect(-10,-10,20,20);
beginPath();
moveTo(7,0);
lineTo(20,-10);
lineTo(20,10);
fill();
font = '100 8px "Press Start 2P", sans-serif';
textAlign = 'center';
textBaseline = 'top';
fillText('Camera', 4, 15);
} finally { restore(); } }
}
function mediaStream(c,x,y,vid) {
with (c) {
save();
translate(x-10,y-97);
// cable
fillStyle = 'black';
font = '100 10px "Press Start 2P", sans-serif';
textAlign = 'right';
fillText('Input', 95, 170);
textAlign = 'left';
fillText('Output', 407, 170);
// media stream
fillStyle = '#EE8800';
strokeStyle = '#FFCC00';
lineWidth = 6;
fillRect(100,100,300,170);
strokeRect(100,100,300,170);
fillStyle = 'black';
font = '900 12px "Press Start 2P", sans-serif';
textAlign = 'left';
fillText('MediaStream', 110, 123);
// tracks
textAlign = 'left';
strokeStyle = '#CC3300';
fillStyle = '#FFFF00';
lineWidth = 4;
globalAlpha = vid ? 1 : 0.4;
fillRect(120,140,100,110);
strokeRect(120,140,100,110);
globalAlpha = 1;
fillRect(238,140,100,110);
strokeRect(238,140,100,110);
fillStyle = 'black';
font = '900 10px "Press Start 2P", sans-serif';
globalAlpha = vid ? 1 : 0.4;
fillText('Track', 123, 155);
fillText('(video)', 123, 170);
globalAlpha = 1;
fillText('Track', 241, 155);
fillText('(stereo', 241, 170);
fillText(' audio)', 241, 185);
// channels
strokeStyle = '#999999';
fillStyle = '#FFFFFF';
lineWidth = 2;
fillRect(245,191,86,23);
strokeRect(245,191,86,23);
fillRect(245,220,86,23);
strokeRect(245,220,86,23);
fillStyle = 'black';
font = '100 8px "Press Start 2P", sans-serif';
textAlign = 'left';
textBaseline = 'alphabetic';
fillText('left', 249, 202);
fillText('channel', 249, 211);
fillText('right', 249, 231);
fillText('channel', 249, 240);
// track check marks
fillStyle = 'black';
font = '900 35px "Lucida Grande", sans-serif';
textAlign = 'center';
textBaseline = 'middle';
fillText(vid ? '\u2713' : '\u2716', 220, 245);
fillText('\u2713', 338, 245);
restore();
}
}
-->
<p>The ability to duplicate a <code><a href="#mediastream">MediaStream</a></code>, i.e.
create a new <code><a href="#mediastream">MediaStream</a></code> object from the track
list of an existing stream, allows for greater control since separate <code>
<a href="#mediastream">MediaStream</a></code> instances can be manipulated and consumed
individually. This can be used, for instance, in a video-conferencing scenario to display
the local video from the user's camera and microphone in a local monitor, while only
transmitting the audio to the remote peer (e.g. in response to the user using a "video
mute" feature). Combining tracks from different <code><a href="#mediastream">MediaStream</a>
</code> objects into a new <code><a href="#mediastream">MediaStream</a></code> makes it
possible to, e.g., record selected tracks from a conversation involving several <code>
<a href="#mediastream">MediaStream</a></code> objects with a single <code>
<a href="#mediastreamrecorder">MediaStreamRecorder</a></code>.</p>
<!--
c.clearRect(0, 0, 640, 480);
c.save();
try {
with (c) {
save();
strokeStyle = '#AA0000';
lineWidth = 20;
beginPath();
moveTo(50,98);
lineTo(550, 98);
lineTo(550, 210);
lineTo(50, 210);
lineTo(50, 320);
lineTo(550, 320);
lineTo(550,420);
stroke();
beginPath();
moveTo(50,320);
lineTo(50,420);
stroke();
restore();
fillStyle = 'black';
font = '100 10px "Press Start 2P", sans-serif';
textAlign = 'center';
fillText('<video>', 50, 440);
fillText('PeerConnection', 550, 440);
font = '100 8px "Press Start 2P", sans-serif';
}
cameraIcon(c,25,98)
mediaStream(c,50,10, true);
mediaStream(c,50,233, false);
with (c) {
font = '100 8px "Press Start 2P", sans-serif';
textAlign = 'left';
textBaseline = 'middle';
fillStyle = 'gray';
fillText('from', 4, 130);
fillText('getUserMedia()', 4, 140);
fillText('via URL.getObjectURL()', 4, 450);
textAlign = 'center';
fillText('via addStream()', 550, 450);
}
} finally {
c.restore();
}
function cameraIcon(c,x,y) {
with (c) { save(); try {
translate(x,y);
fillRect(-10,-10,20,20);
beginPath();
moveTo(7,0);
lineTo(20,-10);
lineTo(20,10);
fill();
font = '100 8px "Press Start 2P", sans-serif';
textAlign = 'center';
textBaseline = 'top';
fillText('Camera', 4, 15);
} finally { restore(); } }
}
function mediaStream(c,x,y,vid) {
with (c) {
save();
translate(x-10,y-97);
// cable
fillStyle = 'black';
font = '100 10px "Press Start 2P", sans-serif';
textAlign = 'right';
fillText('Input', 95, 170);
textAlign = 'left';
fillText('Output', 407, 170);
// media stream
fillStyle = '#EE8800';
strokeStyle = '#FFCC00';
lineWidth = 6;
fillRect(100,100,300,170);
strokeRect(100,100,300,170);
fillStyle = 'black';
font = '900 12px "Press Start 2P", sans-serif';
textAlign = 'left';
fillText(!vid ? 'MediaStream' : 'LocalMediaStream', 110, 123);
// tracks
textAlign = 'left';
strokeStyle = '#CC3300';
fillStyle = '#FFFF00';
lineWidth = 4;
globalAlpha = vid ? 1 : 0.4;
fillRect(120,140,100,110);
strokeRect(120,140,100,110);
globalAlpha = 1;
fillRect(238,140,100,110);
strokeRect(238,140,100,110);
fillStyle = 'black';
font = '900 10px "Press Start 2P", sans-serif';
globalAlpha = vid ? 1 : 0.4;
fillText('Track', 123, 155);
fillText('(video)', 123, 170);
globalAlpha = 1;
fillText('Track', 241, 155);
fillText('(stereo', 241, 170);
fillText(' audio)', 241, 185);
// channels
strokeStyle = '#999999';
fillStyle = '#FFFFFF';
lineWidth = 2;
fillRect(245,191,86,23);
strokeRect(245,191,86,23);
fillRect(245,220,86,23);
strokeRect(245,220,86,23);
fillStyle = 'black';
font = '100 8px "Press Start 2P", sans-serif';
textAlign = 'left';
textBaseline = 'alphabetic';
fillText('left', 249, 202);
fillText('channel', 249, 211);
fillText('right', 249, 231);
fillText('channel', 249, 240);
// track check marks
fillStyle = 'black';
font = '900 35px "Lucida Grande", sans-serif';
textAlign = 'center';
textBaseline = 'middle';
fillText(vid ? '\u2713' : '\u2716', 220, 245);
fillText('\u2713', 338, 245);
restore();
}
}
-->
<p>The <code><a href="#localmediastream">LocalMediaStream</a></code> interface is used
when the user agent is generating the stream's data (e.g. from a camera or streaming it
from a local video file). It allows authors to control individual tracks during the
generation of the content, e.g. to allow the user to temporarily disable a local camera
during a video-conference chat.</p>
<p>When a <code><a href="#localmediastream">LocalMediaStream</a></code> object is being
generated from a local file (as opposed to a live audio/video source), the user agent
should stream the data from the file in real time, not all at once. This reduces the
ease with which pages can distinguish live video from pre-recorded video, which can
help protect the user's privacy.</p>
</div>
<div id="interface-definitions" class="section">
<h3><span class="secno">3.2 </span>Interface definitions</h3>
<div id="mediastream" class="section">
<h4><span class="secno">3.2.1 </span>MediaStream</h4>
<p>The <dfn id="dom-mediastream" title="dom-MediaStream"><code>MediaStream(<var title="">trackList</var>)</code></dfn> constructor must return a new <code><a href="#mediastream">MediaStream</a></code> object with a newly generated label.
A new <code><a href="#mediastreamtrack">MediaStreamTrack</a></code> object is created
for every unique underlying media source in <var title="">trackList</var> and appended
to the new <code><a href="#mediastream">MediaStream</a></code> object's track list
according to the track ordering constraints.
</p><p>A <code><a href="#mediastream">MediaStream</a></code> object is said to <em>end</em>
when the user agent learns that no more data will ever be forthcoming for this
stream.</p>
<p>When a <code><a href="#mediastream">MediaStream</a></code> object ends for any
reason (e.g. because the user rescinds the permission for the page to use the local
camera, or because the data comes from a finite file and the file's end has been
reached and the user has not requested that it be looped, or because the stream comes
from a remote peer and the remote peer has permanently stopped sending data, it is
said to be <dfn id="concept-stream-finished" title="concept-stream-finished">finished
</dfn>. When this happens for any reason other than the <code title="dom-MediaStream-stop">
<a href="#dom-mediastream-stop">stop()</a></code> method being invoked, the user agent must
queue a task that runs the following steps:</p>
<ol>
<li>
<p>If the object's <code title="dom-MediaStream-readyState"><a href="#dom-mediastream-readystate">readyState</a></code> attribute has the value
<code title="dom-MediaStream-ENDED"><a href="#widl-MediaStream-ENDED">ENDED</a></code> (2) already, then abort these steps. (The
<code title="dom-MediaStream-stop"><a href="#dom-mediastream-stop">stop()</a></code> method was probably called just before
the stream stopped for other reasons, e.g. the user clicked an in-page stop button
and then the user-agent-provided stop button.)</p>
</li>
<li>
<p>Set the object's <code title="dom-MediaStream-readyState"><a href="#dom-mediastream-readystate">readyState</a></code> attribute to <code title="dom-MediaStream-ENDED"><a href="#widl-MediaStream-ENDED">ENDED</a></code> (2).</p>
</li>
<li>
<p>Fire a simple event named <code title="event-MediaStream-ended"><a href="#event-mediastream-ended">ended</a></code> at
the object.</p>
</li>
</ol>
<p>As soon as a <code><a href="#mediastream">MediaStream</a></code> object is <a href="#concept-stream-finished" title="concept-stream-finished">finished</a>, the stream's
tracks start outputting only silence and/or blackness, as appropriate, <a href="#finishedMute">as defined earlier</a>.</p>
<p>If the end of the stream was reached due to a user request, the task
source for this <span title="concept-task">task</span> is the user
interaction task source. Otherwise the task source for this
<span title="concept-task">task</span> is the networking task source.</p>
<pre class="idl"><span class="idlInterface" id="idl-def-MediaStream">[<span class="extAttr">Constructor (in MediaStreamTrackList trackList)</span>]
interface <span class="idlInterfaceID">MediaStream</span> {
<span class="idlAttribute"> readonly attribute <span class="idlAttrType"><a>DOMString</a></span> <span class="idlAttrName"><a href="#widl-MediaStream-label">label</a></span>;</span>
<span class="idlAttribute"> readonly attribute <span class="idlAttrType"><a id="mediastreamtracklist">MediaStreamTrackList</a></span> <span class="idlAttrName"><a href="#widl-MediaStream-tracks">tracks</a></span>;</span>
<span class="idlMethod"> <span class="idlMethType"><a href="#idl-def-MediaStreamRecorder" class="idlType"><code>MediaStreamRecorder</code></a></span> <span class="idlMethName"><a href="#widl-MediaStream-record-MediaStreamRecorder">record</a></span> ();</span>
<span class="idlConst"> const <span class="idlConstType"><a>unsigned short</a></span> <span class="idlConstName"><a href="#widl-MediaStream-LIVE">LIVE</a></span> = <span class="idlConstValue">1</span>;</span>
<span class="idlConst"> const <span class="idlConstType"><a>unsigned short</a></span> <span class="idlConstName"><a href="#widl-MediaStream-ENDED">ENDED</a></span> = <span class="idlConstValue">2</span>;</span>
<span class="idlAttribute"> readonly attribute <span class="idlAttrType"><a>unsigned short</a></span> <span class="idlAttrName"><a href="#widl-MediaStream-readyState">readyState</a></span>;</span>
<span class="idlAttribute"> attribute <span class="idlAttrType"><a>Function</a>?</span> <span class="idlAttrName"><a href="#widl-MediaStream-onended">onended</a></span>;</span>
};</span>
</pre><div id="attributes-2" class="section"><h5><span class="secno">3.2.1.1 </span>Attributes</h5><dl class="attributes"><dt id="widl-MediaStream-label"><code>label</code> of type <span class="idlAttrType"><a>DOMString</a></span>, readonly</dt><dd>Returns a label that is unique to this stream, so that streams can be recognized
after they are sent through the <code><a href="#peerconnection">PeerConnection</a></code> API.<div><em>No exceptions.</em></div></dd><dt id="widl-MediaStream-onended"><code>onended</code> of type <span class="idlAttrType"><a>Function</a></span>, nullable</dt><dd>This event handler, of type <code title="event-MediaStream-ended"><a href="#event-mediastream-ended">ended</a></code>, must be supported by all objects
implementing the <code><a href="#mediastream">MediaStream</a></code> interface.<div><em>No exceptions.</em></div></dd><dt id="widl-MediaStream-readyState"><code>readyState</code> of type <span class="idlAttrType"><a>unsigned short</a></span>, readonly</dt><dd>
<p>The <dfn id="dom-mediastream-readystate" title="dom-MediaStream-readyState"><code>readyState</code></dfn> attribute represents the
state of the stream. It must return the value to which the user agent last set it
(as defined below). It can have the following values: <dfn id="dfn-live">LIVE</dfn> or
<dfn id="dfn-ended">ENDED</dfn>.</p>
<p>When a <code><a href="#mediastream">MediaStream</a></code> object is created,
its <code title="dom-MediaStream-readyState"><a href="#dom-mediastream-readystate">readyState</a></code> attribute must be set to
<code title="dom-MediaStream-LIVE"><a href="#widl-MediaStream-LIVE">LIVE</a></code>
(1), unless it is being created using the <code title="dom-MediaStream"><a href="#dom-mediastream">MediaStream()</a></code> constructor whose argument is a list of
<code><a href="#mediastreamtrack">MediaStreamTrack</a></code> objects whose underlying
media sources will never produce any more data, in which case the <code><a href="#mediastream">MediaStream</a></code> object must be created with its <code title="dom-MediaStream-readyState"><a href="#dom-mediastream-readystate">readyState</a></code> attribute set to <code title="dom-MediaStream-ENDED"><a href="#widl-MediaStream-ENDED">ENDED</a></code> (2).</p>
<div><em>No exceptions.</em></div></dd><dt id="widl-MediaStream-tracks"><code>tracks</code> of type <span class="idlAttrType"><a>MediaStreamTrackList</a></span>, readonly</dt><dd>
<p>Returns a <code><a href="#mediastreamtracklist">MediaStreamTrackList</a></code>
object representing the tracks that can be enabled and disabled.</p>
<p>A <code><a href="#mediastream">MediaStream</a></code> can have multiple audio
and video sources (e.g. because the user has multiple microphones, or because the
real source of the stream is a media resource with
many media tracks). The stream represented by a <code><a href="#mediastream">MediaStream</a></code> thus has zero or more tracks.</p>
<p>The <dfn id="dom-mediastream-tracks" title="dom-MediaStream-tracks"><code>tracks</code></dfn> attribute must return an
<span title="array host objects">array host object</span> for objects of type
<code><a href="#mediastreamtrack">MediaStreamTrack</a></code> that is <em>fixed
length</em> and <em>read only</em>. The same object must be returned each time the
attribute is accessed. [<cite><a class="bibref" rel="biblioentry" href="#bib-WEBIDL">WEBIDL</a></cite>]</p>
<p>The array must contain the <code><a href="#mediastreamtrack">MediaStreamTrack</a></code> objects that correspond to the the
tracks of the stream. The relative order of all tracks in a user agent must be
stable. All audio tracks must precede all video tracks. Tracks that come from a
media resource whose format defines an order must be
in the order defined by the format; tracks that come from a media resource whose format does not define an order must be
in the relative order in which the tracks are declared in that media resource. Within these constraints, the order is
user-agent defined.</p>
<div><em>No exceptions.</em></div></dd></dl></div><div id="methods-3" class="section"><h5><span class="secno">3.2.1.2 </span>Methods</h5><dl class="methods"><dt id="widl-MediaStream-record-MediaStreamRecorder"><code>record</code></dt><dd>
<p>Begins recording the stream. The returned <code><a href="#mediastreamrecorder">MediaStreamRecorder</a></code> object provides access to the
recorded data.</p>
<p>When the <dfn id="dom-mediastream-record" title="dom-MediaStream-record"><code>record()</code></dfn> method is invoked, the user
agent must return a new <code><a href="#mediastreamrecorder">MediaStreamRecorder</a></code> object associated with the
stream.</p>
<div><em>No parameters.</em></div><div><em>No exceptions.</em></div><div><em>Return type: </em><code><a href="#idl-def-MediaStreamRecorder" class="idlType"><code>MediaStreamRecorder</code></a></code></div></dd></dl></div><div id="constants-1" class="section"><h5><span class="secno">3.2.1.3 </span>Constants</h5><dl class="constants"><dt id="widl-MediaStream-ENDED"><code>ENDED</code> of type <span class="idlConstType"><a>unsigned short</a></span></dt><dd>The stream has finished (the user agent is no longer receiving or generating
data, and will never receive or generate more data for this stream).</dd><dt id="widl-MediaStream-LIVE"><code>LIVE</code> of type <span class="idlConstType"><a>unsigned short</a></span></dt><dd>The stream is active (the user agent is making a best-effort attempt to receive
or generate data in real time).</dd></dl></div>
<pre class="idl"><span class="idlImplements"><a href="#idl-def-MediaStream" class="idlType"><code>MediaStream</code></a> implements <a>EventTarget</a>;</span></pre><div class="idlImplementsDesc"><p>All instances of the <code><a href="#idl-def-MediaStream" class="idlType"><code>MediaStream</code></a></code> type are defined to also implement the <a>EventTarget</a> interface.</p></div>
</div>
<div id="localmediastream" class="section">
<h4><span class="secno">3.2.2 </span>LocalMediaStream</h4>
<pre class="idl"><span class="idlInterface" id="idl-def-LocalMediaStream">interface <span class="idlInterfaceID">LocalMediaStream</span> : <span class="idlSuperclass"><a href="#idl-def-MediaStream" class="idlType"><code>MediaStream</code></a></span> {
<span class="idlMethod"> <span class="idlMethType"><a>void</a></span> <span class="idlMethName"><a href="#widl-LocalMediaStream-stop-void">stop</a></span> ();</span>
};</span>
</pre><div id="methods-4" class="section"><h5><span class="secno">3.2.2.1 </span>Methods</h5><dl class="methods"><dt id="widl-LocalMediaStream-stop-void"><code>stop</code></dt><dd>
<p>When a <code><a href="#localmediastream">LocalMediaStream</a></code> object's
<dfn id="dom-mediastream-stop" title="dom-MediaStream-stop"><code>stop()</code></dfn> method is invoked, the user agent
must queue a task that runs the following steps:</p>
<ol>
<li>
<p>If the object's <code title="dom-MediaStream-readyState"><a href="#dom-mediastream-readystate">readyState</a></code> attribute is in the
<code title="dom-MediaStream-ENDED"><a href="#widl-MediaStream-ENDED">ENDED</a></code> (2) state, then abort these
steps.</p>
</li>
<li>
<p>Permanently stop the generation of data for the stream. If the data is being
generated from a live source (e.g. a microphone or camera), and no other stream
is being generated from a live source, then the user agent should remove any
active "on-air" indicator. If the data is being generated from a prerecorded
source (e.g. a video file), any remaining content in the file is ignored. The
stream is <a href="#concept-stream-finished" title="concept-stream-finished">finished</a>. The stream's tracks start outputting
only silence and/or blackness, as appropriate, <a href="#finishedMute">as
defined earlier</a>.</p>
</li>
<li>
<p>Set the object's <code title="dom-MediaStream-readyState"><a href="#dom-mediastream-readystate">readyState</a></code> attribute to <code title="dom-MediaStream-ENDED"><a href="#widl-MediaStream-ENDED">ENDED</a></code>
(2).</p>
</li>
<li>
<p>Fire a simple event named <code title="event-MediaStream-ended"><a href="#event-mediastream-ended">ended</a></code>
at the object.</p>
</li>
</ol>
<p>The task source for the <span title="concept-task">tasks</span>
queued for the <code title="dom-MediaStream-stop"><a href="#dom-mediastream-stop">stop()</a></code> method is the DOM manipulation task
source.</p>
<div><em>No parameters.</em></div><div><em>No exceptions.</em></div><div><em>Return type: </em><code><a>void</a></code></div></dd></dl></div>
</div>
<div id="mediastreamtrack" class="section">
<h4><span class="secno">3.2.3 </span>MediaStreamTrack</h4>
<pre class="idl"><span class="idlTypedef" id="idl-def-MediaStreamTrackList">typedef <span class="idlTypedefType"><a href="#idl-def-MediaStreamTrack" class="idlType"><code>MediaStreamTrack</code></a></span>[] <span class="idlTypedefID">MediaStreamTrackList</span>;</span></pre><div class="idlTypedefDesc">Throughout this specification, the identifier <span class="idlTypedefID">MediaStreamTrackList</span> is used to refer to the array of <span class="idlTypedefType"><a href="#idl-def-MediaStreamTrack" class="idlType"><code>MediaStreamTrack</code></a></span> type.</div>
<pre class="idl"><span class="idlInterface" id="idl-def-MediaStreamTrack">interface <span class="idlInterfaceID">MediaStreamTrack</span> {
<span class="idlAttribute"> readonly attribute <span class="idlAttrType"><a>DOMString</a></span> <span class="idlAttrName"><a href="#widl-MediaStreamTrack-kind">kind</a></span>;</span>
<span class="idlAttribute"> readonly attribute <span class="idlAttrType"><a>DOMString</a></span> <span class="idlAttrName"><a href="#widl-MediaStreamTrack-label">label</a></span>;</span>
<span class="idlAttribute"> attribute <span class="idlAttrType"><a>boolean</a></span> <span class="idlAttrName"><a href="#widl-MediaStreamTrack-enabled">enabled</a></span>;</span>
};</span>
</pre><div id="attributes-3" class="section"><h5><span class="secno">3.2.3.1 </span>Attributes</h5><dl class="attributes"><dt id="widl-MediaStreamTrack-enabled"><code>enabled</code> of type <span class="idlAttrType"><a>boolean</a></span></dt><dd>
<p>The <dfn id="dom-mediastreamtrack-enabled" title="dom-MediaStreamTrack-enabled"><code>MediaStreamTrack.enabled</code></dfn>
attribute, on getting, must return the last value to which it was set. On setting,
it must be set to the new value, and then, if the <code><a href="#mediastreamtrack">MediaStreamTrack</a></code> object is still associated with a
track, must enable the track if the new value is true, and disable it
otherwise.</p>
<p class="note">Thus, after a <code><a href="#mediastreamtrack">MediaStreamTrack</a></code> is disassociated from its track,
its <code title="dom-MediaStreamTrack-enabled"><a href="#dom-mediastreamtrack-enabled">enabled</a></code> attribute still changes value
when set, it just doesn't do anything with that new value.</p>
<div><em>No exceptions.</em></div></dd><dt id="widl-MediaStreamTrack-kind"><code>kind</code> of type <span class="idlAttrType"><a>DOMString</a></span>, readonly</dt><dd>
<p>The <dfn id="dom-mediastreamtrack-kind" title="dom-MediaStreamTrack-kind"><code>MediaStreamTrack.kind</code></dfn> attribute must
return the string "<code title="""">audio</code>" if the object's corresponding
track is or was an audio track, "<code title="""">video</code>" if the
corresponding track is or was a video track, and a user-agent defined string
otherwise.</p>
<div><em>No exceptions.</em></div></dd><dt id="widl-MediaStreamTrack-label"><code>label</code> of type <span class="idlAttrType"><a>DOMString</a></span>, readonly</dt><dd>
<p>When a <code><a href="#localmediastream">LocalMediaStream</a></code> object is
created, the user agent must generate a globally unique identifier string, and must
initialize the object's <code title="dom-MediaStream-label"><a href="#dom-mediastream-label">label</a></code> attribute to that string. Such strings
must only use characters in the ranges U+0021, U+0023 to U+0027, U+002A to U+002B,
U+002D to U+002E, U+0030 to U+0039, U+0041 to U+005A, U+005E to U+007E, and must be
36 characters long.</p>
<!-- UUIDs have 36 characters
including hyphens; the ranges above comes from RFC4574 (the a=label:
thing in SDP) -->
<p>When a <code><a href="#mediastream">MediaStream</a></code> is created to
represent a stream obtained from a remote peer, the <code title="dom-MediaStream-label"><a href="#dom-mediastream-label">label</a></code> attribute
is initialized from information provided by the remote source.</p>
<!-- described below
-->
<p>When a <code><a href="#mediastream">MediaStream</a></code> is created from
another using the <code title="dom-MediaStream"><a href="#dom-mediastream">MediaStream()</a></code> constructor, the <code title="dom-MediaStream-label"><a href="#dom-mediastream-label">label</a></code> attribute
is initialized to a newly generated value.</p>
<!-- described above -->
<p>The <dfn id="dom-mediastream-label" title="dom-MediaStream-label"><code>label</code></dfn> attribute must return the value to
which it was initialized when the object was created.</p>
<p class="note">The label of a <code><a href="#mediastream">MediaStream</a></code>
object is unique to the source of the stream, but that does not mean it is not
possible to end up with duplicates. For example, a locally
generated stream could be sent from one user to a remote peer using <code><a href="#peerconnection">PeerConnection</a></code>, and then sent back to the original
user in the same manner, in which case the original user will have multiple streams
with the same label (the locally-generated one and the one received from the remote
peer).</p>
<p>User agents may label audio and video sources (e.g. "Internal microphone" or
"External USB Webcam"). The <dfn id="dom-mediastreamtrack-label" title="dom-MediaStreamTrack-label"><code>MediaStreamTrack.label</code></dfn> attribute
must return the label of the object's corresponding track, if any. If the
corresponding track has or had no label, the attribute must instead return the
empty string.</p>
<p class="note">Thus the <code title="dom-MediaStreamTrack-kind"><a href="#dom-mediastreamtrack-kind">kind</a></code> and <code title="dom-MediaStreamTrack-label"><a href="#dom-mediastreamtrack-label">label</a></code>
attributes do not change value, even if the <code><a href="#mediastreamtrack">MediaStreamTrack</a></code> object is disassociated from its
corresponding track.</p>
<div><em>No exceptions.</em></div></dd></dl></div>
</div>
<div id="mediastreamrecorder" class="section">
<h4><span class="secno">3.2.4 </span>MediaStreamRecorder</h4>
<pre class="idl"><span class="idlInterface" id="idl-def-MediaStreamRecorder">interface <span class="idlInterfaceID">MediaStreamRecorder</span> {
<span class="idlMethod"> <span class="idlMethType"><a>voice</a></span> <span class="idlMethName"><a href="#widl-MediaStreamRecorder-getRecordedData-voice-BlobCallback-callback">getRecordedData</a></span> (<span class="idlParam"><span class="idlParamType"><a href="#idl-def-BlobCallback" class="idlType"><code>BlobCallback</code></a>?</span> <span class="idlParamName">callback</span></span>);</span>
};</span>
</pre><div id="methods-5" class="section"><h5><span class="secno">3.2.4.1 </span>Methods</h5><dl class="methods"><dt id="widl-MediaStreamRecorder-getRecordedData-voice-BlobCallback-callback"><code>getRecordedData</code></dt><dd>
<p>Creates a <code>Blob</code> of the recorded data, and invokes the provided
callback with that <code>Blob</code>.</p>
<p>When the <dfn id="dom-mediastreamrecorder-getrecordeddata" title="dom-MediaStreamRecorder-getRecordedData"><code>getRecordedData()</code></dfn>
method is called, the user agent must run the following steps:</p>
<ol>
<li>
<p>Let <var title="">callback</var> be the callback indicated by the method's
first argument.</p>
</li>
<li>
<p>If <var title="">callback</var> is null, abort these steps.</p>
</li>
<!-- we could throw an exception instead (that's
why the method doesn't return until later: so that we can add an
exception here without changing the algorithm) -->
<li>
<p>Let <var title="">data</var> be the data that was streamed by the
<code><a href="#mediastream">MediaStream</a></code> object from which the
<code><a href="#mediastreamrecorder">MediaStreamRecorder</a></code> was created
since the creation of the <code><a href="#mediastreamrecorder">MediaStreamRecorder</a></code> object.</p>
</li>
<li>
<p>Return, and run the remaining steps asynchronously.</p>
</li>
<li>
<p>Generate a file that containing <var title="">data</var> in a format
supported by the user agent for use in <code>audio</code> and
<code>video</code> elements.</p>
</li>
<li>
<p>Let <var title="">blob</var> be a <code>Blob</code> object representing the
contents of the file generated in the previous step. [<cite><a class="bibref" rel="biblioentry" href="#bib-FILE-API">FILE-API</a></cite>]</p>
</li>
<li>
<p>Queue a task to invoke <var title="">callback</var> with
<var title="">blob</var> as its argument.</p>
</li>
</ol>
<p class="note">The <code title="dom-MediaStreamRecorder-getRecordedData"><a href="#dom-mediastreamrecorder-getrecordeddata">getRecordedData()</a></code> method can
be called multiple times on one <code><a href="#mediastreamrecorder">MediaStreamRecorder</a></code> object; each time, it will
create a new file as if this was the first time the method was being called. In
particular, the method does not stop or reset the recording when the method is
called.</p>
<table class="parameters"><tr><th>Parameter</th><th>Type</th><th>Nullable</th><th>Optional</th><th>Description</th></tr><tr><td class="prmName">callback</td><td class="prmType"><code><a href="#idl-def-BlobCallback" class="idlType"><code>BlobCallback</code></a></code></td><td class="prmNullTrue">✔</td><td class="prmOptFalse">✘</td><td class="prmDesc"></td></tr></table><div><em>No exceptions.</em></div><div><em>Return type: </em><code><a>voice</a></code></div></dd></dl></div>
</div>
<div id="blobcallback" class="section">
<h4><span class="secno">3.2.5 </span>BlobCallback</h4>
<pre class="idl"><span class="idlInterface" id="idl-def-BlobCallback">[<span class="extAttr">Callback=FunctionOnly, NoInterfaceObject</span>]
interface <span class="idlInterfaceID">BlobCallback</span> {
<span class="idlMethod"> <span class="idlMethType"><a>void</a></span> <span class="idlMethName"><a href="#widl-BlobCallback-handleEvent-void-Blob-blob">handleEvent</a></span> (<span class="idlParam"><span class="idlParamType"><a>Blob</a></span> <span class="idlParamName">blob</span></span>);</span>
};</span>
</pre><div id="methods-6" class="section"><h5><span class="secno">3.2.5.1 </span>Methods</h5><dl class="methods"><dt id="widl-BlobCallback-handleEvent-void-Blob-blob"><code>handleEvent</code></dt><dd>Def TBD<table class="parameters"><tr><th>Parameter</th><th>Type</th><th>Nullable</th><th>Optional</th><th>Description</th></tr><tr><td class="prmName">blob</td><td class="prmType"><code><a>Blob</a></code></td><td class="prmNullFalse">✘</td><td class="prmOptFalse">✘</td><td class="prmDesc"></td></tr></table><div><em>No exceptions.</em></div><div><em>Return type: </em><code><a>void</a></code></div></dd></dl></div>
</div>
<div id="url" class="section">
<h4><span class="secno">3.2.6 </span>URL</h4>
<p><em>Note that the following is actually only a partial interface, but ReSpec does
not yet support that.</em></p>
<pre class="idl"><span class="idlInterface" id="idl-def-URL">interface <span class="idlInterfaceID">URL</span> {
<span class="idlMethod"> <span class="idlMethType"><a>static DOMString</a></span> <span class="idlMethName"><a href="#widl-URL-createObjectURL-static-DOMString-MediaStream-stream">createObjectURL</a></span> (<span class="idlParam"><span class="idlParamType"><a href="#idl-def-MediaStream" class="idlType"><code>MediaStream</code></a></span> <span class="idlParamName">stream</span></span>);</span>
};</span>
</pre><div id="methods-7" class="section"><h5><span class="secno">3.2.6.1 </span>Methods</h5><dl class="methods"><dt id="widl-URL-createObjectURL-static-DOMString-MediaStream-stream"><code>createObjectURL</code></dt><dd>
<p>Mints a <a href="#blob-url">Blob URL</a> to refer to the given <code><a href="#mediastream">MediaStream</a></code>.</p>
<p>When the <dfn id="dom-url-createobjecturl" title="dom-URL-createObjectURL"><code>createObjectURL()</code></dfn> method is called
with a <code><a href="#mediastream">MediaStream</a></code> argument, the user agent
must return a unique <a href="#blob-url">Blob URL</a> for the given <code><a href="#mediastream">MediaStream</a></code>. [<cite><a class="bibref" rel="biblioentry" href="#bib-FILE-API">FILE-API</a></cite>]</p>
<p>For audio and video streams, the data exposed on that stream must be in a format
supported by the user agent for use in <code>audio</code> and <code>video</code>
elements.</p>
<p class="bookkeeping">A <dfn id="blob-url">Blob URL</dfn> is the same as what the
File API specification calls a Blob URI, except that anything in the
definition of that feature that refers to <code>File</code> and <code>Blob</code>
objects is hereby extended to also apply to <code><a href="#mediastream">MediaStream</a></code> and <code><a href="#localmediastream">LocalMediaStream</a></code> objects.</p>
<table class="parameters"><tr><th>Parameter</th><th>Type</th><th>Nullable</th><th>Optional</th><th>Description</th></tr><tr><td class="prmName">stream</td><td class="prmType"><code><a href="#idl-def-MediaStream" class="idlType"><code>MediaStream</code></a></code></td><td class="prmNullFalse">✘</td><td class="prmOptFalse">✘</td><td class="prmDesc"></td></tr></table><div><em>No exceptions.</em></div><div><em>Return type: </em><code><a>static DOMString</a></code></div></dd></dl></div>
</div>
</div>
<div id="examples-1" class="section">
<h3><span class="secno">3.3 </span>Examples</h3>
<div class="example">
<p>This sample code exposes a button. When clicked, the button is disabled and the
user is prompted to offer a stream. The user can cause the button to be re-enabled by
providing a stream (e.g. giving the page access to the local camera) and then
disabling the stream (e.g. revoking that access).</p>
<pre><input type="button" value="Start" onclick="start()" id="startBtn">
<script>
var startBtn = document.getElementById('startBtn');
function start() {
navigator.getUserMedia('audio,video', gotStream);
startBtn.disabled = true;
}
function gotStream(stream) {
stream.onended = function () {
startBtn.disabled = false;
}
}
</script>
</pre>
</div>
<div class="example">
<p>This example allows people to record a short audio message and upload it to the
server. This example even shows rudimentary error handling.</p>
<pre><input type="button" value="⚫" onclick="msgRecord()" id="recBtn">
<input type="button" value="◼" onclick="msgStop()" id="stopBtn" disabled>
<p id="status">To start recording, press the ⚫ button.</p>
<script>
var recBtn = document.getElementById('recBtn');
var stopBtn = document.getElementById('stopBtn');
function report(s) {
document.getElementById('status').textContent = s;
}
function msgRecord() {
report('Attempting to access microphone...');
navigator.getUserMedia('audio', gotStream, noStream);
recBtn.disabled = true;
}
var msgStream, msgStreamRecorder;
function gotStream(stream) {
report('Recording... To stop, press to ◼ button.');
msgStream = stream;
msgStreamRecorder = stream.record();
stopBtn.disabled = false;
stream.onended = function () {
msgStop();
}
}
function msgStop() {
report('Creating file...');
stopBtn.disabled = true;
msgStream.onended = null;
msgStream.stop();
msgStreamRecorder.getRecordedData(msgSave);
}
function msgSave(blob) {
report('Uploading file...');
var x = new XMLHttpRequest();
x.open('POST', 'uploadMessage');
x.send(blob);
x.onload = function () {
report('Done! To record a new message, press the ⚫ button.');
recBtn.disabled = false;
};
x.onerror = function () {
report('Failed to upload message. To try recording a message again, press the ⚫ button.');
recBtn.disabled = false;
};
}
function noStream() {
report('Could not obtain access to your microphone. To try again, press the ⚫ button.');
recBtn.disabled = false;
}
</script>
</pre>
</div>
<div class="example">
<p>This example allows people to take photos of themselves from the local video
camera.</p>
<pre><article>
<style scoped>
video { transform: scaleX(-1); }
p { text-align: center; }
</style>
<h1>Snapshot Kiosk</h1>
<section id="splash">
<p id="errorMessage">Loading...</p>
</section>
<section id="app" hidden>
<p><video id="monitor" autoplay></video> <canvas id="photo"></canvas>
<p><input type=button value="&#x1F4F7;" onclick="snapshot()">
</section>
<script>
navigator.getUserMedia('video user', gotStream, noStream);
var video = document.getElementById('monitor');
var canvas = document.getElementById('photo');
function gotStream(stream) {
video.src = URL.getObjectURL(stream);
video.onerror = function () {
stream.stop();
};
stream.onended = noStream;
video.onloadedmetadata = function () {
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
document.getElementById('splash').hidden = true;
document.getElementById('app').hidden = false;
};
}
function noStream() {
document.getElementById('errorMessage').textContent = 'No camera available.';
}
function snapshot() {
canvas.getContext('2d').drawImage(video, 0, 0);
}
</script>
</article>
</pre>
</div>
</div>
</div>
<div id="peer-to-peer-connections" class="section">
<!-- OddPage -->
<h2><span class="secno">4. </span>Peer-to-peer connections</h2>
<p>A <code><a href="#peerconnection">PeerConnection</a></code> allows two users to
communicate directly, browser-to-browser. Communications are coordinated via a
signaling channel provided by script in the page via the server, e.g. using
<code>XMLHttpRequest</code>.</p>
<p>Calling "new <code title="dom-PeerConnection"><a href="#dom-peerconnection">PeerConnection</a></code>(<var title="">configuration</var>,
<var title="">signalingCallback</var>)" creates a <code><a href="#peerconnection">PeerConnection</a></code> object.</p>
<p>The <var title="">configuration</var> string gives the address of a STUN or TURN
server to use to establish the connection. [<cite><a class="bibref" rel="biblioentry" href="#bib-STUN">STUN</a></cite>] [<cite><a class="bibref" rel="biblioentry" href="#bib-TURN">TURN</a></cite>]</p>
<p>The allowed formats for this string are:</p>
<dl>
<dt>"<code title=""""><var title="">TYPE</var> 203.0.113.2:3478</code>"</dt>
<dd>
<p>Indicates a specific IP address and port for the server.</p>
</dd>
<dt>"<code title=""""><var title="">TYPE</var> relay.example.net:3478</code>""</dt>
<dd>
<p>Indicates a specific host and port for the server; the user agent will look up
the IP address in DNS.</p>
</dd>
<dt>"<code title=""""><var title="">TYPE</var> example.net</code>""</dt>
<dd>
<p>Indicates a specific domain for the server; the user agent will look up the IP
address and port in DNS.</p>
</dd>
</dl>
<p>The "<code title=""""><var title="">TYPE</var></code>" is one of:</p>
<dl>
<dt><code title="""">STUN</code></dt>
<dd>Indicates a STUN server</dd>
<dt><code title="""">STUNS</code></dt>
<dd>Indicates a STUN server that is to be contacted using a TLS session.</dd>
<dt><code title="""">TURN</code></dt>
<dd>Indicates a TURN server</dd>
<dt><code title="""">TURNS</code></dt>
<dd>Indicates a TURN server that is to be contacted using a TLS session.</dd>
</dl>
<p>The <var title="">signalingCallback</var> argument is a method that will be invoked
when the user agent needs to send a message to the other host over the signaling
channel. When the callback is invoked, convey its first argument (a string) to the
other peer using whatever method is being used by the Web application to relay
signaling messages. (Messages returned from the other peer are provided back to the
user agent using the <code title="dom-PeerConnection-processSignalingMessage"><a href="#dom-peerconnection-processsignalingmessage">processSignalingMessage()</a></code>
method.)</p>
<p>A <code><a href="#peerconnection">PeerConnection</a></code> object has an associated
<dfn id="peerconnection-signaling-callback"><code>PeerConnection</code> signaling
callback</dfn>, a <dfn id="peerconnection-ice-agent"><code>PeerConnection</code> ICE
Agent</dfn>,
a <dfn id="peerconnection-readiness-state"><code>PeerConnection</code>
readiness state</dfn> and an <dfn id="ice-started-flag">SDP Agent</dfn>. These
are initialized when the object is created.</p>
<p>When the <dfn id="dom-peerconnection" title="dom-PeerConnection"><code>PeerConnection()</code></dfn> constructor is invoked, the
user agent must run the following steps. This algorithm has a synchronous
section (which is triggered as part of the event loop algorithm).
Steps in the synchronous section are marked with ⌛.</p>
<ol>
<li>
<p>Let <var title="">serverConfiguration</var> be the constructor's first
argument.</p>
</li>
<li>
<p>Let <var title="">signalingCallback</var> be the constructor's second
argument.</p>
</li>
<li>
<p>Let <var title="">connection</var> be a newly created <code><a href="#peerconnection">PeerConnection</a></code> object.</p>
</li>
<li>
<p>Create an ICE Agent and let <var title="">connection</var>'s <a href="#peerconnection-ice-agent"><code>PeerConnection</code> ICE Agent</a> be that ICE
Agent. [<cite><a class="bibref" rel="biblioentry" href="#bib-ICE">ICE</a></cite>]</p>
</li>
<li>
<p>If <var title="">serverConfiguration</var> contains a U+000A LINE FEED (LF)
character or a U+000D CARRIAGE RETURN (CR) character (or both), remove all
characters from <var title="">serverConfiguration</var> after the first such
character.</p>
</li>
<li>
<p><span title="split a string on spaces">Split <var title="">serverConfiguration</var> on spaces</span> to obtain <var title="">configuration
components</var>.</p>
</li>
<li>
<p>If <var title="">configuration components</var> has two or more components, and
the first component is a case-sensitive match for one of the following
strings:</p>
<ul class="breif">
<li>"<code title="">STUN</code>"</li>
<li>"<code title="">STUNS</code>"</li>
<li>"<code title="">TURN</code>"</li>
<li>"<code title="">TURNS</code>"</li>
</ul>
<p>...then run the following substeps:</p>
<ol>
<li>
<p>Let <var title="">server type</var> be STUN if the first component of
<var title="">configuration components</var> is '<code title="">STUN</code>' or
'<code title="">STUNS</code>', and TURN otherwise (the first component of
<var title="">configuration components</var> is "<code title="">TURN</code>" or
"<code title="">TURNS</code>").</p>
</li>
<li>
<p>Let <var title="">secure</var> be true if the first component of <var title="">configuration components</var> is "<code title="">STUNS</code>" or
"<code title="">TURNS</code>", and false otherwise.</p>
</li>
<li>
<p>Let <var title="">host</var> be the contents of the second component of
<var title="">configuration components</var> up to the character before the
first U+003A COLON character (:), if any, or the entire string otherwise.</p>
</li>
<li>
<p>Let <var title="">port</var> be the contents of the second component of
<var title="">configuration components</var> from the character after the first
U+003A COLON character (:) up to the end, if any, or the empty string
otherwise.</p>
</li>
<li>
<p>Configure the <a href="#peerconnection-ice-agent"><code>PeerConnection</code> ICE Agent</a>'s STUN or
TURN server as follows:</p>
<ul>
<li>If <var title="">server type</var> is STUN, the server is a STUN server.
Otherwise, <var title="">server type</var> is TURN and the server is a TURN
server.</li>
<li>If <var title="">secure</var> is true, the server is to be contacted
using TLS-over-TCP, otherwise, it is to be contacted using UDP.</li>
<li>The IP address, host name, or domain name of the server is <var title="">host</var>.</li>
<li>The port to use is <var title="">port</var>. If this is the empty string,
then only a domain name is configured (and the ICE Agent will use DNS SRV
requests to determine the IP address and port).</li>
<li>The long-term username for the STUN or TURN server is the <span title="ASCII serialization of an origin">ASCII serialization</span> of the
entry script's origin; the long-term password is
the empty string.</li>
</ul>
<p>If the given IP address, host name, domain name, or port are invalid, then
the user agent must act as if no STUN or TURN server is configured.</p>
</li>
</ol>
</li>
<li>
<p>Let the <var title="">connection</var>'s <a href="#peerconnection-signaling-callback"><code>PeerConnection</code> signaling
callback</a> be <var title="">signalingCallback</var>.</p>
</li>
<li>
<p>Set <var title="">connection</var>'s <a href="#peerconnection-readiness-state"><code>PeerConnection</code> readiness state</a>
to <code title="dom-PeerConnection-NEW"><a href="#widl-PeerConnection-NEW">NEW</a></code> (0).</p>
</li>
<li>
<p>Set <var title="">connection</var>'s <a href="#peerconnection-readiness-state"><code>PeerConnection</code> ice state </a>
to <code title="dom-PeerConnection-NEW"><a href="#widl-PeerConnection-NEW">NEW</a></code> (0).</p>
</li>
<li>
<p>Set <var title="">connection</var>'s <a href="#peerconnection-readiness-state"><code>PeerConnection</code> sdp state </a>
to <code title="dom-PeerConnection-NEW"><a href="#widl-PeerConnection-NEW">NEW</a></code> (0).</p>
</li>
<li>
<p>Let <var title="">connection</var>'s <code title="dom-PeerConnection-localStreams"><a href="#widl-PeerConnection-localStreams">localStreams</a></code> attribute be an empty
read-only <code><a href="#mediastream">MediaStream</a></code> array.
[<cite><a class="bibref" rel="biblioentry" href="#bib-WEBIDL">WEBIDL</a></cite>]</p>
</li>
<li>
<p>Let <var title="">connection</var>'s <code title="dom-PeerConnection-remoteStreams"><a href="#widl-PeerConnection-remoteStreams">remoteStreams</a></code> attribute be an empty
read-only <code><a href="#mediastream">MediaStream</a></code> array.
[<cite><a class="bibref" rel="biblioentry" href="#bib-WEBIDL">WEBIDL</a></cite>]</p>
</li>
<li>
<p>Return <var title="">connection</var>, but continue these steps
asynchronously.</p>
</li>
<li>
<p>Await a stable state. The synchronous section consists
of the remaining steps of this algorithm. (Steps in <span title="synchronous section">synchronous sections</span> are marked with ⌛.)</p>
</li>
<li> <p>⌛ If the ice state is set to NEW, it must queue a task to start
gathering ICE address and set the ice state to ICEGATHERING.</p> </li>
<li> <p>⌛ Once the ICE address gathering is complete, if there are any streams in
localStreams, the SDP Agent will send the initial the SDP offer. The
initial SDP offer <em class="rfc2119" title="must">must</em> contain both the ICE candidate information
as well as the SDP to represent the media descriptions for all the
streams in localStreams. </p> </li>
</ol>
<p> During the lifetime of the peerConnection object, the following
procedures are followed: </p>
<ol>
<li> <p> If a local media stream has been added and an SDP offer needs to
be sent, and the ICE state is not NEW or ICEGATHERING, and the SDP Agent
state is NEW or SDPIDLE, then send and queue a task to send an SDP offer and
change the SPD state to SDP Waiting.</p> </li>
<li> <p> If an SDP offer has been received, and the SDP state is NEW or
SDPIDLE, pass the ICE candidates from the SDP offer to the ICE Agent and
change it state to ICECHECKING. Construct an appropriate SDP answer, update the
remote streams, queue a task to send the SDP offer, and set the SDPAgent
state to SDPIDLE. </p> </li>
<li> <p> At the point the sdpState changes from NEW to some other
state, the readyState changes to NEGOTIATING. </p> </li>
<li> <p> If the ICE Agent finds a candidates that froms a valid
connection, the ICE state is changed to ICECONNECTED </p> </li>
<li> <p> If the ICE Agent finishes checking all candidates, if a
connection has been found, the ice state is changed to ICECOMPLETED and if
not connection has been found it is changed to ICEFAILED. </p> </li>
<li> <p> If the iceState is ICECONNECTED or ICECOMPLETED and the
SDP stat is SDPIDLE, the readyState is set to ACTIVE. </p> </li>
<li> <p> If the iceState is ICEFAILED, a task is queued to calls the close method. </p> </li>
<li> <p> The close method will cause the system to wait until the sdpStat
is SDPIDLE then it will send an SDP offer terminating all media and change
the readyState to CLOSING as well as stop all ICE process and change the
iceState to ICE_CLOSED. Once an SDP anser to this offer is received, the
readyState will be changed to CLOSED. </p> </li>
</ol>
<p>User agents may negotiate any codec and any resolution, bitrate, or other quality
metric. User agents are encouraged to initially negotiate for the native resolution of
the stream. For streams that are then rendered (using a <code>video</code> element),
user agents are encouraged to renegotiate for a resolution that matches the rendered
display size.</p>
<p class="note">Starting with the native resolution means that if the Web application
notifies its peer of the native resolution as it starts sending data, and the peer
prepares its <code>video</code> element accordingly, there will be no need for a
renegotiation once the stream is flowing.</p>
<p>All SDP media descriptions for streams represented by <code><a href="#mediastream">MediaStream</a></code> objects must include a label attribute
("<code title="">a=label:</code>") whose value is the value of the <code><a href="#mediastream">MediaStream</a></code> object's <code title="dom-MediaStream-label"><a href="#dom-mediastream-label">label</a></code> attribute.
[<cite><a class="bibref" rel="biblioentry" href="#bib-SDP">SDP</a></cite>] [<cite><a class="bibref" rel="biblioentry" href="#bib-SDPLABEL">SDPLABEL</a></cite>]</p>
<p><a href="#peerconnection"><code>PeerConnection</code>s</a> must not generate any
candidates for media streams whose media descriptions do not have a label attribute
("<code title="">a=label:</code>"). [<cite><a class="bibref" rel="biblioentry" href="#bib-ICE">ICE</a></cite>] [<cite><a class="bibref" rel="biblioentry" href="#bib-SDP">SDP</a></cite>] [<cite><a class="bibref" rel="biblioentry" href="#bib-SDPLABEL">SDPLABEL</a></cite>]</p>
<p>When a user agent starts receiving media for a component and a candidate was
provided for that component by a <a href="#peerconnection"><code>PeerConnection</code></a>, the user agent must follow these
steps:</p>
<ol>
<li>
<p>Let <var title="">connection</var> be the <code><a href="#peerconnection">PeerConnection</a></code> expecting this media.</p>
</li>
<li>
<p>If there is already a <code><a href="#mediastream">MediaStream</a></code> object
for the media stream to which this component belongs, then associate the component
with that media stream and abort these steps. (Some media streams have multiple
components; this API does not expose the role of these individual components in
ICE.)</p>
</li>
<li>
<p>Create a <code><a href="#mediastream">MediaStream</a></code> object to represent
the media stream. Set its <code title="dom-MediaStream-label"><a href="#dom-mediastream-label">label</a></code> attribute to the value of the SDP Label
attribute for that component's media stream.</p>
</li>
<li>
<p>Queue a task to run the following substeps:</p>
<ol>
<li>
<p>If the <var title="">connection</var>'s <a href="#peerconnection-readiness-state"><code>PeerConnection</code> readiness
state</a> is <code title="dom-PeerConnection-CLOSED"><a href="#widl-PeerConnection-CLOSED">CLOSED</a></code> (3), abort these steps.</p>
</li>
<!-- close() was probably called just before this
task ran -->
<li>
<p>Add the newly created <code><a href="#mediastream">MediaStream</a></code>
object to the end of <var title="">connection</var>'s <code title="dom-PeerConnection-remoteStreams"><a href="#widl-PeerConnection-remoteStreams">remoteStreams</a></code> array.</p>
</li>
<li>
<p><a href="#fire-a-stream-event">Fire a stream event</a> named <code title="event-MediaStream-addstream"><a href="#event-mediastream-addstream">addstream</a></code> with the newly created
<code><a href="#mediastream">MediaStream</a></code> object at the <var title="">connection</var> object.</p>
</li>
</ol>
</li>
</ol>
<p>When a <a href="#peerconnection"><code>PeerConnection</code></a> finds that a stream
from the remote peer has been removed (its port has been set to zero in a media
description sent on the signaling channel), the user agent must follow these steps:</p>
<ol>
<li>
<p>Let <var title="">connection</var> be the <code><a href="#peerconnection">PeerConnection</a></code> associated with the stream being
removed.</p>
</li>
<li>
<p>Let <var title="">stream</var> be the <code><a href="#mediastream">MediaStream</a></code> object that represents the media stream being
removed, if any. If there isn't one, then abort these steps.</p>
</li>
<li>
<p>By definition, <var title="">stream</var> is now <a href="#concept-stream-finished" title="concept-stream-finished">finished</a>.</p>
<p class="note">A <span title="concept-task">task</span> is thus <span title="queue a task">queued</span> to update <var title="">stream</var> and fire an
event.</p>
</li>
<li>
<p>Queue a task to run the following substeps:</p>
<ol>
<li>
<p>If the <var title="">connection</var>'s <a href="#peerconnection-readiness-state"><code>PeerConnection</code> readiness
state</a> is <code title="dom-PeerConnection-CLOSED"><a href="#widl-PeerConnection-NEW">CLOSED</a></code> (3), abort these steps.</p>
</li>
<!-- close() was probably called just before this
task ran -->
<li>
<p>Remove <var title="">stream</var> from <var title="">connection</var>'s
<code title="dom-PeerConnection-remoteStreams"><a href="#widl-PeerConnection-remoteStreams">remoteStreams</a></code> array.</p>
</li>
<li>
<p><a href="#fire-a-stream-event">Fire a stream event</a> named <code title="event-MediaStream-removestream"><a href="#event-mediastream-removestream">removestream</a></code> with <var title="">stream</var> at the <var title="">connection</var> object.</p>
</li>
</ol>
</li>
</ol>
<p>The task source for the <span title="concept-task">tasks</span> listed
in this section is the networking task source.</p>
<p class="warning">To prevent network sniffing from allowing a fourth party to
establish a connection to a peer using the information sent out-of-band to the other
peer and thus spoofing the client, the configuration information should always be
transmitted using an encrypted connection.</p>
<div id="peerconnection" class="section">
<h3><span class="secno">4.1 </span>PeerConnection</h3>
<pre class="idl"><span class="idlInterface" id="idl-def-PeerConnection">[<span class="extAttr">Constructor (in DOMString configuration, in SignalingCallback signalingCallback)</span>]
interface <span class="idlInterfaceID">PeerConnection</span> {
<span class="idlMethod"> <span class="idlMethType"><a>void</a></span> <span class="idlMethName"><a href="#widl-PeerConnection-processSignalingMessage-void-DOMString-message">processSignalingMessage</a></span> (<span class="idlParam"><span class="idlParamType"><a>DOMString</a></span> <span class="idlParamName">message</span></span>);</span>
<span class="idlConst"> const <span class="idlConstType"><a>unsigned short</a></span> <span class="idlConstName"><a href="#widl-PeerConnection-NEW">NEW</a></span> = <span class="idlConstValue">0</span>;</span>
<span class="idlConst"> const <span class="idlConstType"><a>unsigned short</a></span> <span class="idlConstName"><a href="#widl-PeerConnection-NEGOTIATING">NEGOTIATING</a></span> = <span class="idlConstValue">1</span>;</span>
<span class="idlConst"> const <span class="idlConstType"><a>unsigned short</a></span> <span class="idlConstName"><a href="#widl-PeerConnection-ACTIVE">ACTIVE</a></span> = <span class="idlConstValue">2</span>;</span>
<span class="idlConst"> const <span class="idlConstType"><a>unsigned short</a></span> <span class="idlConstName"><a href="#widl-PeerConnection-CLOSING">CLOSING</a></span> = <span class="idlConstValue">4</span>;</span>
<span class="idlConst"> const <span class="idlConstType"><a>unsigned short</a></span> <span class="idlConstName"><a href="#widl-PeerConnection-CLOSED">CLOSED</a></span> = <span class="idlConstValue">3</span>;</span>
<span class="idlAttribute"> readonly attribute <span class="idlAttrType"><a>unsigned short</a></span> <span class="idlAttrName"><a href="#widl-PeerConnection-readyState">readyState</a></span>;</span>
<span class="idlConst"> const <span class="idlConstType"><a>unsigned short</a></span> <span class="idlConstName"><a href="#widl-PeerConnection-ICE_GATHERING">ICE_GATHERING</a></span> = <span class="idlConstValue">0x100</span>;</span>
<span class="idlConst"> const <span class="idlConstType"><a>unsigned short</a></span> <span class="idlConstName"><a href="#widl-PeerConnection-ICE_WAITING">ICE_WAITING</a></span> = <span class="idlConstValue">0x200</span>;</span>
<span class="idlConst"> const <span class="idlConstType"><a>unsigned short</a></span> <span class="idlConstName"><a href="#widl-PeerConnection-ICE_CHECKING">ICE_CHECKING</a></span> = <span class="idlConstValue">0x300</span>;</span>
<span class="idlConst"> const <span class="idlConstType"><a>unsigned short</a></span> <span class="idlConstName"><a href="#widl-PeerConnection-ICE_CONNECTED">ICE_CONNECTED</a></span> = <span class="idlConstValue">0x400</span>;</span>
<span class="idlConst"> const <span class="idlConstType"><a>unsigned short</a></span> <span class="idlConstName"><a href="#widl-PeerConnection-ICE_COMPLETED">ICE_COMPLETED</a></span> = <span class="idlConstValue">0x500</span>;</span>
<span class="idlConst"> const <span class="idlConstType"><a>unsigned short</a></span> <span class="idlConstName"><a href="#widl-PeerConnection-ICE_FAILED">ICE_FAILED</a></span> = <span class="idlConstValue">0x600</span>;</span>
<span class="idlConst"> const <span class="idlConstType"><a>unsigned short</a></span> <span class="idlConstName"><a href="#widl-PeerConnection-ICE_CLOSED">ICE_CLOSED</a></span> = <span class="idlConstValue">00x700</span>;</span>
<span class="idlAttribute"> readonly attribute <span class="idlAttrType"><a>unsigned short</a></span> <span class="idlAttrName"><a href="#widl-PeerConnection-iceState">iceState</a></span>;</span>
<span class="idlConst"> const <span class="idlConstType"><a>unsigned short</a></span> <span class="idlConstName"><a href="#widl-PeerConnection-SDP_IDLE">SDP_IDLE</a></span> = <span class="idlConstValue">0x1000</span>;</span>
<span class="idlConst"> const <span class="idlConstType"><a>unsigned short</a></span> <span class="idlConstName"><a href="#widl-PeerConnection-SDP_WAITING">SDP_WAITING</a></span> = <span class="idlConstValue">0x2000</span>;</span>
<span class="idlConst"> const <span class="idlConstType"><a>unsigned short</a></span> <span class="idlConstName"><a href="#widl-PeerConnection-SDP_GLARE">SDP_GLARE</a></span> = <span class="idlConstValue">0x3000</span>;</span>
<span class="idlAttribute"> readonly attribute <span class="idlAttrType"><a>unsigned short</a></span> <span class="idlAttrName"><a href="#widl-PeerConnection-sdpState">sdpState</a></span>;</span>
<span class="idlMethod"> <span class="idlMethType"><a>void</a></span> <span class="idlMethName"><a href="#widl-PeerConnection-addStream-void-MediaStream-stream-MediaStreamHints-hints">addStream</a></span> (<span class="idlParam"><span class="idlParamType"><a href="#idl-def-MediaStream" class="idlType"><code>MediaStream</code></a></span> <span class="idlParamName">stream</span></span>, <span class="idlParam"><span class="idlParamType"><a>MediaStreamHints</a></span> <span class="idlParamName">hints</span></span>);</span>
<span class="idlMethod"> <span class="idlMethType"><a>void</a></span> <span class="idlMethName"><a href="#widl-PeerConnection-removeStream-void-MediaStream-stream">removeStream</a></span> (<span class="idlParam"><span class="idlParamType"><a href="#idl-def-MediaStream" class="idlType"><code>MediaStream</code></a></span> <span class="idlParamName">stream</span></span>);</span>
<span class="idlAttribute"> readonly attribute <span class="idlAttrType"><a href="#idl-def-MediaStream" class="idlType"><code>MediaStream</code></a>[]</span> <span class="idlAttrName"><a href="#widl-PeerConnection-localStreams">localStreams</a></span>;</span>
<span class="idlAttribute"> readonly attribute <span class="idlAttrType"><a href="#idl-def-MediaStream" class="idlType"><code>MediaStream</code></a>[]</span> <span class="idlAttrName"><a href="#widl-PeerConnection-remoteStreams">remoteStreams</a></span>;</span>
<span class="idlMethod"> <span class="idlMethType"><a>void</a></span> <span class="idlMethName"><a href="#widl-PeerConnection-close-void">close</a></span> ();</span>
<span class="idlAttribute"> attribute <span class="idlAttrType"><a>Function</a>?</span> <span class="idlAttrName"><a href="#widl-PeerConnection-onconnecting">onconnecting</a></span>;</span>
<span class="idlAttribute"> attribute <span class="idlAttrType"><a>Function</a>?</span> <span class="idlAttrName"><a href="#widl-PeerConnection-onopen">onopen</a></span>;</span>
<span class="idlAttribute"> attribute <span class="idlAttrType"><a>Function</a>?</span> <span class="idlAttrName"><a href="#widl-PeerConnection-onstatechange">onstatechange</a></span>;</span>
<span class="idlAttribute"> attribute <span class="idlAttrType"><a>Function</a>?</span> <span class="idlAttrName"><a href="#widl-PeerConnection-onaddstream">onaddstream</a></span>;</span>
<span class="idlAttribute"> attribute <span class="idlAttrType"><a>Function</a>?</span> <span class="idlAttrName"><a href="#widl-PeerConnection-onremovestream">onremovestream</a></span>;</span>
};</span>
</pre><div id="attributes-4" class="section"><h4><span class="secno">4.1.1 </span>Attributes</h4><dl class="attributes"><dt id="widl-PeerConnection-iceState"><code>iceState</code> of type <span class="idlAttrType"><a>unsigned short</a></span>, readonly</dt><dd>
<p>The <dfn id="dom-peerconnection-icestate" title="dom-PeerConnection-iceState"><code title="">iceState</code></dfn> attribute
must return the state of the <code><a href="#peerconnection">PeerConnection</a></code> ICE Agent
<a href="#dom-peerconnection-icestate"><code>PeerConnection</code> ICE
state</a>, represented by a number from the following list:</p>
<dl>
<dt><code><a href="#peerconnection">PeerConnection</a></code> . <code title="dom-PeerConnection-NEW"><a href="#widl-PeerConnection-NEW">NEW</a></code>
(0)</dt>
<dd>The object was just created, and no networking has yet occurred.</dd>
<dt><code><a href="#peerconnection">PeerConnection</a></code> . <code title="dom-PeerConnection-GATHERING"><a href="#widl-PeerConnection-ICE_GATHERING">ICE_GATHERING</a></code> (0x100)</dt>
<dd>The ICE Agent is attempting to establish a gather addresses.</dd>
<dt><code><a href="#peerconnection">PeerConnection</a></code> . <code title="dom-PeerConnection-ICE_WAITING"><a href="#widl-PeerConnection-ICE_WAITING">ICE_WAITING</a></code> (0x200)</dt>
<dd>The ICE Agent is waiting for candidates from the other side before it
can start checking.</dd>
<dt><code><a href="#peerconnection">PeerConnection</a></code> . <code title="dom-PeerConnection-CHECKING"><a href="#widl-PeerConnection-ICE_CHECKING">ICE_CHECKING</a></code> (0x300)</dt>
<dd>The ICE Agent is checking candidates but has not yet found a connection.</dd>
<dt><code><a href="#peerconnection">PeerConnection</a></code> . <code title="dom-PeerConnection-CONNECTED"><a href="#widl-PeerConnection-ICE_CONNECTED">ICE_CONNECTED</a></code> (0x400)</dt>
<dd>The ICE Agent has found a connection but is still checking other
candidates to see if there is a better connection.</dd>
<dt><code><a href="#peerconnection">PeerConnection</a></code> . <code title="dom-PeerConnection-COMPLETED"><a href="#widl-PeerConnection-ICE_COMPLETED">ICE_COMPLETED</a></code> (0x500)</dt>
<dd>The ICE Agent has finished checking and found a connection.</dd>
<dt><code><a href="#peerconnection">PeerConnection</a></code> . <code title="dom-PeerConnection-ICE_FAILED"><a href="#widl-PeerConnection-ICE_FAILED">ICE_FAILED</a></code> (0x600)</dt>
<dd>The ICE Agent is finished checking all candidates and failed to find a connection.</dd>
<dt><code><a href="#peerconnection">PeerConnection</a></code> . <code title="dom-PeerConnection-CLOSED"><a href="#widl-PeerConnection-ICE_CLOSED">ICE_CLOSED</a></code> (0x700)</dt>
<dd>The ICE Agent has shut down and is no longer responding to STUN requests.</dd>
</dl>
<div><em>No exceptions.</em></div></dd><dt id="widl-PeerConnection-localStreams"><code>localStreams</code> of type array of <span class="idlAttrType"><a href="#idl-def-MediaStream" class="idlType"><code>MediaStream</code></a></span>, readonly</dt><dd>
<p>Returns a live array containing the streams that the user agent is currently
attempting to transmit to the remote peer (those that were added with <code title="dom-PeerConnection-addStream"><a href="#widl-PeerConnection-addStream-void-MediaStream-stream-MediaStreamHints-hints">addStream()</a></code>).</p>
<p>Specifically, it must return the read-only <code><a href="#mediastream">MediaStream</a></code> array that the attribute was set to when the
<code><a href="#peerconnection">PeerConnection</a></code>'s constructor ran.</p>
<div><em>No exceptions.</em></div></dd><dt id="widl-PeerConnection-onaddstream"><code>onaddstream</code> of type <span class="idlAttrType"><a>Function</a></span>, nullable</dt><dd>This event handler, of <span title="event handler event type">event handler event
type</span> <code title="event-MediaStream-addstream"><a href="#event-mediastream-addstream">addstream</a></code>, must be supported by all objects
implementing the <code><a href="#peerconnection">PeerConnection</a></code>
interface.<div><em>No exceptions.</em></div></dd><dt id="widl-PeerConnection-onconnecting"><code>onconnecting</code> of type <span class="idlAttrType"><a>Function</a></span>, nullable</dt><dd>This event handler, of <span title="event handler event type">event handler event
type</span> <code title="event-MediaStream-connecting"><a href="#event-mediastream-connecting">connecting</a></code>, must be supported by all
objects implementing the <code><a href="#peerconnection">PeerConnection</a></code>
interface.<div><em>No exceptions.</em></div></dd><dt id="widl-PeerConnection-onopen"><code>onopen</code> of type <span class="idlAttrType"><a>Function</a></span>, nullable</dt><dd>This event handler, of <span title="event handler event type">event handler event
type</span> <code title="event-MediaStream-open"><a href="#event-mediastream-open">open</a></code>, must be supported by all objects
implementing the <code><a href="#peerconnection">PeerConnection</a></code>
interface.<div><em>No exceptions.</em></div></dd><dt id="widl-PeerConnection-onremovestream"><code>onremovestream</code> of type <span class="idlAttrType"><a>Function</a></span>, nullable</dt><dd>This event handler, of <span title="event handler event type">event handler event
type</span> <code title="event-MediaStream-removestream"><a href="#event-mediastream-removestream">removestream</a></code>, must be supported by all
objects implementing the <code><a href="#peerconnection">PeerConnection</a></code>
interface.<div><em>No exceptions.</em></div></dd><dt id="widl-PeerConnection-onstatechange"><code>onstatechange</code> of type <span class="idlAttrType"><a>Function</a></span>, nullable</dt><dd>This event handler, of <span title="event handler event type">event handler event
type</span> <code title="event-MediaStream-open"><a href="#event-mediastream-open">open</a></code>, must be supported by all objects
implementing the <code><a href="#peerconnection">PeerConnection</a></code>
interface. It is called any time the readyState, iceState, or sdpState
changes. <div><em>No exceptions.</em></div></dd><dt id="widl-PeerConnection-readyState"><code>readyState</code> of type <span class="idlAttrType"><a>unsigned short</a></span>, readonly</dt><dd>
<p>The <dfn id="dom-peerconnection-readystate" title="dom-PeerConnection-readyState"><code title="">readyState</code></dfn> attribute
must return the <code><a href="#peerconnection">PeerConnection</a></code> object's
<a href="#peerconnection-readiness-state"><code>PeerConnection</code> readiness
state</a>, represented by a number from the following list:</p>
<dl>
<dt><code><a href="#peerconnection">PeerConnection</a></code> . <code title="dom-PeerConnection-NEW"><a href="#widl-PeerConnection-NEW">NEW</a></code>
(0)</dt>
<dd>The object was just created, and no networking has yet occurred.</dd>
<dt><code><a href="#peerconnection">PeerConnection</a></code> . <code title="dom-PeerConnection-NEGOTIATING"><a href="#widl-PeerConnection-NEGOTIATING">NEGOTIATING</a></code> (1)</dt>
<dd>The user agent is attempting to establish an connection with the ICE
Agent and to negotiate codecs with the SDP Agent.</dd>
<dt><code><a href="#peerconnection">PeerConnection</a></code> . <code title="dom-PeerConnection-ACTIVE"><a href="#widl-PeerConnection-ACTIVE">ACTIVE</a></code> (2)</dt>
<dd>The ICE Agent has found a connection the SDP Agent has performed a
round of codec negotiation. It is possible for whatever media was
negotiated to flow.</dd>
<dt><code><a href="#peerconnection">PeerConnection</a></code> . <code title="dom-PeerConnection-CLOSING"><a href="#widl-PeerConnection-CLOSING">CLOSING</a></code> (4)</dt>
<dd> The <code><a href="#peerconnection">PeerConnection</a></code>
object is terminating all media and is in the process of closing the
Ice Agent and SDP Agent. </dd>
<dt><code><a href="#peerconnection">PeerConnection</a></code> . <code title="dom-PeerConnection-CLOSED"><a href="#widl-PeerConnection-CLOSED">CLOSED</a></code> (3)</dt>
<dd>The connection is closed. </dd>
</dl>
<div><em>No exceptions.</em></div></dd><dt id="widl-PeerConnection-remoteStreams"><code>remoteStreams</code> of type array of <span class="idlAttrType"><a href="#idl-def-MediaStream" class="idlType"><code>MediaStream</code></a></span>, readonly</dt><dd>
<p>Returns a live array containing the streams that the user agent is currently
receiving from the remote peer.</p>
<p>Specifically, it must return the read-only <code><a href="#mediastream">MediaStream</a></code> array that the attribute was set to when the
<code><a href="#peerconnection">PeerConnection</a></code>'s constructor ran.</p>
<p>This array is updated when <code title="event-MediaStream-addstream"><a href="#event-mediastream-addstream">addstream</a></code> and <code title="event-MediaStream-removestream"><a href="#event-mediastream-removestream">removestream</a></code> events are fired.</p>
<div><em>No exceptions.</em></div></dd><dt id="widl-PeerConnection-sdpState"><code>sdpState</code> of type <span class="idlAttrType"><a>unsigned short</a></span>, readonly</dt><dd> <p>The <dfn id="dom-peerconnection-sdpstate" title="dom-PeerConnection-sdpState"><code title="">sdpState</code></dfn> attribute
must return the state of the <code><a href="#peerconnection">PeerConnection</a></code> SDP Agent , represented by
a number from the following list:</p>
<dl>
<dt><code><a href="#peerconnection">PeerConnection</a></code> . <code title="dom-PeerConnection-NEW"><a href="#widl-PeerConnection-NEW">NEW</a></code>
(0)</dt>
<dd>The object was just created, and no networking has yet occurred.</dd>
<dt><code><a href="#peerconnection">PeerConnection</a></code> . <code title="dom-PeerConnection-SDP_IDLE"><a href="#widl-PeerConnection-SDP_IDLE">SDP_IDLE</a></code> (0x1000)</dt>
<dd>At least one SDP offer or answer has been exchange and the SDP Agent
is ready to send an SDP offer or receive an SDP answer.</dd>
<dt><code><a href="#peerconnection">PeerConnection</a></code> . <code title="dom-PeerConnection-SDP_WAITING"><a href="#widl-PeerConnection-SDP_WAITING">SDP_WAITING</a></code> (0x2000)</dt>
<dd>The SDP Agent has sent and offer and is waiting for a answer.</dd>
<dt><code><a href="#peerconnection">PeerConnection</a></code> . <code title="dom-PeerConnection-SDP_GLARE"><a href="#widl-PeerConnection-SDP_GLARE">SDP_GLARE</a></code> (0x3000)</dt>
<dd>The SDP Agent received an offer while waiting for an answer and now
much wait a rondom amount of time before retrying to send the offer.</dd>
</dl>
<div><em>No exceptions.</em></div></dd></dl></div><div id="methods-8" class="section"><h4><span class="secno">4.1.2 </span>Methods</h4><dl class="methods"><dt id="widl-PeerConnection-addStream-void-MediaStream-stream-MediaStreamHints-hints"><code>addStream</code></dt><dd>
<p>Attempts to starting sending the given stream to the remote peer.
The format for the MediaStreamHints objects is currently undefined
by the specification.</p>
<p>When the other peer starts sending a stream in this manner, an <code title="event-MediaStream-addstream"><a href="#event-mediastream-addstream">addstream</a></code> event is fired at the
<code><a href="#peerconnection">PeerConnection</a></code> object.</p>
<!-- </ol> -->
<p>When the <dfn id="dom-peerconnection-addstream" title="dom-PeerConnection-addStream"><code title="">addStream()</code></dfn> method is
invoked, the user agent must run the following steps:</p>
<ol>
<li>
<p>Let <var title="">stream</var> be the method's first argument.</p>
</li>
<li>
<p>Let <var title="">hints</var> be the method's second argument.</p>
</li>
<li>
<p>If the <code><a href="#peerconnection">PeerConnection</a></code> object's
<a href="#peerconnection-readiness-state"><code>PeerConnection</code> readiness
state</a> is <code title="dom-PeerConnection-CLOSED"><a href="#widl-PeerConnection-NEW">CLOSED</a></code> (3), throw an
<code>INVALID_STATE_ERR</code> exception.</p>
</li>
<li>
<p>If <var title="">stream</var> is already in the <code><a href="#peerconnection">PeerConnection</a></code> object's <code title="dom-PeerConnection-localStreams"><a href="#widl-PeerConnection-localStreams">localStreams</a></code> object, then abort
these steps.</p>
</li>
<li>
<p>Add <var title="">stream</var> to the end of the <code><a href="#peerconnection">PeerConnection</a></code> object's <code title="dom-PeerConnection-localStreams"><a href="#widl-PeerConnection-localStreams">localStreams</a></code> object.</p>
</li>
<li>
<p>Return from the method.</p>
</li>
<li>
<p>Parse the <var title="">hints</var> provided by the application
and apply them to the MediaStream, if possible.
</p>
</li>
<li>
<p>Have the <code><a href="#peerconnection">PeerConnection</a></code> add a
media stream for <var title="">stream</var> the next time the user agent
<span title="provide a stable state">provides a stable state</span>. Any other
pending stream additions and removals must be processed at the same time.</p>
</li>
</ol>
<table class="parameters"><tr><th>Parameter</th><th>Type</th><th>Nullable</th><th>Optional</th><th>Description</th></tr><tr><td class="prmName">stream</td><td class="prmType"><code><a href="#idl-def-MediaStream" class="idlType"><code>MediaStream</code></a></code></td><td class="prmNullFalse">✘</td><td class="prmOptFalse">✘</td><td class="prmDesc"></td></tr><tr><td class="prmName">hints</td><td class="prmType"><code><a>MediaStreamHints</a></code></td><td class="prmNullFalse">✘</td><td class="prmOptFalse">✘</td><td class="prmDesc"></td></tr></table><div><em>No exceptions.</em></div><div><em>Return type: </em><code><a>void</a></code></div></dd><dt id="widl-PeerConnection-close-void"><code>close</code></dt><dd>
<p>When the <dfn id="dom-peerconnection-close" title="dom-PeerConnection-close"><code title="">close()</code></dfn> method is invoked,
the user agent must run the following steps:</p>
<ol>
<li>
<p>If the <code><a href="#peerconnection">PeerConnection</a></code> object's
<a href="#peerconnection-readiness-state"><code>PeerConnection</code> readiness
state</a> is <code title="dom-PeerConnection-CLOSED"><a href="#widl-PeerConnection-CLOSED">CLOSED</a></code> (3), throw an
<code>INVALID_STATE_ERR</code> exception.</p>
</li>
<li>
<p>Destroy the <a href="#peerconnection-ice-agent"><code>PeerConnection</code>
ICE Agent</a>, abruptly ending any active ICE processing and any active
streaming, and releasing any relevant resources (e.g. TURN permissions).</p>
</li>
<li>
<p>Set the object's <a href="#peerconnection-readiness-state"><code>PeerConnection</code> readiness
state</a> to <code title="dom-PeerConnection-CLOSED"><a href="#widl-PeerConnection-CLOSED">CLOSED</a></code> (3).</p>
</li>
<!--
<li><p>Queue a task to fire a simple
event named <code title="event-MediaStream-close">close</code> at the
<code>PeerConnection</code> object.</p></p></li>
-->
</ol>
<p class="note">The <code title="dom-PeerConnection-localStreams"><a href="#widl-PeerConnection-localStreams">localStreams</a></code> and <code title="dom-PeerConnection-remoteStreams"><a href="#widl-PeerConnection-remoteStreams">remoteStreams</a></code> objects remain in the
state they were in when the object was closed.</p>
<div><em>No parameters.</em></div><div><em>No exceptions.</em></div><div><em>Return type: </em><code><a>void</a></code></div></dd><dt id="widl-PeerConnection-processSignalingMessage-void-DOMString-message"><code>processSignalingMessage</code></dt><dd>
<p>When a message is relayed from the remote peer over the signaling channel is
received by the Web application, pass it to the user agent by calling the
<code title="dom-PeerConnection-processSignalingMessage"><a href="#dom-peerconnection-processsignalingmessage">processSignalingMessage()</a></code>
method.</p>
<p>The order of messages is important. Passing messages to the user agent in a
different order than they were generated by the remote peer's user agent can
prevent a successful connection from being established or degrade the connection's
quality if one is established.</p>
<p>When the <dfn id="dom-peerconnection-processsignalingmessage" title="dom-PeerConnection-processSignalingMessage"><code title="""">processSignalingMessage()</code></dfn> method is invoked, the user agent must
run the following steps:</p>
<ol>
<li>
<p>Let <var title="">message</var> be the method's argument.</p>
</li>
<li>
<p>Let <var title="">connection</var> be the <code><a href="#peerconnection">PeerConnection</a></code> object on which the method was
invoked.</p>
</li>
<li>
<p>If <var title="">connection</var>'s <a href="#peerconnection-readiness-state"><code>PeerConnection</code> readiness
state</a> is <code title="dom-PeerConnection-CLOSED"><a href="#widl-PeerConnection-NEW">CLOSED</a></code> (3), throw an
<code>INVALID_STATE_ERR</code> exception.</p>
</li>
<li>
<p>If the first four characters of <var title="">message</var> are not
"<code title="">SDP</code>" followed by a U+000A LINE FEED (LF) character, then
abort these steps. (This indicates an error in the signaling channel
implementation. User agents may report such errors to their developer consoles
to aid debugging.)</p>
<p class="note">Future extensions to the <code><a href="#peerconnection">PeerConnection</a></code> interface might use other prefix
values to implement additional features.</p>
</li>
<li>
<p>Let <var title="">sdp</var> be the string consisting of all but the first
four characters of <var title="">message</var>.</p>
</li>
<li>
<p> Pass the <var title="">sdp</var> to the <a href="#peerconnection-ice-agent"><code>PeerConnection</code> SDP Agent</a> as a
subsequent offer or answer, to be interpreted as appropriate given the current
state of the SDP Agent. [<cite><a class="bibref" rel="biblioentry" href="#bib-ICE">ICE</a></cite>]</p>
</li>
</ol>
<p>When a <a href="#peerconnection-ice-agent"><code>PeerConnection</code> ICE
Agent</a> forms a connection to the the far side and enters the state
ICECONNECTED, the user
agent must queue a task that sets the <code><a href="#peerconnection">PeerConnection</a></code> object's <a href="#peerconnection-readiness-state"><code>PeerConnection</code> readiness state</a>
to <code title="dom-PeerConnection-ACTIVE"><a href="#widl-PeerConnection-ACTIVE">ACTIVE</a></code> (2) and then <span title="fire a simple event">fires a simple event</span> named <code title="event-MediaStream-open"><a href="#event-mediastream-open">open</a></code> at the
<code><a href="#peerconnection">PeerConnection</a></code> object.</p>
<table class="parameters"><tr><th>Parameter</th><th>Type</th><th>Nullable</th><th>Optional</th><th>Description</th></tr><tr><td class="prmName">message</td><td class="prmType"><code><a>DOMString</a></code></td><td class="prmNullFalse">✘</td><td class="prmOptFalse">✘</td><td class="prmDesc"></td></tr></table><div><em>No exceptions.</em></div><div><em>Return type: </em><code><a>void</a></code></div></dd><dt id="widl-PeerConnection-removeStream-void-MediaStream-stream"><code>removeStream</code></dt><dd>
<p>Stops sending the given stream to the remote peer.</p>
<p>When the other peer stops sending a stream in this manner, a <code title="event-MediaStream-removestream"><a href="#event-mediastream-removestream">removestream</a></code> event is fired at the
<code><a href="#peerconnection">PeerConnection</a></code> object.</p>
<p>When the <dfn id="dom-peerconnection-removestream" title="dom-PeerConnection-removeStream"><code title="">removeStream()</code></dfn> method
is invoked, the user agent must run the following steps:</p>
<ol>
<li>
<p>Let <var title="">stream</var> be the method's argument.</p>
</li>
<li>
<p>If the <code><a href="#peerconnection">PeerConnection</a></code> object's
<a href="#peerconnection-readiness-state"><code>PeerConnection</code> readiness
state</a> is <code title="dom-PeerConnection-CLOSED"><a href="#widl-PeerConnection-CLOSED">CLOSED</a></code> (3), throw an
<code>INVALID_STATE_ERR</code> exception.</p>
</li>
<li>
<p>If <var title="">stream</var> is not in the <code><a href="#peerconnection">PeerConnection</a></code> object's <code title="dom-PeerConnection-localStreams"><a href="#widl-PeerConnection-localStreams">localStreams</a></code> object, then abort
these steps.</p>
</li>
<li>
<p>Remove <var title="">stream</var> from the <code><a href="#peerconnection">PeerConnection</a></code> object's <code title="dom-PeerConnection-localStreams"><a href="#widl-PeerConnection-localStreams">localStreams</a></code> object.</p>
</li>
<li>
<p>Return from the method.</p>
</li>
<li>
<p>Have the <code><a href="#peerconnection">PeerConnection</a></code>remove the
media stream for <var title="">stream</var> the next time the user agent
<span title="provide a stable state">provides a stable state</span>. Any other
pending stream additions and removals must be processed at the same time.</p>
</li>
<!-- section 9.1.1.2 -->
</ol>
<table class="parameters"><tr><th>Parameter</th><th>Type</th><th>Nullable</th><th>Optional</th><th>Description</th></tr><tr><td class="prmName">stream</td><td class="prmType"><code><a href="#idl-def-MediaStream" class="idlType"><code>MediaStream</code></a></code></td><td class="prmNullFalse">✘</td><td class="prmOptFalse">✘</td><td class="prmDesc"></td></tr></table><div><em>No exceptions.</em></div><div><em>Return type: </em><code><a>void</a></code></div></dd></dl></div><div id="constants-2" class="section"><h4><span class="secno">4.1.3 </span>Constants</h4><dl class="constants"><dt id="widl-PeerConnection-ACTIVE"><code>ACTIVE</code> of type <span class="idlConstType"><a>unsigned short</a></span></dt><dd> A connection has been formed and if any media streams were
successfully negotiated, any relevant media can be streaming.</dd><dt id="widl-PeerConnection-CLOSED"><code>CLOSED</code> of type <span class="idlConstType"><a>unsigned short</a></span></dt><dd>The <code title="dom-PeerConnection-close"><a href="#dom-peerconnection-close">close()</a></code> method has been invoked.</dd><dt id="widl-PeerConnection-CLOSING"><code>CLOSING</code> of type <span class="idlConstType"><a>unsigned short</a></span></dt><dd>The object is starting to shut down after the <code title="dom-PeerConnection-close"><a href="#dom-peerconnection-close">close()</a></code> method has been invoked.</dd><dt id="widl-PeerConnection-ICE_CHECKING"><code>ICE_CHECKING</code> of type <span class="idlConstType"><a>unsigned short</a></span></dt><dd>The ICE Agent is checking candidates but has not yet found a connection
that works.</dd><dt id="widl-PeerConnection-ICE_CLOSED"><code>ICE_CLOSED</code> of type <span class="idlConstType"><a>unsigned short</a></span></dt><dd>The ICE Agent is terminating and will no longer repined to STUN
connectivity checks.</dd><dt id="widl-PeerConnection-ICE_COMPLETED"><code>ICE_COMPLETED</code> of type <span class="idlConstType"><a>unsigned short</a></span></dt><dd>The ICE Agent has finished checking all candidates and a connection has
been formed.</dd><dt id="widl-PeerConnection-ICE_CONNECTED"><code>ICE_CONNECTED</code> of type <span class="idlConstType"><a>unsigned short</a></span></dt><dd>The ICE Agent has found at least one candidate that works but is still checking.</dd><dt id="widl-PeerConnection-ICE_FAILED"><code>ICE_FAILED</code> of type <span class="idlConstType"><a>unsigned short</a></span></dt><dd>The ICE Agent has finished checking all candidates and no connection
was worked.</dd><dt id="widl-PeerConnection-ICE_GATHERING"><code>ICE_GATHERING</code> of type <span class="idlConstType"><a>unsigned short</a></span></dt><dd>The ICE Agent is gather addresses that can be used.</dd><dt id="widl-PeerConnection-ICE_WAITING"><code>ICE_WAITING</code> of type <span class="idlConstType"><a>unsigned short</a></span></dt><dd>THE ICE Agent has complete gathering addresses and is waiting for candidates
to start checking. </dd><dt id="widl-PeerConnection-NEGOTIATING"><code>NEGOTIATING</code> of type <span class="idlConstType"><a>unsigned short</a></span></dt><dd>The peerConenction object is attempting to get to the point wehre media
can flow.</dd><dt id="widl-PeerConnection-NEW"><code>NEW</code> of type <span class="idlConstType"><a>unsigned short</a></span></dt><dd>The object was just created and its ICE and SDP Agent have not yet been started.</dd><dt id="widl-PeerConnection-SDP_GLARE"><code>SDP_GLARE</code> of type <span class="idlConstType"><a>unsigned short</a></span></dt><dd>Both side sent SDP offers at the same time and the SDP Agent is waiting to
be able to retransmit the SDP offer.</dd><dt id="widl-PeerConnection-SDP_IDLE"><code>SDP_IDLE</code> of type <span class="idlConstType"><a>unsigned short</a></span></dt><dd>A valid offer anser pair has been exchanged and the SDP Agent is waiting
for the next SDP transaction.</dd><dt id="widl-PeerConnection-SDP_WAITING"><code>SDP_WAITING</code> of type <span class="idlConstType"><a>unsigned short</a></span></dt><dd> The SDP Agent has sent an SDP offer and is waiting for a response.</dd></dl></div>
<pre class="idl"><span class="idlImplements"><a href="#idl-def-PeerConnection" class="idlType"><code>PeerConnection</code></a> implements <a>EventTarget</a>;</span></pre><div class="idlImplementsDesc"><p>All instances of the <code><a href="#idl-def-PeerConnection" class="idlType"><code>PeerConnection</code></a></code> type are defined to also implement the <a>EventTarget</a> interface.</p></div>
</div>
<div id="signalingcallback" class="section">
<h3><span class="secno">4.2 </span>SignalingCallback</h3>
<pre class="idl"><span class="idlInterface" id="idl-def-SignalingCallback">[<span class="extAttr">Callback=FunctionOnly, NoInterfaceObject</span>]
interface <span class="idlInterfaceID">SignalingCallback</span> {
<span class="idlMethod"> <span class="idlMethType"><a>void</a></span> <span class="idlMethName"><a href="#widl-SignalingCallback-handleEvent-void-DOMString-message-PeerConnection-source">handleEvent</a></span> (<span class="idlParam"><span class="idlParamType"><a>DOMString</a></span> <span class="idlParamName">message</span></span>, <span class="idlParam"><span class="idlParamType"><a href="#idl-def-PeerConnection" class="idlType"><code>PeerConnection</code></a></span> <span class="idlParamName">source</span></span>);</span>
};</span>
</pre><div id="methods-9" class="section"><h4><span class="secno">4.2.1 </span>Methods</h4><dl class="methods"><dt id="widl-SignalingCallback-handleEvent-void-DOMString-message-PeerConnection-source"><code>handleEvent</code></dt><dd>Def TBD<table class="parameters"><tr><th>Parameter</th><th>Type</th><th>Nullable</th><th>Optional</th><th>Description</th></tr><tr><td class="prmName">message</td><td class="prmType"><code><a>DOMString</a></code></td><td class="prmNullFalse">✘</td><td class="prmOptFalse">✘</td><td class="prmDesc"></td></tr><tr><td class="prmName">source</td><td class="prmType"><code><a href="#idl-def-PeerConnection" class="idlType"><code>PeerConnection</code></a></code></td><td class="prmNullFalse">✘</td><td class="prmOptFalse">✘</td><td class="prmDesc"></td></tr></table><div><em>No exceptions.</em></div><div><em>Return type: </em><code><a>void</a></code></div></dd></dl></div>
</div>
<div id="examples-2" class="section">
<h3><span class="secno">4.3 </span>Examples</h3>
<div class="example">
<p>When two peers decide they are going to set up a connection to each other, they
both go through these steps. The STUN/TURN server configuration describes a server
they can use to get things like their public IP address or to set up NAT traversal.
They also have to send data for the signaling channel to each other using the same
out-of-band mechanism they used to establish that they were going to communicate in
the first place.</p>
<pre>// the first argument describes the STUN/TURN server configuration
var local = new PeerConnection('TURNS example.net', sendSignalingChannel);
local.signalingChannel(...); // if we have a message from the other side, pass it along here
// (aLocalStream is some LocalMediaStream object)
local.addStream(aLocalStream); // start sending video
function sendSignalingChannel(message) {
... // send message to the other side via the signaling channel
}
function receiveSignalingChannel (message) {
// call this whenever we get a message on the signaling channel
local.signalingChannel(message);
}
local.onaddstream = function (event) {
// (videoElement is some <video> element)
videoElement.src = URL.getObjectURL(event.stream);
};
</pre>
</div>
</div>
</div>
<div id="the-data-stream" class="section">
<!-- OddPage -->
<h2><span class="secno">5. </span>The data stream</h2>
<p class="note">Although progress is being made, there is currently not enough
agreement on the data channel to write it up. This section will be filled in as rough
consensus is reached.</p>
</div>
<div id="garbage-collection" class="section">
<!-- OddPage -->
<h2><span class="secno">6. </span>Garbage collection</h2>
<p>A <code>Window</code> object <dfn id="concept-peerconnection-owner" title="concept-PeerConnection-owner">has a strong reference</dfn> to any <code><a href="#peerconnection">PeerConnection</a></code> objects created from the constructor whose
global object is that <code>Window</code> object.</p>
<!-- we
could be less strict here, e.g. dropping the reference when there's
no way for an event to be fired because there's no event handlers
registered and there's no way for the remote peer to notice anything
because no media is streaming; or e.g. dropping the reference when
the object reaches the CLOSED state. But as dropping the reference
in those cases is black-box indistinguishable from keeping the
reference, I haven't bothered to work out the exact rules. If you do
change this, see the /unloading document cleanup steps/. -->
</div>
<div id="event-definitions" class="section">
<!-- OddPage -->
<h2><span class="secno">7. </span>Event definitions</h2>
<p>The <code title="event-MediaStream-addstream"><a href="#event-mediastream-addstream">addstream</a></code> and <code title="event-MediaStream-removestream"><a href="#event-mediastream-removestream">removestream</a></code> events use the <code><a href="#mediastreamevent">MediaStreamEvent</a></code> interface:</p>
<div id="mediastreamevent" class="section">
<h3><span class="secno">7.1 </span>MediaStreamEvent</h3>
<p><dfn id="fire-a-stream-event" title="fire a stream event">Firing a stream event
named <var title="">e</var></dfn> with a <code><a href="#mediastream">MediaStream</a></code> <var title="">stream</var> means that an event
with the name <var title="">e</var>, which does not bubble (except where otherwise
stated) and is not cancelable (except where otherwise stated), and which uses the
<code><a href="#mediastreamevent">MediaStreamEvent</a></code> interface with the
<code title="dom-MediaStreamEvent-stream"><a href="#dom-mediastreamevent-stream">stream</a></code> attribute set to <var title="">stream</var>, must be created and dispatched at the given target.</p>
<pre class="idl"><span class="idlInterface" id="idl-def-MediaStreamEvent">interface <span class="idlInterfaceID">MediaStreamEvent</span> : <span class="idlSuperclass"><a>Event</a></span> {
<span class="idlAttribute"> readonly attribute <span class="idlAttrType"><a href="#idl-def-MediaStream" class="idlType"><code>MediaStream</code></a>?</span> <span class="idlAttrName"><a href="#widl-MediaStreamEvent-stream">stream</a></span>;</span>
<span class="idlMethod"> <span class="idlMethType"><a>void</a></span> <span class="idlMethName"><a href="#widl-MediaStreamEvent-initMediaStreamEvent-void-DOMString-typeArg-boolean-canBubbleArg-boolean-cancelableArg-MediaStream-streamArg">initMediaStreamEvent</a></span> (<span class="idlParam"><span class="idlParamType"><a>DOMString</a></span> <span class="idlParamName">typeArg</span></span>, <span class="idlParam"><span class="idlParamType"><a>boolean</a></span> <span class="idlParamName">canBubbleArg</span></span>, <span class="idlParam"><span class="idlParamType"><a>boolean</a></span> <span class="idlParamName">cancelableArg</span></span>, <span class="idlParam"><span class="idlParamType"><a href="#idl-def-MediaStream" class="idlType"><code>MediaStream</code></a>?</span> <span class="idlParamName">streamArg</span></span>);</span>
};</span>
</pre><div id="attributes-5" class="section"><h4><span class="secno">7.1.1 </span>Attributes</h4><dl class="attributes"><dt id="widl-MediaStreamEvent-stream"><code>stream</code> of type <span class="idlAttrType"><a href="#idl-def-MediaStream" class="idlType"><code>MediaStream</code></a></span>, readonly, nullable</dt><dd>
<p>The <dfn id="dom-mediastreamevent-stream" title="dom-MediaStreamEvent-stream"><code>stream</code></dfn> attribute represents the
<code><a href="#mediastream">MediaStream</a></code> object associated with the
event.</p>
<div><em>No exceptions.</em></div></dd></dl></div><div id="methods-10" class="section"><h4><span class="secno">7.1.2 </span>Methods</h4><dl class="methods"><dt id="widl-MediaStreamEvent-initMediaStreamEvent-void-DOMString-typeArg-boolean-canBubbleArg-boolean-cancelableArg-MediaStream-streamArg"><code>initMediaStreamEvent</code></dt><dd>
<p>The <dfn id="dom-mediastreamevent-initmediastreamevent" title="dom-MediaStreamEvent-initMediaStreamEvent"><code>initMediaStreamEvent()</code></dfn>
method must initialize the event in a manner analogous to the similarly-named
method in the DOM Events interfaces. [<cite><a class="bibref" rel="biblioentry" href="#bib-DOM-LEVEL-3-EVENTS">DOM-LEVEL-3-EVENTS</a></cite>]</p>
<table class="parameters"><tr><th>Parameter</th><th>Type</th><th>Nullable</th><th>Optional</th><th>Description</th></tr><tr><td class="prmName">typeArg</td><td class="prmType"><code><a>DOMString</a></code></td><td class="prmNullFalse">✘</td><td class="prmOptFalse">✘</td><td class="prmDesc"></td></tr><tr><td class="prmName">canBubbleArg</td><td class="prmType"><code><a>boolean</a></code></td><td class="prmNullFalse">✘</td><td class="prmOptFalse">✘</td><td class="prmDesc"></td></tr><tr><td class="prmName">cancelableArg</td><td class="prmType"><code><a>boolean</a></code></td><td class="prmNullFalse">✘</td><td class="prmOptFalse">✘</td><td class="prmDesc"></td></tr><tr><td class="prmName">streamArg</td><td class="prmType"><code><a href="#idl-def-MediaStream" class="idlType"><code>MediaStream</code></a></code></td><td class="prmNullTrue">✔</td><td class="prmOptFalse">✘</td><td class="prmDesc"></td></tr></table><div><em>No exceptions.</em></div><div><em>Return type: </em><code><a>void</a></code></div></dd></dl></div>
</div>
</div>
<div class="informative section" id="event-summary">
<!-- OddPage -->
<h2><span class="secno">8. </span>Event summary</h2><p><em>This section is non-normative.</em></p>
<p>The following event fires on <code><a href="#mediastream">MediaStream</a></code>
objects:</p>
<table>
<tbody><tr>
<th>Event name</th>
<th>Interface</th>
<th>Fired when...</th>
</tr>
</tbody><tbody>
<tr>
<td><dfn id="event-mediastream-ended" title="event-MediaStream-ended"><code>ended</code></dfn></td>
<td><code>Event</code></td>
<td>The <code><a href="#mediastream">MediaStream</a></code> object will no longer
stream any data, either because the user revoked the permissions, or because the
source device has been ejected, or because the remote peer stopped sending data,
or because the <code title="dom-MediaStream-stop"><a href="#dom-mediastream-stop">stop()</a></code> method was invoked.</td>
</tr>
</tbody>
</table>
<p>The following events fire on <code><a href="#peerconnection">PeerConnection</a></code> objects:</p>
<table>
<tbody><tr>
<th>Event name</th>
<th>Interface</th>
<th>Fired when...</th>
</tr>
</tbody><tbody>
<tr>
<td><dfn id="event-mediastream-connecting" title="event-MediaStream-connecting"><code>connecting</code></dfn></td>
<td><code>Event</code></td>
<td>The ICE Agent has begun negotiating with the peer. This can happen multiple
times during the lifetime of the <code><a href="#peerconnection">PeerConnection</a></code> object.</td>
</tr>
<tr>
<td><dfn id="event-mediastream-open" title="event-MediaStream-open"><code>open</code></dfn></td>
<td><code>Event</code></td>
<td>The ICE Agent has finished negotiating with the peer.</td>
</tr>
<tr>
<td><dfn id="event-mediastream-message" title="event-MediaStream-message"><code>message</code></dfn></td>
<td><code>MessageEvent</code></td>
<td>A data UDP media stream message (to be defined) was
received.</td>
</tr>
<tr>
<td><dfn id="event-mediastream-addstream" title="event-MediaStream-addstream"><code>addstream</code></dfn></td>
<td><code><a href="#mediastreamevent">MediaStreamEvent</a></code></td>
<td>A new stream has been added to the <code title="dom-PeerConnection-remoteStreams"><a href="#widl-PeerConnection-remoteStreams">remoteStreams</a></code> array.</td>
</tr>
<tr>
<td><dfn id="event-mediastream-removestream" title="event-MediaStream-removestream"><code>removestream</code></dfn></td>
<td><code><a href="#mediastreamevent">MediaStreamEvent</a></code></td>
<td>A stream has been removed from the <code title="dom-PeerConnection-remoteStreams"><a href="#widl-PeerConnection-remoteStreams">remoteStreams</a></code> array.</td>
</tr>
</tbody>
</table>
</div>
<div id="application-html-peer-connection-data" class="section">
<!-- OddPage -->
<h2><span class="secno">9. </span>application/html-peer-connection-data</h2>
<p>This registration is for community review and will be submitted to the IESG for
review, approval, and registration with IANA.</p>
<!--
To: ietf-types@iana.org
Subject: Registration of media type application/html-peer-connection-data
-->
<dl>
<dt>Type name:</dt>
<dd>application</dd>
<dt>Subtype name:</dt>
<dd>html-peer-connection-data</dd>
<dt>Required parameters:</dt>
<dd>No required parameters</dd>
<dt>Optional parameters:</dt>
<dd>No optional parameters</dd>
<dt>Encoding considerations:</dt>
<dd>This MIME type defines a binary protocol format which uses UTF-8 for text
encoding.</dd>
<dt>Security considerations:</dt>
<dd>
<p>This format is used for encoding UDP packets transmitted by potentially hostile
Web page content via a trusted user agent to a destination selected by a
potentially hostile remote server. To prevent this mechanism from being abused for
cross-protocol attacks, all the data in these packets is masked so as to appear to
be random noise. The intent of this masking is to reduce the potential attack
scenarios to those already possible previously.</p>
<p>However, this feature still allows random data to be sent to destinations that
might not normally have been able to receive them, such as to hosts within the
victim's intranet. If a service within such an intranet cannot handle receiving UDP
packets containing random noise, it might be vulnerable to attack from this
feature.</p>
</dd>
<dt>Interoperability considerations:</dt>
<dd>Rules for processing both conforming and non-conforming content are defined in
this specification.</dd>
<dt>Published specification:</dt>
<dd>This document is the relevant specification.</dd>
<dt>Applications that use this media type:</dt>
<dd>This type is only intended for use with SDP. [<cite><a class="bibref" rel="biblioentry" href="#bib-SDP">SDP</a></cite>]</dd>
<dt>Additional information:</dt>
<dd>
<dl>
<dt>Magic number(s):</dt>
<dd>No sequence of bytes can uniquely identify data in this format, as all data
in this format is intentionally masked to avoid cross-protocol attacks.</dd>
<dt>File extension(s):</dt>
<dd>This format is not for use with files.</dd>
<dt>Macintosh file type code(s):</dt>
<dd>This format is not for use with files.</dd>
</dl>
</dd>
<dt>Person & email address to contact for further information:</dt>
<dd>Daniel C. Burnett <dburnett@voxeo.com></dd>
<dt>Intended usage:</dt>
<dd>Common</dd>
<dt>Restrictions on usage:</dt>
<dd>No restrictions apply.</dd>
<dt>Author:</dt>
<dd>Daniel C. Burnett <dburnett@voxeo.com></dd>
<dt>Change controller:</dt>
<dd>W3C</dd>
</dl>
<p>Fragment identifiers cannot be used with <code><a href="#application-html-peer-connection-data">application/html-peer-connection-data</a></code>
as URLs cannot be used to identify streams that use this format.</p>
</div>
<div class="appendix section" id="acknowledgements">
<!-- OddPage -->
<h2><span class="secno">A. </span>Acknowledgements</h2>
<p>The editors wish to thank the Working Group chairs, Harald Alvestrand and Stefan
Håkansson, for their support.</p>
</div>
<div id="references" class="appendix section">
<!-- OddPage -->
<h2><span class="secno">B. </span>References</h2><div id="normative-references" class="section"><h3><span class="secno">B.1 </span>Normative references</h3><dl class="bibliography"><dt id="bib-DOM-LEVEL-3-EVENTS">[DOM-LEVEL-3-EVENTS]</dt><dd>Björn Höhrmann; Tom Pixley; Philippe Le Hégaret. <a href="http://www.w3.org/TR/2011/WD-DOM-Level-3-Events-20110531/"><cite>Document Object Model (DOM) Level 3 Events Specification.</cite></a> 31 May 2011. W3C Working Draft. (Work in progress.) URL: <a href="http://www.w3.org/TR/2011/WD-DOM-Level-3-Events-20110531/">http://www.w3.org/TR/2011/WD-DOM-Level-3-Events-20110531/</a>
</dd><dt id="bib-FILE-API">[FILE-API]</dt><dd>Arun Ranganathan. <a href="http://www.w3.org/TR/2009/WD-FileAPI-20091117/"><cite>File API.</cite></a> 17 November 2009. W3C Working Draft. (Work in progress.) URL: <a href="http://www.w3.org/TR/2009/WD-FileAPI-20091117/">http://www.w3.org/TR/2009/WD-FileAPI-20091117/</a>
</dd>
<dt id="bib-ICE">[ICE]</dt><dd>J. Rosenberg <a href="http://tools.ietf.org/html/rfc5245"><cite>Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal for Offer/Answer Protocols.</cite></a> April 2010. Internet RFC 5245. URL: <a href="http://tools.ietf.org/html/rfc5245">http://tools.ietf.org/html/rfc5245</a></dd>
<dt id="bib-SDP">[SDP]</dt><dd>J. Rosenberg, H. Schulzrinne. <a href="http://tools.ietf.org/html/rfc3264"><cite>An Offer/Answer Model with the Session Description Protocol (SDP).</cite></a> June 2002. Internet RFC 3264. URL: <a href="http://tools.ietf.org/html/rfc3264">http://tools.ietf.org/html/rfc3264</a></dd>
<dt id="bib-SDPLABEL">[SDPLABEL]</dt><dd>O. Levin, G. Camarillo. <a href="http://tools.ietf.org/html/rfc4574"><cite>The Session Description Protocol (SDP) Label Attribute.</cite></a> August 2006. Internet RFC 4574. URL: <a href="http://tools.ietf.org/html/rfc4574">http://tools.ietf.org/html/rfc4574</a></dd>
<dt id="bib-STUN">[STUN]</dt><dd>J. Rosenberg, R. Mahy, P. Matthews, D. Wing. <a href="http://tools.ietf.org/html/rfc5389"><cite>Session Traversal Utilities for NAT (STUN).</cite></a> October 2008. Internet RFC 5389. URL: <a href="http://tools.ietf.org/html/rfc5389">http://tools.ietf.org/html/rfc5389</a></dd>
<dt id="bib-TURN">[TURN]</dt><dd>P. Mahy, P. Matthews, J. Rosenberg. <a href="http://tools.ietf.org/html/rfc5766"><cite>Traversal Using Relays around NAT (TURN): Relay Extensions to Session Traversal Utilities for NAT (STUN).</cite></a> April 2010. Internet RFC 5766. URL: <a href="http://tools.ietf.org/html/rfc5766">http://tools.ietf.org/html/rfc5766</a></dd>
<dt id="bib-WEBIDL">[WEBIDL]</dt><dd>Cameron McCormack. <a href="http://www.w3.org/TR/2008/WD-WebIDL-20081219"><cite>Web IDL.</cite></a> 19 December 2008. W3C Working Draft. (Work in progress.) URL: <a href="http://www.w3.org/TR/2008/WD-WebIDL-20081219">http://www.w3.org/TR/2008/WD-WebIDL-20081219</a>
</dd>
</dl></div><div id="informative-references" class="section"><h3><span class="secno">B.2 </span>Informative references</h3><p>No informative references.</p></div></div></body></html>