Another abandoned server code base... this is kind of an ancestor of taskrambler.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2686 lines
156 KiB

<?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>&quot;<code title="">audio</code>&quot;</dt>
<dd>The provided media needs to include audio data.</dd>
<dt>&quot;<code title="">video</code>&quot;</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 &quot;hot&quot;
(i.e. an &quot;on-air&quot; or &quot;recording&quot; 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>&lt;script&gt;
navigator.getUserMedia('audio', gotAudio);
function gotAudio(stream) {
// ... use 'stream' ...
}
&lt;/script&gt;
</pre>
</div>
<div class="example">
<p>A video-conferencing system would ask for both audio and video:</p>
<pre>&lt;script&gt;
function beginCall() {
navigator.getUserMedia('audio,video user', gotStream);
}
function gotStream(stream) {
// ... use 'stream' ...
}
&lt;/script&gt;
</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 &quot;the video currently coming from the user's
video camera&quot;. 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 &quot;video
mute&quot; 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 &quot;on-air&quot; 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 &quot;<code title="&quot;&quot;">audio</code>&quot; if the object's corresponding
track is or was an audio track, &quot;<code title="&quot;&quot;">video</code>&quot; 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. &quot;Internal microphone&quot; or
&quot;External USB Webcam&quot;). 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>&lt;input type=&quot;button&quot; value=&quot;Start&quot; onclick=&quot;start()&quot; id=&quot;startBtn&quot;&gt;
&lt;script&gt;
var startBtn = document.getElementById('startBtn');
function start() {
navigator.getUserMedia('audio,video', gotStream);
startBtn.disabled = true;
}
function gotStream(stream) {
stream.onended = function () {
startBtn.disabled = false;
}
}
&lt;/script&gt;
</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>&lt;input type=&quot;button&quot; value=&quot;&quot; onclick=&quot;msgRecord()&quot; id=&quot;recBtn&quot;&gt;
&lt;input type=&quot;button&quot; value=&quot;&quot; onclick=&quot;msgStop()&quot; id=&quot;stopBtn&quot; disabled&gt;
&lt;p id=&quot;status&quot;&gt;To start recording, press the ⚫ button.&lt;/p&gt;
&lt;script&gt;
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;
}
&lt;/script&gt;
</pre>
</div>
<div class="example">
<p>This example allows people to take photos of themselves from the local video
camera.</p>
<pre>&lt;article&gt;
&lt;style scoped&gt;
video { transform: scaleX(-1); }
p { text-align: center; }
&lt;/style&gt;
&lt;h1&gt;Snapshot Kiosk&lt;/h1&gt;
&lt;section id=&quot;splash&quot;&gt;
&lt;p id=&quot;errorMessage&quot;&gt;Loading...&lt;/p&gt;
&lt;/section&gt;
&lt;section id=&quot;app&quot; hidden&gt;
&lt;p&gt;&lt;video id=&quot;monitor&quot; autoplay&gt;&lt;/video&gt; &lt;canvas id=&quot;photo&quot;&gt;&lt;/canvas&gt;
&lt;p&gt;&lt;input type=button value=&quot;&amp;#x1F4F7;&quot; onclick=&quot;snapshot()&quot;&gt;
&lt;/section&gt;
&lt;script&gt;
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);
}
&lt;/script&gt;
&lt;/article&gt;
</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 &quot;new <code title="dom-PeerConnection"><a href="#dom-peerconnection">PeerConnection</a></code>(<var title="">configuration</var>,
<var title="">signalingCallback</var>)&quot; 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>&quot;<code title="&quot;&quot;"><var title="">TYPE</var> 203.0.113.2:3478</code>&quot;</dt>
<dd>
<p>Indicates a specific IP address and port for the server.</p>
</dd>
<dt>&quot;<code title="&quot;&quot;"><var title="">TYPE</var> relay.example.net:3478</code>&quot;&quot;</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>&quot;<code title="&quot;&quot;"><var title="">TYPE</var> example.net</code>&quot;&quot;</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 &quot;<code title="&quot;&quot;"><var title="">TYPE</var></code>&quot; is one of:</p>
<dl>
<dt><code title="&quot;&quot;">STUN</code></dt>
<dd>Indicates a STUN server</dd>
<dt><code title="&quot;&quot;">STUNS</code></dt>
<dd>Indicates a STUN server that is to be contacted using a TLS session.</dd>
<dt><code title="&quot;&quot;">TURN</code></dt>
<dd>Indicates a TURN server</dd>
<dt><code title="&quot;&quot;">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>&quot;<code title="">STUN</code>&quot;</li>
<li>&quot;<code title="">STUNS</code>&quot;</li>
<li>&quot;<code title="">TURN</code>&quot;</li>
<li>&quot;<code title="">TURNS</code>&quot;</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 &quot;<code title="">TURN</code>&quot; or
&quot;<code title="">TURNS</code>&quot;).</p>
</li>
<li>
<p>Let <var title="">secure</var> be true if the first component of <var title="">configuration components</var> is &quot;<code title="">STUNS</code>&quot; or
&quot;<code title="">TURNS</code>&quot;, 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
(&quot;<code title="">a=label:</code>&quot;) 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
(&quot;<code title="">a=label:</code>&quot;). [<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="&quot;&quot;">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
&quot;<code title="">SDP</code>&quot; 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 &lt;video&gt; 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 &amp; email address to contact for further information:</dt>
<dd>Daniel C. Burnett &lt;dburnett@voxeo.com&gt;</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 &lt;dburnett@voxeo.com&gt;</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>