HTML5 Tracker

Diff (omit for latest revision)
Filter

Short URL: http://html5.org/r/6275

SVNBugCommentTime (UTC)
627512530[Gecko] [Internet Explorer] [Opera] [Webkit] Revamp how audioTracks and videoTracks work on HTMLMediaElement and MediaStream.2011-06-30 23:52
Index: source
===================================================================
--- source	(revision 6274)
+++ source	(revision 6275)
@@ -2498,9 +2498,10 @@
     specification. <a href="#refsWEBIDL">[WEBIDL]</a></p>
 
     <p>The terms <dfn>supported property indices</dfn>, <dfn>supported
-    property names</dfn>, and <dfn title="dfn-read-only-array">read
-    only</dfn> (when applied to arrays) are used as defined in the
-    WebIDL specification.</p>
+    property names</dfn>, <dfn>determine the value of an indexed
+    property</dfn>, <dfn>array host objects</dfn>, and <dfn
+    title="dfn-read-only-array">read only</dfn> (when applied to
+    arrays) are used as defined in the WebIDL specification.</p>
 
     <p id="float-nan">Except where otherwise specified, if an IDL
     attribute that is a floating point number type (<code
@@ -29068,9 +29069,9 @@
            attribute boolean <span title="dom-media-defaultMuted">defaultMuted</span>;
 
   // tracks
-  readonly attribute <span>MultipleTrackList</span> <span title="dom-media-audioTracks">audioTracks</span>;
-  readonly attribute <span>ExclusiveTrackList</span> <span title="dom-media-videoTracks">videoTracks</span>;
-  readonly attribute <span>TextTrack</span>[] <span title="dom-media-textTracks">textTracks</span>;
+  readonly attribute <span>AudioTrackList</span> <span title="dom-media-audioTracks">audioTracks</span>;
+  readonly attribute <span>VideoTrackList</span> <span title="dom-media-videoTracks">videoTracks</span>;
+  readonly attribute <span>TextTrackList</span> <span title="dom-media-textTracks">textTracks</span>;
   <span>MutableTextTrack</span> <span title="dom-media-addTextTrack">addTextTrack</span>(in DOMString kind, in optional DOMString label, in optional DOMString language);
 };</pre>
 
@@ -32124,9 +32125,7 @@
 
   </div>
 
-<!--START rtc--><!--PEERCONNECTION-->
   <h5>Media resources with multiple media tracks</h5>
-<!--END rtc--><!--PEERCONNECTION-->
 
   <p>A <span>media resource</span> can have multiple embedded audio
   and video tracks. For example, in addition to the primary video and
@@ -32140,7 +32139,7 @@
 
    <dd>
 
-    <p>Returns a <code>MultipleTrackList</code> object representing
+    <p>Returns an <code>AudioTrackList</code> object representing
     the audio tracks available in the <span>media resource</span>.</p>
 
    </dd>
@@ -32149,7 +32148,7 @@
 
    <dd>
 
-    <p>Returns an <code>ExclusiveTrackList</code> object representing
+    <p>Returns an <code>VideoTrackList</code> object representing
     the video tracks available in the <span>media resource</span>.</p>
 
    </dd>
@@ -32161,7 +32160,7 @@
   <p>The <dfn
   title="dom-media-audioTracks"><code>audioTracks</code></dfn>
   attribute of a <span>media element</span> must return a
-  <span>live</span> <code>MultipleTrackList</code> object representing
+  <span>live</span> <code>AudioTrackList</code> object representing
   the audio tracks available in the <span>media element</span>'s
   <span>media resource</span>. The same object must be returned each
   time.</p>
@@ -32169,16 +32168,17 @@
   <p>The <dfn
   title="dom-media-videoTracks"><code>videoTracks</code></dfn>
   attribute of a <span>media element</span> must return a
-  <span>live</span> <code>ExclusiveTrackList</code> object
+  <span>live</span> <code>VideoTrackList</code> object
   representing the video tracks available in the <span>media
   element</span>'s <span>media resource</span>. The same object must
   be returned each time.</p>
 
-  <p class="note">There are only ever two <code>TrackList</code>
-  objects (one <code>MultipleTrackList</code> object and one
-  <code>ExclusiveTrackList</code> object) per <span>media
+  <p class="note">There are only ever one <code>AudioTrackList</code>
+  object and one <code>VideoTrackList</code> object per <span>media
   element</span>, even if another <span>media resource</span> is
-  loaded into the element: the objects are reused.</p>
+  loaded into the element: the objects are reused. (The
+  <code>AudioTrack</code> and <code>VideoTrack</code> objects are
+  not, though.)</p>
 
   </div>
 
@@ -32203,9 +32203,9 @@
    container.appendChild(video);
    video.onloadedmetadata = function (event) {
      for (var i = 0; i &lt; video.videoTracks.length; i += 1) {
-       if (video.videoTracks.getKind(i) == 'sign') {
+       if (video.videoTracks[i].kind == 'sign') {
          var sign = document.createElement('video');
-         sign.src = url + '#track=' + video.videoTracks.getID(i);
+         sign.src = url + '#track=' + video.videoTracks[i].id; <!-- should escape this probably -->
          sign.autoplay = true;
          sign.controller = controller;
          container.appendChild(sign);
@@ -32219,44 +32219,47 @@
   </div>
 
 
-<!--START rtc--><!--PEERCONNECTION-->
-  <h6><code>TrackList</code> objects</h6>
+  <h6><code>AudioTrackList</code> and <code>VideoTrackList</code> objects</h6>
 
-  <!-- should probably move this section out since it is also used by
-  the video conferencing stuff -->
+  <p>The <code>AudioTrackList</code> and <code>VideoTrackList</code>
+  interfaces are used by attributes defined in the previous
+  section.</p>
 
-<!--END rtc--><!--PEERCONNECTION-->
-  <p>The <code>MultipleTrackList</code> and
-  <code>ExclusiveTrackList</code> interfaces, used by the attributes
-  defined in the previous section, are substantially similar. Their
-  common features are defined in the <code>TrackList</code> interface,
-  from which they both inherit.</p>
-<!--START rtc--><!--PEERCONNECTION-->
+  <pre class="idl">interface <dfn>AudioTrackList</dfn> {
+  readonly attribute unsigned long <span title="dom-AudioTrackList-length">length</span>;
+  getter <span>AudioTrack</span> (in unsigned long index);
+  <span>AudioTrack</span>? <span title="dom-AudioTrackList-getTrackById">getTrackById</span>(in DOMString id);
+           attribute <span>Function</span>? <span title="handler-TrackList-onchange">onchange</span>;
+};
 
-  <pre class="idl">interface <dfn>TrackList</dfn> {
-  readonly attribute unsigned long <span title="dom-TrackList-length">length</span>;
-  DOMString <span title="dom-TrackList-getID">getID</span>(in unsigned long index);
-  DOMString <span title="dom-TrackList-getKind">getKind</span>(in unsigned long index);
-  DOMString <span title="dom-TrackList-getLabel">getLabel</span>(in unsigned long index);
-  DOMString <span title="dom-TrackList-getLanguage">getLanguage</span>(in unsigned long index);
+interface <dfn>AudioTrack</dfn> {
+  readonly attribute DOMString <span title="dom-AudioTrack-id">id</span>;
+  readonly attribute DOMString <span title="dom-AudioTrack-kind">kind</span>;
+  readonly attribute DOMString <span title="dom-AudioTrack-label">label</span>;
+  readonly attribute DOMString <span title="dom-AudioTrack-language">language</span>;
+           attribute boolean <span title="dom-AudioTrack-enabled">enabled</span>;
+};
 
+interface <dfn>VideoTrackList</dfn> {
+  readonly attribute unsigned long <span title="dom-VideoTrackList-length">length</span>;
+  getter <span>VideoTrack</span> (in unsigned long index);
+  <span>VideoTrack</span>? <span title="dom-VideoTrackList-getTrackById">getTrackById</span>(in DOMString id);
+  readonly attribute long <span title="dom-VideoTrackList-selectedIndex">selectedIndex</span>;
            attribute <span>Function</span>? <span title="handler-TrackList-onchange">onchange</span>;
 };
 
-interface <dfn>MultipleTrackList</dfn> : <span>TrackList</span> {
-  boolean <span title="dom-TrackList-isEnabled">isEnabled</span>(in unsigned long index);
-  void <span title="dom-TrackList-enable">enable</span>(in unsigned long index);
-  void <span title="dom-TrackList-disable">disable</span>(in unsigned long index);
-};
-
-interface <dfn>ExclusiveTrackList</dfn> : <span>TrackList</span> {
-  readonly attribute long <span title="dom-TrackList-selectedIndex">selectedIndex</span>;
-  void <span title="dom-TrackList-select">select</span>(in unsigned long index);
+interface <dfn>VideoTrack</dfn> {
+  readonly attribute DOMString <span title="dom-VideoTrack-id">id</span>;
+  readonly attribute DOMString <span title="dom-VideoTrack-kind">kind</span>;
+  readonly attribute DOMString <span title="dom-VideoTrack-label">label</span>;
+  readonly attribute DOMString <span title="dom-VideoTrack-language">language</span>;
+           attribute boolean <span title="dom-VideoTrack-selected">selected</span>;
 };</pre>
 
   <dl class="domintro">
 
-   <dt><var title="">tracks</var> . <code title="dom-TrackList-length">length</code></dt>
+   <dt><var title="">media</var> . <code title="dom-media-audioTracks">audioTracks</code> . <code title="dom-AudioTrackList-length">length</code></dt>
+   <dt><var title="">media</var> . <code title="dom-media-videoTracks">videoTracks</code> . <code title="dom-VideoTrackList-length">length</code></dt>
 
    <dd>
 
@@ -32264,66 +32267,75 @@
 
    </dd>
 
-   <dt><var title="">id</var> = <var title="">tracks</var> . <code title="dom-TrackList-getID">getID</code>( <var title="">index</var> )</dt>
+   <dt><var title="">audioTrack</var> = <var title="">media</var> . <code title="dom-media-audioTracks">audioTracks</code>[<var title="">index</var>]</dt>
+   <dt><var title="">videoTrack</var> = <var title="">media</var> . <code title="dom-media-videoTracks">videoTracks</code>[<var title="">index</var>]</dt>
 
    <dd>
 
-    <p>Returns the ID of the given track. This is the ID that can be
-    used with a fragment identifier if the format supports the
-    <cite>Media Fragments URI</cite> syntax. <a
-    href="#hrefMEDIAFRAG">[MEDIAFRAG]</a></p>
+    <p>Returns the specified <code>AudioTrack</code> or <code>VideoTrack</code> object.</p>
 
    </dd>
 
-   <dt><var title="">kind</var> = <var title="">tracks</var> . <code title="dom-TrackList-getKind">getKind</code>( <var title="">index</var> )</dt>
+   <dt><var title="">audioTrack</var> = <var title="">media</var> . <code title="dom-media-audioTracks">audioTracks</code> . <code title="dom-AudioTrackList-getTrackById">getTrackById</code>( <var title="">id</var> )</dt>
+   <dt><var title="">videoTrack</var> = <var title="">media</var> . <code title="dom-media-videoTracks">videoTracks</code> . <code title="dom-VideoTrackList-getTrackById">getTrackById</code>( <var title="">id</var> )</dt>
 
    <dd>
 
-    <p>Returns the category the given track falls into. The <a href="#dom-TrackList-getKind-categories">possible track categories</a> are given below.</p>
+    <p>Returns the <code>AudioTrack</code> or <code>VideoTrack</code> object with the given identifier, or null if no track has that identifier.</p>
 
    </dd>
 
-   <dt><var title="">label</var> = <var title="">tracks</var> . <code title="dom-TrackList-getLabel">getLabel</code>( <var title="">index</var> )</dt>
+   <dt><var title="">audioTrack</var> . <code title="dom-AudioTrack-id">id</code></dt>
+   <dt><var title="">videoTrack</var> . <code title="dom-VideoTrack-id">id</code></dt>
 
    <dd>
 
-    <p>Returns the label of the given track, if known, or the empty string otherwise.</p>
+    <p>Returns the ID of the given track. This is the ID that can be
+    used with a fragment identifier if the format supports the
+    <cite>Media Fragments URI</cite> syntax, and that can be used with
+    the <code title="">getTrackById()</code> method. <a
+    href="#hrefMEDIAFRAG">[MEDIAFRAG]</a></p>
 
    </dd>
 
-   <dt><var title="">language</var> = <var title="">tracks</var> . <code title="dom-TrackList-getLanguage">getLanguage</code>( <var title="">index</var> )</dt>
+   <dt><var title="">audioTrack</var> . <code title="dom-AudioTrack-kind">kind</code></dt>
+   <dt><var title="">videoTrack</var> . <code title="dom-VideoTrack-kind">kind</code></dt>
 
    <dd>
 
-    <p>Returns the language of the given track, if known, or the empty string otherwise.</p>
+    <p>Returns the category the given track falls into. The <a href="#dom-TrackList-getKind-categories">possible track categories</a> are given below.</p>
 
    </dd>
 
-   <dt><var title="">enabled</var> = <var title="">audioTracks</var> . <code title="dom-TrackList-isEnabled">isEnabled</code>( <var title="">index</var> )</dt>
+   <dt><var title="">audioTrack</var> . <code title="dom-AudioTrack-label">label</code></dt>
+   <dt><var title="">videoTrack</var> . <code title="dom-VideoTrack-label">label</code></dt>
 
    <dd>
 
-    <p>Returns true if the given track is active, and false otherwise.</p>
+    <p>Returns the label of the given track, if known, or the empty string otherwise.</p>
 
    </dd>
 
-   <dt><var title="">audioTracks</var> . <code title="dom-TrackList-enable">enable</code>( <var title="">index</var> )</dt>
+   <dt><var title="">audioTrack</var> . <code title="dom-AudioTrack-language">language</code></dt>
+   <dt><var title="">videoTrack</var> . <code title="dom-VideoTrack-language">language</code></dt>
 
    <dd>
 
-    <p>Enables the given track.</p>
+    <p>Returns the language of the given track, if known, or the empty string otherwise.</p>
 
    </dd>
 
-   <dt><var title="">audioTracks</var> . <code title="dom-TrackList-disable">disable</code>( <var title="">index</var> )</dt>
+   <dt><var title="">audioTrack</var> . <code title="dom-AudioTrack-enabled">enabled</code> [ = <var title="">value</var> ]</dt>
 
    <dd>
 
-    <p>Disables the given track.</p>
+    <p>Returns true if the given track is active, and false otherwise.</p>
 
+    <p>Can be set, to change whether the track is enabled or not. If multiple audio tracks are enabled simultaneously, they are mixed.</p>
+
    </dd>
 
-   <dt><var title="">videoTracks</var> . <code title="dom-TrackList-selectedIndex">selectedIndex</code></dt>
+   <dt><var title="">media</var> . <code title="dom-media-videoTracks">videoTracks</code> . <code title="dom-VideoTrackList-selectedIndex">selectedIndex</code></dt>
 
    <dd>
 
@@ -32331,46 +32343,120 @@
 
    </dd>
 
-   <dt><var title="">videoTracks</var> . <code title="dom-TrackList-select">select</code>( <var title="">index</var> )</dt>
+   <dt><var title="">videoTrack</var> . <code title="dom-VideoTrack-selected">selected</code> [ = <var title="">value</var> ]</dt>
 
    <dd>
 
-    <p>Selects the given track.</p>
+    <p>Returns true if the given track is active, and false otherwise.</p>
 
+    <p>Can be set, to change whether the track is selected or not. Either zero or one video track is selected; selecting a new track while a previous one is selected will unselect the previous one.</p>
+
    </dd>
 
   </dl>
 
   <div class="impl">
 
-  <p>The <dfn title="dom-TrackList-length"><code>length</code></dfn>
-  attribute must return the number of tracks represented by the
-  <code>TrackList</code> object at the time of getting.</p>
+  <p>An <code>AudioTrackList</code> object represents a dynamic list
+  of zero or more audio tracks, of which zero or more can be enabled
+  at a time. Each audio track is represented by an
+  <code>AudioTrack</code> object.</p>
 
-  <p>Tracks in a <code>TrackList</code> object must be consistently
-  ordered. If the <span>media resource</span> is in a format that
-  defines an order, then that order must be used; otherwise, the order
-  must be the relative order in which the tracks are declared in the
-  <span>media resource</span>. Each track in a <code>TrackList</code>
-  thus has an index; the first has the index 0, and each subsequent
-  track is numbered one higher than the previous one.</p>
+  <p>A <code>VideoTrackList</code> object represents a dynamic list of
+  zero or more video tracks, of which zero or one can be selected at a
+  time. Each video track is represented by a <code>VideoTrack</code>
+  object.</p>
 
-  <p>The <dfn title="dom-TrackList-getID"><code>getID(<var
-  title="">index</var>)</code></dfn> method must return the identifier
-  of the track with index <var title="">index</var>, if there is one.
-  If there is no such track, then the method must instead throw an
-  <code>INDEX_SIZE_ERR</code> exception. If the <span>media
-  resource</span> is in a format that supports the <cite>Media
-  Fragments URI</cite> fragment identifier syntax, the returned
-  identifier must be the same identifier that would enable the track
-  if used as the name of a track in the track dimension of such a
+  <p>Tracks in <code>AudioTrackList</code> and
+  <code>VideoTrackList</code> objects must be consistently ordered. If
+  the <span>media resource</span> is in a format that defines an
+  order, then that order must be used; otherwise, the order must be
+  the relative order in which the tracks are declared in the
+  <span>media resource</span>. The order used is called the <i>natural
+  order</i> of the list.</p>
+
+  <p class="note">Each track in a <code>TrackList</code> thus has an
+  index; the first has the index 0, and each subsequent track is
+  numbered one higher than the previous one. If a <span>media
+  resource</span> dynamically adds or removes audio or video tracks,
+  then the indices of the tracks will change dynamically. If the
+  <span>media resource</span> changes entirely, then all the previous
+  tracks will be removed and replaced with new tracks.</p>
+
+  <p>The <dfn
+  title="dom-AudioTrackList-length"><code>AudioTrackList.length</code></dfn>
+  and <dfn
+  title="dom-VideoTrackList-length"><code>VideoTrackList.length</code></dfn>
+  attributes must return the number of tracks represented by their
+  objects at the time of getting.</p>
+
+  <p>The <span>supported property indices</span> of
+  <code>AudioTrackList</code> and <code>VideoTrackList</code> objects
+  at any instant are the numbers from zero to the number of tracks
+  represented by the respective object minus one, if any tracks are
+  represented. If a <code>AudioTrackList</code> or
+  <code>VideoTrackList</code> object represents no tracks, it has no
+  <span>supported property indices</span>.</p>
+
+  <p>To <span>determine the value of an indexed property</span> for a
+  given index <var title="">index</var> in an
+  <code>AudioTrackList</code> or <code>VideoTrackList</code> object
+  <var title="">list</var>, the user agent must return the
+  <code>AudioTrack</code> or <code>VideoTrack</code> object that
+  represents the <var title="">index</var>th track in <var
+  title="">list</var>.</p>
+
+  <p>The <dfn
+  title="dom-AudioTrackList-getTrackById"><code>AudioTrackList.getTrackById(<var
+  title="">id</var>)</code></dfn> and <dfn
+  title="dom-VideoTrackList-getTrackById"><code>VideoTrackList.getTrackById(<var
+  title="">id</var>)</code></dfn> methods must return the first
+  <code>AudioTrack</code> or <code>VideoTrack</code> object
+  (respectively) in the <code>AudioTrack</code> or
+  <code>VideoTrack</code> object (respectively) whose identifier is
+  equal to the value of the <var title="">id</var> argument (in the
+  natural order of the list, as defined above). When no tracks match
+  the given argument, the methods must return null.</p>
+
+  <p>The <code>AudioTrack</code> and <code>VideoTrack</code> objects
+  represent specific tracks of a <span>media resource</span>. Each
+  track can have an identifier, category, label, and language. These
+  aspects of a track are permanent for the lifetime of the track; even
+  if a track is removed from a <span>media resource</span>'s
+  <code>AudioTrackList</code> or <code>VideoTrackList</code> objects,
+  those aspects do not change.</p>
+
+  <p>In addition, <code>AudioTrack</code> objects can each be enabled
+  or disabled; this is the audio track's <i>enabled state</i>. When an
+  <code>AudioTrack</code> is created, its <i>enabled state</i> must be
+  set to false (disabled). The <span
+  title="concept-media-load-resource">resource fetch algorithm</span>
+  can override this.</p>
+
+  <p>Similarly, a single <code>VideoTrack</code> object per
+  <code>VideoTrackList</code> object can be selected, this is the
+  video track's <i>selection state</i>. When an
+  <code>VideoTrack</code> is created, its <i>selection state</i> must
+  be set to false (not selected). The <span
+  title="concept-media-load-resource">resource fetch algorithm</span>
+  can override this.</p>
+
+  <p>The <dfn
+  title="dom-AudioTrack-id"><code>AudioTrack.id</code></dfn> and <dfn
+  title="dom-VideoTrack-id"><code>VideTrack.id</code></dfn>
+  attributes must return the identifier of the track, if it has one,
+  or the empty string otherwise. If the <span>media resource</span> is
+  in a format that supports the <cite>Media Fragments URI</cite>
+  fragment identifier syntax, the identifier returned for a particular
+  track must be the same identifier that would enable the track if
+  used as the name of a track in the track dimension of such a
   fragment identifier. <a href="#refsMEDIAFRAG">[MEDIAFRAG]</a></p>
 
-  <p>The <dfn title="dom-TrackList-getKind"><code>getKind(<var
-  title="">index</var>)</code></dfn> method must return the category
-  of the track with index <var title="">index</var>, if there is one.
-  If there is no such track, then the method must instead throw an
-  <code>INDEX_SIZE_ERR</code> exception.</p>
+  <p>The <dfn
+  title="dom-AudioTrack-kind"><code>AudioTrack.kind</code></dfn> and
+  <dfn title="dom-VideoTrack-kind"><code>VideoTrack.kind</code></dfn>
+  attributes must return the category of the track, if it has one, or
+  the empty string otherwise.</p>
 
   <p>The category of a track is the string given in the first column
   of the table below that is the most appropriate for the track based
@@ -32381,12 +32467,15 @@
   what the category given in the cell in the first column of that row
   applies to; a category is only appropriate for an audio track if it
   applies to audio tracks, and a category is only appropriate for
-  video tracks if it applies to video tracks.</p>
+  video tracks if it applies to video tracks. Categories must only be
+  returned for <code>AudioTrack</code> objects if they are appropriate
+  for audio, and must only be returned for <code>VideoTrack</code>
+  objects if they are appropriate for video.</p>
 
   </div>
 
   <table id="dom-TrackList-getKind-categories">
-   <caption>Return values for <code title="dom-TrackList-getKind">getKind()</code></caption>
+   <caption>Return values for <code title="dom-AudioTrack-kind">AudioTrack.kind()</code> and <code title="dom-VideoTrack-kind">VideoTrack.kind()</code></caption>
    <thead>
     <tr>
      <th>Category
@@ -32396,37 +32485,43 @@
    <tbody>
 
     <tr>
-     <td>"<dfn title="dom-TrackList-getKind-alternate"><code>alternative</code></dfn>"
+     <td>"<dfn title="value-track-kind-alternate"><code>alternative</code></dfn>"
      <td>A possible alternative to the main track, e.g. a different take of a song (audio), or a different angle (video).
      <td>Audio and video.
      <td>Ogg: "audio/alterate" or "video/alternate".
 
     <tr>
-     <td>"<dfn title="dom-TrackList-getKind-description"><code>description</code></dfn>"
+     <td>"<dfn title="value-track-kind-description"><code>description</code></dfn>"
      <td>An audio description of a video track.
      <td>Audio only.
      <td>Ogg: "audio/audiodesc".
 
     <tr>
-     <td>"<dfn title="dom-TrackList-getKind-main"><code>main</code></dfn>"
+     <td>"<dfn title="value-track-kind-main"><code>main</code></dfn>"
      <td>The primary audio or video track.
      <td>Audio and video.
      <td>Ogg: "audio/main" or "video/main"; WebM: the "FlagDefault" element is set.
 
     <tr>
-     <td>"<dfn title="dom-TrackList-getKind-sign"><code>sign</code></dfn>"
+     <td>"<dfn title="value-track-kind-sign"><code>sign</code></dfn>"
      <td>A sign-language interpretation of an audio track.
      <td>Video only.
      <td>Ogg: "video/sign".
 
     <tr>
-     <td>"<dfn title="dom-TrackList-getKind-translation"><code>translation</code></dfn>"
+     <td>"<dfn title="value-track-kind-translation"><code>translation</code></dfn>"
      <td>A translated version of the main track.
      <td>Audio only.
      <td>Ogg: "audio/dub".
 
+    <tr> <!-- added because of the volume of use cases, but we should remove it if none of the formats start supporting it -->
+     <td>"<dfn title="value-track-kind-commentary"><code>commentary</code></dfn>"
+     <td>Commentary on the primary audio or video track, e.g. a director's commentary.
+     <td>Audio and video.
+     <td>No known formats expose this category at this time.
+
     <tr>
-     <td>"<dfn title="dom-TrackList-getKind-none"><code></code></dfn>" (empty string)
+     <td>"<dfn title="value-track-kind-none"><code></code></dfn>" (empty string)
      <td>No explicit kind, or the kind given by the track's metadata is not recognised by the user agent.
      <td>Audio and video.
      <td>Any other track type or track role.
@@ -32435,85 +32530,72 @@
 
   <div class="impl">
 
-  <p>The <dfn title="dom-TrackList-getLabel"><code>getLabel(<var
-  title="">index</var>)</code></dfn> method must return the label of
-  the track with index <var title="">index</var>, if there is one and
-  it has a label. If there is no such track, then the method must
-  instead throw an <code>INDEX_SIZE_ERR</code> exception. If there is
-  a track with index <var title="">index</var>, but it has no label,
-  then the method must return the empty string.</p>
+  <p>The <dfn
+  title="dom-AudioTrack-label"><code>AudioTrack.label</code></dfn> and
+  <dfn
+  title="dom-VideoTrack-label"><code>VideoTrack.label</code></dfn>
+  attributes must return the label of the track, if it has one, or the
+  empty string otherwise.</p>
 
-  <p>The <dfn title="dom-TrackList-getLanguage"><code>getLanguage(<var
-  title="">index</var>)</code></dfn> method must return the BCP 47
-  language tag of the language of the track with index <var
-  title="">index</var>, if there is one and it has a language. If
-  there is no such track, then the method must instead throw an
-  <code>INDEX_SIZE_ERR</code> exception. If there is a track with
-  index <var title="">index</var>, but it has no language, or the user
+  <p>The <dfn
+  title="dom-AudioTrack-language"><code>AudioTrack.language</code></dfn>
+  and <dfn
+  title="dom-VideoTrack-language"><code>VideoTrack.language</code></dfn>
+  attributes must return the BCP 47 language tag of the language of
+  the track, if it has one, or the empty string otherwise. If the user
   agent is not able to express that language as a BCP 47 language tag
   (for example because the language information in the <span>media
   resource</span>'s format is a free-form string without a defined
-  interpretation), then the method must return the empty string.</p>
+  interpretation), then the method must return the empty string, as if
+  the track had no language.</p>
 
-  <hr>
+  <p>The <dfn
+  title="dom-AudioTrack-enabled"><code>AudioTrack.enabled</code></dfn>
+  attribute, on getting, must return true if the track is currently
+  enabled, and false otherwise. On setting, it must enable the track
+  if the new value is true, and disable it otherwise. (If the track is
+  no longer in an <code>AudioTrackList</code> object, then the track
+  being enabled or disabled has no effect beyond changing the value of
+  the attribute on the <code>AudioTrack</code> object.)</p>
 
-  <p>A <code>MultipleTrackList</code> object represents a track list
-  where multiple tracks can be enabled simultaneously. Each track is
-  either enabled or disabled.</p>
+  <p>Whenever an audio track in an <code>AudioTrackList</code> is
+  enabled or disabled, the user agent must <span>queue a task</span>
+  to <span>fire a simple event</span> named <code
+  title="event-media-change">change</code> at the
+  <code>AudioTrackList</code> object.</p>
 
-  <p>The <dfn title="dom-TrackList-isEnabled"><code>isEnabled(<var
-  title="">index</var>)</code></dfn> method must return true if there
-  is a track with index <var title="">index</var>, and it is currently
-  enabled, false if there is a track with index <var
-  title="">index</var>, but it is currently disabled, and must throw
-  an <code>INDEX_SIZE_ERR</code> exception if there is no track with
-  index <var title="">index</var>.</p>
+  <p>The <dfn
+  title="dom-VideoTrackList-selectedIndex"><code>VideoTrackList.selectedIndex</code></dfn>
+  attribute must return the index of the currently selected track, if
+  any. If the <code>VideoTrackList</code> object does not currently
+  represent any tracks, or if none of the tracks are selected, it must
+  instead return &#x2212;1.</p>
 
-  <p>The <dfn title="dom-TrackList-enable"><code>enable(<var
-  title="">index</var>)</code></dfn> method must enable the track with
-  index <var title="">index</var>, if there is one. If there is not,
-  it must instead throw an <code>INDEX_SIZE_ERR</code> exception.</p>
-
-  <p>The <dfn title="dom-TrackList-disable"><code>disable(<var
-  title="">index</var>)</code></dfn> method must disable the track with
-  index <var title="">index</var>, if there is one. If there is not,
-  it must instead throw an <code>INDEX_SIZE_ERR</code> exception.</p>
-
-  <p>Whenever a track is enabled or disabled, the user agent must
-  <span>queue a task</span> to <span>fire a simple event</span> named
-  <code title="event-media-change">change</code> at the
-  <code>MultipleTrackList</code> object.</p>
-
-  <hr>
-
-  <p>An <code>ExclusiveTrackList</code> object represents a track list
-  where exactly one track is selected at a time.</p>
-
   <p>The <dfn
-  title="dom-TrackList-selectedIndex"><code>selectedIndex</code></dfn>
-  attribute must return the index of the currently selected track. If
-  the <code>ExclusiveTrackList</code> object does not represent any
-  tracks, it must instead return &#x2212;1.</p>
+  title="dom-VideoTrack-selected"><code>VideoTrack.selected</code></dfn>
+  attribute, on getting, must return true if the track is currently
+  selected, and false otherwise. On setting, it must select the track
+  if the new value is true, and unselect it otherwise. If the track is
+  in a <code>VideoTrackList</code>, then all the other
+  <code>VideoTrack</code> objects in that list must be unselected. (If
+  the track is no longer in a <code>VideoTrackList</code> object, then
+  the track being selected or unselected has no effect beyond changing
+  the value of the attribute on the <code>VideoTrack</code>
+  object.)</p>
 
-  <p>The <dfn title="dom-TrackList-select"><code>select(<var
-  title="">index</var>)</code></dfn> must select the track with index
-  <var title="">index</var>, if there is one, unselecting whichever
-  track was previously selected. If there is no track with index <var
-  title="">index</var>, it must instead throw an
-  <code>INDEX_SIZE_ERR</code> exception.</p>
+  <p>Whenever a track in a <code>VideoTrackList</code> that was
+  previously not selected is selected, the user agent must <span>queue
+  a task</span> to <span>fire a simple event</span> named <code
+  title="event-media-change">change</code> at the
+  <code>VideoTrackList</code> object.</p>
 
-  <p>Whenever the selected track is changed, the user agent must
-  <span>queue a task</span> to <span>fire a simple event</span> named
-  <code title="event-media-change">change</code> at the
-  <code>MultipleTrackList</code> object.</p>
-
   <hr>
 
   <p>The following are the <span>event handlers</span> (and their
   corresponding <span title="event handler event type">event handler
   event types</span>) that must be supported, as IDL attributes, by
-  all objects implementing the <code>TrackList</code>
-  interface:</p>
+  all objects implementing the <code>AudioTrackList</code> and
+  <code>VideoTrackList</code> interfaces:</p>
 
   <table>
    <thead>
@@ -32562,7 +32644,6 @@
    selection -->
 
   </div>
-<!--END rtc--><!--PEERCONNECTION-->
 
 
   <h5>Synchronising multiple media elements</h5>
@@ -34448,8 +34529,10 @@
 
            attribute <span>Function</span>? <span title="handler-TextTrack-oncuechange">oncuechange</span>;
 };
-<span>TextTrack</span> implements <span>EventTarget</span>;</pre>
+<span>TextTrack</span> implements <span>EventTarget</span>;
 
+typedef <span>TextTrack</span>[] <dfn>TextTrackList</dfn>;</pre>
+
   <dl class="domintro">
 
    <dt><var title="">textTrack</var> . <code title="dom-TextTrack-kind">kind</code></dt>
@@ -34881,13 +34964,13 @@
   cue">cues</span> in the list represented by the
   <code>TextTrackCueList</code> object.</p>
 
-  <p>The <span>supported property indicies</span> of a
+  <p>The <span>supported property indices</span> of a
   <code>TextTrackCueList</code> object at any instant are the numbers
   from zero to the number of <span title="text track cue">cues</span>
   in the list represented by the <code>TextTrackCueList</code> object
   minus one, if any. If there are no <span title="text track
   cue">cues</span> in the list, there are no <span>supported property
-  indicies</span>.</p>
+  indices</span>.</p>
 
   <p>To <span>determine the value of an indexed property</span> for a
   given index <var title="">index</var>, the user agent must return
@@ -85503,14 +85586,14 @@
     stream.</p>
 
     <p>If <var title="">audio</var> is true, then the provided media
-    should include an audio component. If <var title="">audio</var>
+    should include an audio track. If <var title="">audio</var>
     is false, then the provided media must not include an audio
-    component.</p>
+    track.</p>
 
     <p>If <var title="">video</var> is true, then the provided media
-    should include a video component. If <var title="">video</var> is
+    should include a video track. If <var title="">video</var> is
     false, then the provided media must not include a video
-    component.</p>
+    track.</p>
 
     <p>User agents are encouraged to default to using the user's
     primary or system default camera and/or microphone (as
@@ -85611,6 +85694,8 @@
 
   <h3>Stream API</h3>
 
+  <h4>Introduction</h4>
+
   <p>The <code>MediaStream</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
@@ -85620,6 +85705,322 @@
   user agents to manipulate media streams in whatever fashion is most
   suitable on the user's platform.</p>
 
+  <p>Each <code>MediaStream</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>MediaStream</code> object has a
+  corresponding <code>StreamTrack</code> object.</p>
+
+  <p>A <code>MediaStream</code> object has an input and an output. The
+  input depends on how the object was created: a
+  <code>LocalMediaStream</code> object generated by a <code
+  title="dom-navigator-getUserMedia">getUserMedia()</code> call, for
+  instance, might take its input from the user's local camera, while a
+  <code>MediaStream</code> created by a <code>PeerConnection</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>PeerConnection</code> object.</p>
+
+  <p>Each track in a <code>MediaStream</code> object can be disabled,
+  meaning that it does not appear in the object's output. All tracks
+  are initially enabled.</p>
+
+  <p>A <code>MediaStream</code> object's output can be "forked" by
+  creating a new <code>MediaStream</code> object from it using the
+  <code title="dom-MediaStream">MediaStream()</code> constructor. The
+  new <code>MediaStream</code> object's input is the output of the
+  object from which it was created, and its output is therefore at
+  most a subset of the "parent" object.</p>
+
+  <p><img src="images/media-stream-1.png" alt=""></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>This can be used, for instance, in a video-conferencing scenario
+  to display the local video from the user's camera and microphone in
+  a local monitor, while only transmitting the audio to the remote
+  peer (e.g. in response to the user using a "video mute"
+  feature).</p>
+
+  <p><img src="images/media-stream-2.png" alt=""></p><!-- again, 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);
+    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>If a track in a <code>MediaStream</code> <var
+  title="">parent</var> is disabled, it does not have a corresponding
+  track in any <code>MediaStream</code> objects that were created from
+  <var title="">parent</var>. When a track in a
+  <code>MediaStream</code> <var title="">parent</var> is disabled, any
+  <code>StreamTrack</code> objects corresponding to the tracks in any
+  <code>MediaStream</code> objects that were created from <var
+  title="">parent</var> are disassociated from any track, and must not
+  be reused for tracks again. If a disabled track in a
+  <code>MediaStream</code> <var title="">parent</var> is re-enabled,
+  from the perspective of any <code>MediaStream</code> objects that
+  were created from <var title="">parent</var> it is a new track and
+  thus new <code>StreamTrack</code> objects must be created for the
+  tracks that correspond to the re-enabled track.</p>
+
+  <hr>
+
   <p>The <code>LocalMediaStream</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
@@ -85634,14 +86035,20 @@
   live video from pre-recorded video, which can help protect the
   user's privacy.</p>
 
+
+  <h4>Interface definitions</h4>
+
   <!-- v2: support reading the bits from the stream directly, for use
   with streaming over WebSocket? Or do we rely on FileReader for that?
   sicking suggests defining a DataStream or BlobStream interface that
   you can get from a Stream to get to the underlying data; such an
   object would then be readable using the File API -->
 
-  <pre class="idl">interface <dfn>MediaStream</dfn> {
+  <pre class="idl">[<span title="dom-MediaStream">Constructor</span>(in <span>MediaStream</span> parentStream)]
+interface <dfn>MediaStream</dfn> {
   readonly attribute DOMString <span title="dom-MediaStream-label">label</span>;
+  readonly attribute <span>StreamTrackList</span> <span title="dom-MediaStream-tracks">tracks</span>;
+
   <span>MediaStreamRecorder</span> <span title="dom-MediaStream-record">record</span>();
 <!--
   const unsigned short <span title="dom-MediaStream-LOADING">LOADING</span> = 0; -->
@@ -85654,14 +86061,27 @@
 
 interface <dfn>LocalMediaStream</dfn> : <span>MediaStream</span> {
   void <span title="dom-MediaStream-stop">stop</span>();
+};
 
-  // track control
-  readonly attribute <span>MultipleTrackList</span> <span title="dom-MediaStream-audioTracks">audioTracks</span>;
-  readonly attribute <span>ExclusiveTrackList</span> <span title="dom-MediaStream-videoTracks">videoTracks</span>;
+typedef <span>StreamTrack</span>[] <dfn>StreamTrackList</dfn>;
+
+interface <dfn>StreamTrack</dfn> {
+  readonly attribute DOMString <span title="dom-StreamTrack-kind">kind</span>;
+  readonly attribute DOMString <span title="dom-StreamTrack-label">label</span>;
+           attribute boolean <span title="dom-StreamTrack-enabled">enabled</span>;
 };</pre>
 
   <dl class="domintro">
 
+   <dt><var title="">stream</var>  = new <code title="dom-MediaStream">MediaStream</code>( <var title="">parentStream</var> )</dt>
+
+   <dd>
+
+    <p>Creates a new <code>MediaStream</code> object whose tracks are the enabled tracks of <var title="">parentStream</var>.</p>
+
+   </dd>
+
+
    <dt><var title="">stream</var> . <code title="dom-MediaStream-label">label</code></dt>
 
    <dd>
@@ -85693,31 +86113,74 @@
    </dd>
 
 
-   <dt><var title="">stream</var> . <code title="dom-MediaStream-audioTracks">audioTracks</code></dt>
+   <dt><var title="">stream</var> . <code title="dom-MediaStream-tracks">tracks</code></dt>
 
    <dd>
 
-    <p>Returns a <code>MultipleTrackList</code> object representing
-    the audio tracks available for mixing into the
-    <code>LocalMediaStream</code>'s stream.</p>
+    <p>Returns a <code>StreamTrackList</code> object representing
+    the tracks that can be enabled and disabled.</p>
 
    </dd>
 
-   <dt><var title="">stream</var> . <code title="dom-MediaStream-videoTracks">videoTracks</code></dt>
 
+   <dt><var title="">stream</var> . <code title="dom-MediaStream-tracks">tracks</code> . <code title="dom-StreamTrackList-length">length</code></dt>
+
    <dd>
 
-    <p>Returns an <code>ExclusiveTrackList</code> object representing
-    the video tracks available for the <code>LocalMediaStream</code>'s
-    stream.</p>
+    <p>Returns the number of tracks in the list.</p>
 
    </dd>
 
 
+   <dt><var title="">track</var> = <var title="">stream</var> . <code title="dom-MediaStream-tracks">tracks</code>[<var title="">index</var>]</dt>
+
+   <dd>
+
+    <p>Returns the specified <code>StreamTrack</code> object.</p>
+
+   </dd>
+
+
+   <dt><var title="">track</var> . <code title="dom-StreamTrack-label">label</code></dt>
+
+   <dd>
+
+    <p>Returns the string "<code title="">audio</code>" if the track
+    is an audio track, and the string "<code title="">video</code>" if
+    it is a video track.</p>
+
+   </dd>
+
+
+   <dt><var title="">track</var> . <code title="dom-StreamTrack-label">label</code></dt>
+
+   <dd>
+
+    <p>Returns the label of the given track, if known, or the empty string otherwise.</p>
+
+   </dd>
+
+
+   <dt><var title="">track</var> . <code title="dom-StreamTrack-enabled">enabled</code> [ = <var title="">value</var> ]</dt>
+
+   <dd>
+
+    <p>Returns true if the given track is active in the <code>MediaStream</code>'s output, and false otherwise.</p>
+
+    <p>Can be set, to change whether the track is enabled or not.</p>
+
+   </dd>
+
   </dl>
 
   <div class="impl">
 
+  <p>The <dfn title="dom-MediaStream"><code>MediaStream(<var
+  title="">parentStream</var>)</code></dfn> constructor must return a
+  new <code>MediaStream</code> object whose tracks at any moment in
+  time are the enabled tracks of <var title="">parentStream</var> at
+  that moment.</p>
+
   <p>The <dfn
   title="dom-MediaStream-readyState"><code>readyState</code></dfn>
   attribute represents the state of the stream. It must return the
@@ -85740,18 +86203,34 @@
   </dl>
 
   <p>When a <code>MediaStream</code> object is created, its <code
-  title="dom-MediaStream-readyState">readyState</code> attribute must be
-  set to <code title="dom-MediaStream-LIVE">LIVE</code> (1).</p>
+  title="dom-MediaStream-readyState">readyState</code> attribute must
+  be set to <code title="dom-MediaStream-LIVE">LIVE</code> (1), unless
+  it is being created using the <code
+  title="dom-MediaStream">MediaStream()</code> constructor whose
+  argument is a <code>MediaStream</code> object whose <code
+  title="dom-MediaStream-readyState">readyState</code> attribute has
+  the value <code title="dom-MediaStream-ENDED">ENDED</code> (2), in
+  which case the <code>MediaStream</code> object must be created with
+  its <code title="dom-MediaStream-readyState">readyState</code>
+  attribute set to <code title="dom-MediaStream-ENDED">ENDED</code>
+  (2).</p>
 
-  <p>When a <code>MediaStream</code> object ends for any reason other than
-  the <code title="dom-MediaStream-stop">stop()</code> method being invoked
-  (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), the user agent
-  must <span>queue a task</span> that runs the following steps:</p>
+  <p>A <code>MediaStream</code> object is said to <i>end</i> when the
+  user agent learns that no more data will ever be forthcoming for
+  this stream.</p>
 
+  <p>When a <code>MediaStream</code> object ends for any reason other
+  than the <code title="dom-MediaStream-stop">stop()</code> method
+  being invoked (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, or because the <code>MediaStream</code> was created from
+  another <code>MediaStream</code> and that stream has just itself
+  ended), the user agent must <span>queue a task</span> that runs the
+  following steps:</p>
+
   <ol>
 
    <li><p>If the object's <code
@@ -85827,7 +86306,7 @@
    source, then the user agent should remove any active "on-air"
    indicator. If the data is being generated from a prerecorded source
    (e.g. a video file), any remaining content in the file is
-   ignored.</p></li>
+   ignored. The stream has <i>ended</i>.</p></li>
 
    <li><p>Set the object's <code
    title="dom-MediaStream-readyState">readyState</code> attribute to
@@ -85845,49 +86324,70 @@
 
   <hr>
 
-  <p>A <code>LocalMediaStream</code> can have multiple audio and video
+  <p>A <code>MediaStream</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 <span>media resource</span> with
   many media tracks). The stream represented by a
-  <code>LocalMediaStream</code> has either zero or one audio track and
-  either zero or one video track.</p>
+  <code>MediaStream</code> thus has zero or more tracks.</p>
 
-  <div class="impl">
+  <hr>
 
-  <p>The <dfn
-  title="dom-MediaStream-audioTracks"><code>audioTracks</code></dfn>
-  attribute of a <code>LocalMediaStream</code> object must return a
-  <span>live</span> <code>MultipleTrackList</code> object representing
-  the audio sources available to the <code>LocalMediaStream</code>. The
-  same object must be returned each time. The
-  <code>LocalMediaStream</code>'s output audio track must be the result
-  of mixing all the enabled audio sources, if any.</p>
+  <p>The <dfn 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>StreamTrack</code> that is
+  <i>fixed length</i> and <i>read only</i>. The same object must be
+  returned each time the attribute is accessed. <a
+  href="#refsWEBIDL">[WEBIDL]</a></p>
 
+  <p>The array must contain the <code>StreamTrack</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 <span>media
+  resource</span> whose format defines an order must be in the order
+  defined by the format; tracks that come from a <span>media
+  resource</span> whose format does not define an order must be in the
+  relative order in which the tracks are declared in that <span>media
+  resource</span>. Within these constraints, the order is user-agent
+  defined.</p> <!-- doesn't matter currently since I can't think of
+  any way that you can get multiple tracks together. It would matter
+  if we allowed a MediaStream() constructor that took an array of
+  streams, though, or if getUserMedia() could return multiple audio or
+  video tracks. -->
+
   <p>The <dfn
-  title="dom-MediaStream-videoTracks"><code>videoTracks</code></dfn>
-  attribute of a <code>LocalMediaStream</code> object must return a
-  <span>live</span> <code>ExclusiveTrackList</code> object
-  representing the video sources available to the
-  <code>LocalMediaStream</code>. The same object must be returned each
-  time. The <code>LocalMediaStream</code>'s output video track must be
-  the selected video source, if any.</p>
+  title="dom-StreamTrack-kind"><code>StreamTrack.kind</code></dfn>
+  attribute must return the string "<code title="">audio</code>" if
+  the object's corresponding track is or was an audio track, "<code
+  title="">video</code>" if the corresponding track is or was a video
+  track, and a user-agent defined string otherwise.</p>
 
   <p>User agents may label audio and video sources (e.g. "Internal
-  microphone" or "External USB Webcam"), in which case the <code
-  title="dom-TrackList-getLabel">getLabel()</code> methods (on the
-  <code>MultipleTrackList</code> and <code>ExclusiveTrackList</code>
-  objects) must use the labels the user agent has assigned as the
-  track labels of the source tracks of the <code>LocalMediaStream</code>
-  object. Otherwise, the <code
-  title="dom-TrackList-getLabel">getLabel()</code> methods must use the
-  empty string as the track labels of the source tracks of the
-  <code>LocalMediaStream</code> object. The <code
-  title="dom-TrackList-getLanguage">getLanguage()</code> methods must
-  use the empty string as the track language for all the source tracks
-  of the <code>LocalMediaStream</code> object.</p>
+  microphone" or "External USB Webcam"). The <dfn
+  title="dom-StreamTrack-label"><code>StreamTrack.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>
 
-  </div>
+  <p class="note">Thus the <code
+  title="dom-StreamTrack-kind">kind</code> and <code
+  title="dom-StreamTrack-label">label</code> attributes do not change
+  value, even if the <code>StreamTrack</code> object is disassociated
+  from its corresponding track.</p>
 
+  <p>The <dfn
+  title="dom-StreamTrack-enabled"><code>StreamTrack.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>StreamTrack</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>StreamTrack</code> is
+  disassociated from its track, its <code
+  title="dom-StreamTrack-enabled">enabled</code> attribute still
+  changes value when set, it just doesn't do anything with that new
+  value.</p>
+
   <hr>
 
   <p>The following are the <span>event handlers</span> (and their
@@ -91757,7 +92257,7 @@
       either the <var title="">source port</var> or the <var
       title="">target port</var> (if any), then throw a
       <code>DATA_CLONE_ERR</code> exception and abort these
-      steps.</p></li>
+      steps.</p>
 
      </li>
 

|