More bug fixes based on TPAC discussions.
Bug 19531 - Rework byte stream format text so it doesn't imply that the MediaSource implementation must support all formats supported by the HTMLMediaElement.
Bug 18575 - Remove 2.x subsections that are already covered by algorithm text.
Bug 18960 - Added unique ID generation text to Initialization Segment Received algorithm.
Bug 18963 - append() now throws a QUOTA_EXCEEDED_ERR when the SourceBuffer is full.
--- a/media-source/media-source-respec.html Tue Nov 27 16:15:18 2012 -0800
+++ b/media-source/media-source-respec.html Tue Dec 04 09:22:40 2012 -0800
@@ -57,14 +57,6 @@
.nonnormative h3 { color: inherit; background: inherit; }
.nonnormative:before { display: table; margin: -1em -0.5em -0.5em auto; width: auto; content: 'This section is non-normative.'; color: black; font-style: italic; border: solid 2px; background: white; padding: 0 0.25em; }
- .example { color: green; margin: 2em 0 2em 2em; padding: 0.5em 1em; border: none; background: #DDFFDD; }
- hr + dl.example, div.impl + dl.domintro { margin-top: 2.5em; margin-bottom: 1.5em; }
- dl.example dt, dl.domintro dt * { color: black; text-decoration: none; }
- dl.example dd { margin: 0.5em 0 1em 2em; padding: 0; }
- dl.example dd p { margin: 0.5em 0; }
-
- .example:before { display: table; margin: -1em -0.5em -0.5em auto; width: auto; content: 'This box is non-normative. Implementation requirements are given below this box.'; color: black; font-style: italic; border: solid 2px; background: white; padding: 0 0.25em; }
-
.iso-box { font-weight: bold; }
.iso-var { font-style: italic; }
@@ -125,27 +117,14 @@
<dt id="init-segment">Initialization Segment</dt>
<dd>
<p>A sequence of bytes that contains all of the initialization information required to decode a sequence of <a def-id="media-segments"></a>. This includes codec initialization data, <a def-id="track-id"></a> mappings for multiplexed segments, and timestamp offsets (e.g. edit lists).</p>
- <dl class="example">
- <p>Container specific examples of initialization segments:</p>
- <dt>ISO Base Media File Format</dt>
- <dd>A <span class="iso-box">moov</span> box.</dd>
- <dt>WebM</dt>
- <dd>The concatenation of the the EBML Header, Segment Header, Info element, and Tracks element.</dd>
- </dl>
- </dd>
+ <p class="note">The <a def-id="byte-stream-format-specs"></a> contain format specific examples.</p>
<dt id="media-segment">Media Segment</dt>
<dd>
<p>A sequence of bytes that contain packetized & timestamped media data for a portion of the presentation timeline. Media segments are always associated with the most recently appended <a def-id="init-segment"></a>.</p>
- <dl class="example">
- <p>Container specific examples of media segments:</p>
- <dt>ISO Base Media File Format</dt>
- <dd>A <span class="iso-box">moof</span> box followed by one or more <span class="iso-box">mdat</span> boxes.</dd>
- <dt>WebM</dt>
- <dd>A Cluster element</dd>
- </dl>
+ <p class="note">The <a def-id="byte-stream-format-specs"></a> contain format specific examples.</p>
</dd>
-
+
<dt id="source-buffer">Source Buffer</dt>
<dd><p>A hypothetical buffer that contains a distinct sequence of <a def-id="init-segments"></a> & <a def-id="media-segments"></a>. When <a def-id="media-segments"></a> are passed to <a def-id="append"></a> they update the state of this buffer. The source buffer only allows a single <a def-id="media-segment"></a> to cover a specific point in the presentation timeline of each track. If a <a def-id="media-segment"></a> gets appended that contains media data overlapping (in presentation time) with media data from an existing segment, then the new media data will override the old media data. Since <a def-id="media-segments"></a> depend on <a def-id="init-segments"></a> the source buffer is also responsible for maintaining these associations. During playback, the media element pulls segment data out of the source buffers, demultiplexes it if necessary, and enqueues it into <a def-id="track-buffers"></a> so it will get decoded and displayed. <a def-id="buffered"></a> describes the time ranges that are covered by <a def-id="media-segments"></a> in the source buffer.</p></dd>
@@ -187,16 +166,6 @@
<h2>Source Buffer Model</h2>
<p>The subsections below outline the buffering model for this proposal. It describes how to add and remove <a def-id="source-buffers"></a> from the presentation and describes the various rules and behaviors associated with appending data to an individual <a def-id="source-buffer"></a>. At the highest level, the web application simply creates <a def-id="source-buffers"></a> and appends a sequence of <a def-id="init-segments"></a> and <a def-id="media-segments"></a> to update the buffer's state. The media element pulls media data out of the <a def-id="source-buffers"></a>, plays it, and fires events just like it would if a normal URL was passed to the <a def-id="media-src"></a> attribute. The web application is expected to monitor media element events to determine when it needs to append more <a def-id="media-segments"></a>.</p>
- <section id="source-buffer-create">
- <h3>Creating Source Buffers</h3>
- <p><a>SourceBuffer</a> objects can be created once a <a>MediaSource</a> object enters the <a def-id="open"></a> state. The application calls <a def-id="addSourceBuffer"></a> with a type string that indicates the format of the data it intends to append to the new SourceBuffer. If the user agent supports the format and has sufficient resources, a new <a>SourceBuffer</a> object is created, added to <a def-id="sourceBuffers"></a>, and returned by the method. If the user agent doesn't support the specified format or can't support another <a>SourceBuffer</a> then it will throw an appropriate exception to signal why the request couldn't be satisfied.</p>
- </section>
-
- <section id="source-buffer-remove">
- <h3>Removing Source Buffers</h3>
- <p>Removing a <a>SourceBuffer</a> with <a def-id="removeSourceBuffer"></a> releases all resources associated with the object. This includes destroying the all the segment data, <a def-id="track-buffers"></a>, and decoders. The media element will also remove the appropriate tracks from <a def-id="audiotracks"></a>, <a def-id="videotracks"></a>, & <a def-id="texttracks"></a> and fire the necessary <a def-id="videoref" name="handler-tracklist-onchange">change</a> events. Playback may become degraded or stop if the currently selected <a def-id="video-track"></a> or the only enabled <a def-id="audio-tracks"></a> are removed.</p>
- </section>
-
<section id="source-buffer-basic-append">
<h3>Basic appending model</h3>
<p>Updating the state of a <a def-id="source-buffer"></a> requires appending at least one <a def-id="init-segment"></a> and one or more <a def-id="media-segments"></a> via <a def-id="append"></a>. The following list outlines some of the basic rules for appending segments.
@@ -214,47 +183,6 @@
</p>
</section>
- <section id="source-buffer-init-segment-constraints">
- <h3>Initialization Segment constraints</h3>
- <p>To simplify the implementation and facilitate interoperability, a few constraints are placed on the <a def-id="init-segments"></a> that are appended to a specific <a>SourceBuffer</a>:
- <ul>
- <li>The number and type of tracks must be consistent across all <a def-id="init-segments"></a>. <br>For example, if the first <a def-id="init-segment"></a> has 2 audio tracks and 1 video track, then all <a def-id="init-segments"></a> that follow, for this <a>SourceBuffer</a> must describe 2 audio tracks and 1 video track.</li>
- <li>
- <a def-id="track-ids"></a> do not need to be the same across <a def-id="init-segments"></a> only if the segment describes one track of each type.<br> For example, if an <a def-id="init-segment"></a> describes a single audio track and a single video track, the internal <a def-id="track-ids"></a> do not need to be the same.</li>
- <li>
- <a def-id="track-ids"></a> must be the same across <a def-id="init-segments"></a> if multiple tracks for a single type are described. (e.g. 2 audio tracks).</li>
- <li>Codecs changes are not allowed. <br> For example, you can't have an <a def-id="init-segment"></a> that specifies a single AAC track and then follows it with one that contains AMR-WB. Support for multiple codecs is handled with multiple <a>SourceBuffer</a> objects.</li>
- <li>Video frame size changes are allowed and must be supported seamlessly.<p class="note">This will cause the <video> display region to change size if you don't use CSS or HTML attributes (width/height) to constrain the element size.</p>
- </li>
- <li>Audio channel count changes are allowed, but they may not be seamless and could trigger downmixing.<p class="note">This is a quality of implementation issue because changing the channel count may require reinitializing the audio device, resamplers, and channel mixers which tends to be audible.</p>
- </li>
- </ul>
- </p>
- </section>
-
- <section id="source-buffer-media-segment-constraints">
- <h3>Media Segment constraints</h3>
- <p>To simplify the implementation and facilitate interoperability, a few constraints are placed on the <a def-id="media-segments"></a> that are appended to a specific <a>SourceBuffer</a>:
- <ul>
- <li>All timestamps must be mapped to the same presentation timeline.</li>
- <li>Segments must start with a <a def-id="random-access-point"></a> to facilitate seamless splicing at the segment boundary.</li>
- <li>Gaps between <a def-id="media-segments"></a> that are smaller than the audio frame size are allowed and must not cause playback to stall. Such gaps must not be reflected by <a def-id="buffered"></a>.
- <p class="note">This is intended to simplify switching between audio streams where the frame boundaries don't always line up across encodings (e.g. Vorbis).</p>
- </li>
- </ul>
- </p>
- </section>
-
- <section id="source-buffer-first-init-segment">
- <h3>Appending the first Initialization Segment</h3>
- <p>Once a new <a>SourceBuffer</a> has been created, it expects an <a def-id="init-segment"></a> to be appended first. This first segment indicates the number and type of streams contained in the <a def-id="media-segments"></a> that follow. This allows the media element to configure the necessary decoders and output devices. This first segment can also cause a <a def-id="ready-state"></a> transition to <a def-id="have-metadata"></a> if this is the first <a>SourceBuffer</a>, or if it is the first track of a specific type (i.e. first audio, first video track, or first text track). If neither of the conditions hold then the tracks for this new <a>SourceBuffer</a> will just appear as disabled tracks and won't affect the current <a def-id="ready-state"></a> until they are selected. The media element will also add the appropriate tracks to the <a def-id="audiotracks"></a>, <a def-id="videotracks"></a>, & <a def-id="texttracks"></a> collections and fire the necessary <a def-id="videoref" name="handler-tracklist-onchange">change</a> events. The description for <a def-id="append"></a> contains all the details.</p>
- </section>
-
- <section id="source-buffer-media-segment-unbuffered">
- <h3>Appending a Media Segment to an unbuffered region</h3>
- <p>If a <a def-id="media-segment"></a> is appended to a time range that is not covered by existing segments in the <a def-id="source-buffer"></a>, then its data is copied directly into the <a def-id="source-buffer"></a>. Addition of this data may trigger <a def-id="ready-state"></a> transitions depending on what other data is buffered and whether the media element has determined if it can start playback. Calls to <a def-id="buffered"></a> will always reflect the current <a def-id="timeranges"></a> buffered in the <a>SourceBuffer</a>.</p>
- </section>
-
<section id="source-buffer-overlapping-segments">
<h3>Appending a Media Segment over a buffered region</h3>
<p>There are several ways that <a def-id="media-segments"></a> can overlap segments in the <a def-id="source-buffer"></a>. Behavior for the different overlap situations are described below. If more than one overlap applies, then the <a href="#source-buffer-overlap-start">start overlap</a> gets resolved first, followed by any <a href="#source-buffer-overlap-complete">complete overlaps</a>, and finally the <a href="#source-buffer-overlap-end">end overlap</a>. If a segment contains multiple tracks then the overlap is resolved independently for each track.</p>
@@ -292,19 +220,6 @@
<p>Here is an example to help clarify the role of the <a def-id="track-buffer"></a>. Say the current playback position has a timestamp of 8 and the media element pulled frames with timestamp 9 & 10 into the track buffer. The web application then appends a higher quality <a def-id="media-segment"></a> that starts with a <a def-id="random-access-point"></a> at timestamp 9. The <a def-id="source-buffer"></a> will get updated with the higher quality data, but the media element won't be able to switch to this higher quality data until the next <a def-id="random-access-point"></a> at timestamp 20. This is because a frame for timestamp 9 is already in the track buffer. As you can see the track buffer represents the "point of no return." for decoding. If a seek occurs the media element may choose to use the higher quality data since a seek might imply flushing the <a def-id="track-buffer"></a> and the user expects a break in playback.</p>
</section>
-
-
- <section id="source-buffer-segment-eviction">
- <h3>Media Segment Eviction</h3>
- <p>When a new <a def-id="media-segment"></a> is appended, memory constraints may cause previously appended segments to get evicted from the <a def-id="source-buffer"></a>. The eviction algorithm is implementation dependent, but segments that aren't likely to be needed soon are the most likely to get evicted. The <a def-id="buffered"></a> attribute allows the web application to monitor what time ranges are currently buffered in the <a def-id="source-buffer"></a>.</p>
- </section>
-
- <section id="source-buffer-timestamp-offsets">
- <h3>Applying Timestamp Offsets</h3>
- <p>For some use cases like ad-insertion or seamless playlists, the web application may want to insert a <a def-id="media-segment"></a> in the presentation timeline at a location that is different than what the internal timestamps indicate. This can be accomplished by using the <a def-id="timestampOffset"></a> attribute on the <a>SourceBuffer</a> object. The value of <a def-id="timestampOffset"></a> is added to all timestamps inside a <a def-id="media-segment"></a> before the contents of that segment are added to the <a def-id="source-buffer"></a>. The <a def-id="timestampOffset"></a> applies to an entire media segment. An exception is thrown if the application tries to update the attribute when only part of a media segment has been appended. Both positive or negative offsets can be assigned to <a def-id="timestampOffset"></a>. If an offset causes a <a def-id="media-segment"></a> timestamp to get converted to a time before the <a def-id="presentation-start-time"></a>, playback will terminate with a <a def-id="media-err-decode"></a> error.</p>
-
- <p>Here is a simple example to clarify how <a def-id="timestampOffset"></a> can be used. Say I have two sounds I want to play in sequence. The first sound is 5 seconds long and the second one is 10 seconds. Both sound files have timestamps that start at 0. First append the <a def-id="init-segment"></a> and all <a def-id="media-segments"></a> for the first sound. Now set <a def-id="timestampOffset"></a> to 5 seconds. Finally append the <a def-id="init-segment"></a> and <a def-id="media-segments"></a> for the second sound. This will result in a 15 second presentation that plays the two sounds in sequence.</p>
- </section>
</section>
<section id="mediasource">
@@ -745,6 +660,10 @@
</ol>
</li>
<li>If <var>data</var>.byteLength is 0, then abort these steps.</li>
+ <li>
+ <p>If the <a def-id="buffer-full-flag"></a> equals true, then throw a <a def-id="quota-exceeded-err"></a> exception and abort these step.</p>
+ <p class="note">The web application must use <a def-id="remove"></a> to free up space in the <a>SourceBuffer</a>.</p>
+ </li>
<li>Add <var>data</var> to the end of the <a def-id="input-buffer"></a>
</li>
<li>Run the <a def-id="segment-parser-loop"></a>.</li>
@@ -791,6 +710,8 @@
</li>
</ol>
</li>
+ <li>If <a def-id="buffer-full-flag"></a> equals true and this object is ready to accept more bytes, then set
+ the <a def-id="buffer-full-flag"></a> to false.</li>
</ol>
</dd>
@@ -827,6 +748,9 @@
<p>The <dfn id="sourcebuffer-input-buffer">input buffer</dfn> is a byte buffer that is used to hold unparsed bytes across <a def-id="append"></a> calls. The buffer is empty when the SourceBuffer object is created.</p>
+ <p>The <dfn id="sourcebuffer-buffer-full-flag">buffer full flag</dfn> keeps track of whether <a def-id="append"></a> is allowed to accept more
+ bytes. It is set to false when the SourceBuffer object is created and gets updated as data is appended and removed.</p>
+
<p>While the <a def-id="input-buffer"></a> is not empty, run the following steps in a loop:</p>
<ol>
<li>If the <a def-id="input-buffer"></a> starts with bytes that violate the <a def-id="byte-stream-format-specs"></a>, then call <a def-id="eos-decode"></a>, and abort this algorithm.</li>
@@ -858,6 +782,7 @@
</li>
<li>Run the <a def-id="coded-frame-processing-algorithm"></a>.</li>
<li>Remove the <a def-id="media-segment"></a> bytes from the beginning of the <a def-id="input-buffer"></a>.</li>
+ <li>If this <a>SourceBuffer</a> is full and cannot accept more media data, then set the <a def-id="buffer-full-flag"></a> to true.</li>
<li>
<p>Set <a def-id="append-state"></a> to <a def-id="waiting-for-segment"></a>.</p>
<p class="note">Incremental parsers should only do this transition after the entire media segment has been received.</p>
@@ -871,6 +796,7 @@
<section id="sourcebuffer-init-segment-received">
<h4>Initialization Segment Received</h4>
<p>The following steps are run when the <a def-id="segment-parser-loop"></a> successfully parses a complete <a def-id="init-segment"></a>:</p>
+ <p>Each SourceBuffer object has an internal <dfn id="first-init-segment-flag">first initialization segment flag</dfn> that tracks whether the first <a def-id="init-segment"></a> has been appended. This flag is set to false when the SourceBuffer is created and updated by the algorithm below.</p>
<ol>
<li>Update the <a def-id="duration"></a> attribute if it currently equals NaN:</li>
<dl class="switch">
@@ -879,58 +805,87 @@
<dt>Otherwise:</dt>
<dd>Run the <a def-id="duration-change-algorithm"></a> with <var>new duration</var> set to positive Infinity.</dd>
</dl>
- <li>Handle state transitions:</li>
- <dl class="switch">
- <dt>If the <a def-id="ready-state"></a> attribute is <a def-id="have-nothing"></a>:</dt>
- <dd>
- <ol>
- <li>Set the <a def-id="ready-state"></a> attribute to <a def-id="have-metadata"></a>.</li>
- <li>
- <a def-id="Queue-a-task-to-fire-an-event-named"></a> <a def-id="loadedmetadata"></a> at the media element.</li>
- </ol>
- </dd>
- <dt>If the <a def-id="ready-state"></a> attribute is greater than <a def-id="have-current-data"></a> and the <a def-id="init-segment"></a> contains the first video or first audio track in the presentation:</dt>
- <dd>
- Set the <a def-id="ready-state"></a> attribute to <a def-id="have-metadata"></a>.
- </dd>
- <dt>Otherwise:</dt>
- <dd>Continue</dd>
- </dl>
- <li>Update <a def-id="audiotracks"></a>
+ <li>If the <a def-id="init-segment"></a> has no audio, video, or text tracks, then call <a def-id="eos-decode"></a> and abort these steps.</li>
+ <li>
+ <p>If the <a def-id="first-init-segment-flag"></a> is true, then verify the following properties. If any of the checks fail then call <a def-id="eos-decode"></a> and abort these steps.</p>
+ <ul>
+ <li>The number of audio, video, and text tracks match what was in the first <a def-id="init-segment"></a>.</li>
+ <li>The codecs for each track, match what was specified in the first <a def-id="init-segment"></a>.</li>
+ <li>If more than one track for a single type are present (ie 2 audio tracks), then the <a def-id="track-ids"></a> match the ones in the
+ first <a def-id="init-segment"></a>.</li>
+ </ul>
</li>
- <dl class="switch">
- <dt>If <a def-id="init-segment"></a> contains the first audio track:</dt>
- <dd>
- <ol>
- <li>Add an <a def-id="audio-track"></a> and mark it as enabled.</li>
- <li>Add this <a>SourceBuffer</a> to <a def-id="activeSourceBuffers"></a>.</li>
- </ol>
- </dd>
- <dt>If <a def-id="init-segment"></a> contains audio tracks beyond those already in the presentation:</dt>
- <dd>Add a disabled <a def-id="audio-track"></a> for each audio track in the <a def-id="init-segment"></a>.</dd>
- </dl>
- <li>Update <a def-id="videotracks"></a>:</li>
- <dl class="switch">
- <dt>If <a def-id="init-segment"></a> contains the first video track:</dt>
- <dd>
- <ol>
- <li>Add a <a def-id="video-track"></a> and mark it as selected.</li>
- <li>Add this <a>SourceBuffer</a> to <a def-id="activeSourceBuffers"></a>.</li>
- </ol>
- </dd>
- <dt>If <a def-id="init-segment"></a> contains the video tracks beyond those already in the presentation:</dt>
- <dd>Add a disabled <a def-id="video-track"></a> for each video track in the <a def-id="init-segment"></a>.</dd>
- </dl>
- <li>Update <a def-id="texttracks"></a>
+ <li>Let <var>active track flag</var> equal false.</li>
+ <li>
+ <p>If the <a def-id="first-init-segment-flag"></a> is false, then run the following steps:</p>
+ <ol>
+ <li>
+ <p>For each audio track in the <a def-id="init-segment"></a>, run following steps:</p>
+ <ol>
+ <li>Let <var>new audio track</var> be a new <a def-id="audio-track"></a> object.</li>
+ <li>Generate a unique ID and assign it to the <a def-id="audiotrack-id"></a> property on <var>new audio track</var>.</li>
+ <li>
+ <p>
+ If <a def-id="audiotracks"></a>.<a def-id="audiotracklist-length"></a> equals 0, then run
+ the following steps:
+ </p>
+ <ol>
+ <li>Set the <a def-id="audiotrack-enabled"></a> property on <var>new audio track</var> to true.</li>
+ <li>Set <var>active track flag</var> to true.</li>
+ </ol>
+ </li>
+ <li>Add <var>new audio track</var> to <a def-id="audiotracks"></a>.</li>
+ </ol>
+ </li>
+ <li>
+ <p>For each video track in the <a def-id="init-segment"></a>, run following steps:</p>
+ <ol>
+ <li>Let <var>new video track</var> be a new <a def-id="video-track"></a> object.</li>
+ <li>Generate a unique ID and assign it to the <a def-id="videotrack-id"></a> property on <var>new video track</var>.</li>
+ <li>
+ <p>
+ If <a def-id="videotracks"></a>.<a def-id="videotracklist-length"></a> equals 0, then run
+ the following steps:
+ </p>
+ <ol>
+ <li>Set the <a def-id="videotrack-selected"></a> property on <var>new video track</var> to true.</li>
+ <li>Set <var>active track flag</var> to true.</li>
+ </ol>
+ </li>
+ <li>Add <var>new video track</var> to <a def-id="videotracks"></a>.</li>
+ </ol>
+ </li>
+ <li>
+ <p>For each text track in the <a def-id="init-segment"></a>, run following steps:</p>
+ <ol>
+ <li>
+ Let <var>new text track</var> be a new <a def-id="text-track"></a> object with its properties populated with the appropriate
+ information from the <a def-id="init-segment"></a>.</li>
+ <li>
+ If the <a def-id="texttrack-mode"></a> property on <var>new text track</var> equals <a def-id="texttrack-showing"></a> or
+ <a def-id="texttrack-hidden"></a>, then set <var>active track flag</var> to true.
+ </li>
+ <li>Add <var>new text track</var> to <a def-id="texttracks"></a>.</li>
+ </ol>
+ </li>
+ <li>If <var>active track flag</var> equals true, then add this <a>SourceBuffer</a> to <a def-id="activeSourceBuffers"></a>.</li>
+ <li>Set <a def-id="first-init-segment-flag"></a> to true.</li>
+ </ol>
</li>
- <dl class="switch">
- <dd>
- <ol>
- <li>Add a <a def-id="text-track"></a> for each text track in the <a def-id="init-segment"></a>.</li>
- <li>If the text track <a def-id="videoref" name="dom-texttrack-mode">mode</a> is <a def-id="videoref" name="dom-texttrack-showing">"showing"</a> or <a def-id="videoref" name="dom-texttrack-hidden">"hidden"</a> then add this <a>SourceBuffer</a> to <a def-id="activeSourceBuffers"></a>.</li>
- </ol>
- </dd>
- </dl>
+ <li>
+ <p>If the <a def-id="ready-state"></a> attribute is <a def-id="have-nothing"></a>, then run the following steps:</p>
+ <ol>
+ <li>
+ If one or more objects in <a def-id="activeSourceBuffers"></a> have <a def-id="first-init-segment-flag"></a> set to false, then abort
+ these steps.</li>
+ <li>Set the <a def-id="ready-state"></a> attribute to <a def-id="have-metadata"></a>.</li>
+ <li><a def-id="Queue-a-task-to-fire-an-event-named"></a> <a def-id="loadedmetadata"></a> at the media element.</li>
+ </ol>
+ </li>
+ <li>
+ If the <var>active track flag</var> equals true and the <a def-id="ready-state"></a> attribute is greater than
+ <a def-id="have-current-data"></a>, then set the <a def-id="ready-state"></a> attribute to <a def-id="have-metadata"></a>.
+ </li>
</ol>
</section>
@@ -1081,12 +1036,46 @@
<section id="byte-stream-formats">
<h2>Byte Stream Formats</h2>
- <p>The bytes provided through <a def-id="append"></a> for a <a>SourceBuffer</a> form a logical byte stream. The format of this byte stream depends on the media container format in use and is defined in a byte stream format specification. Byte stream format specifications based on WebM and the ISO Base Media File Format are provided below. If these formats are supported then the byte stream formats described below must be supported.</p>
+ <p>The bytes provided through <a def-id="append"></a> for a <a>SourceBuffer</a> form a logical byte stream. The format of this byte stream depends on the media container format in use and is defined in a byte stream format specification. Byte stream format specifications based on WebM and the ISO Base Media File Format are provided below. These format specifications are intended to be the authoritative source for how data from these containers is formatted and passed to a <a>SourceBuffer</a>. If a <a>MediaSource</a> implementation claims to support any of these container formats, then it must implement the corresponding byte stream format specification described below.</p>
<p>This section provides general requirements for all byte stream formats:</p>
<ul>
<li>A byte stream format specification must define <a def-id="init-segments"></a> and <a def-id="media-segments"></a>.</li>
<li>It must be possible to identify segment boundaries and segment type (initialization or media) by examining the byte stream alone.</li>
- <li>The combination of an Initialization Segment and any contiguous sequence of Media Segments associated with it must:
+ <li>The following rules apply to all <a def-id="init-segments"></a> within a byte stream:
+ <ol>
+ <li>
+ <p>The number and type of tracks must be consistent.</p>
+ <p>For example, if the first <a def-id="init-segment"></a> has 2 audio tracks and 1 video track, then all <a def-id="init-segments"></a> that follow it in the byte stream must describe 2 audio tracks and 1 video track.</p>
+ </li>
+ <li>
+ <p><a def-id="track-ids"></a> do not need to be the same across <a def-id="init-segments"></a> if the segment describes only one track of each type.</p>
+ <p>For example, if an <a def-id="init-segment"></a> describes a single audio track and a single video track, the internal <a def-id="track-ids"></a> do not need to be the same.</p>
+ </li>
+ <li><a def-id="track-ids"></a> must be the same across <a def-id="init-segments"></a> if the segment describes multiple tracks of a single type. (e.g. 2 audio tracks).</li>
+ <li>
+ <p>Codecs changes are not allowed.</p>
+ <p>For example, a byte stream that starts with an <a def-id="init-segment"></a> that specifies a single AAC track and later contains an <a def-id="init-segment"></a> that specifies a single AMR-WB track is not allowed. Support for multiple codecs is handled with multiple <a>SourceBuffer</a> objects.</p>
+ </li>
+ <li>
+ <p>Video frame size changes are allowed and must be supported seamlessly.</p>
+ <p class="note">This will cause the <video> display region to change size if the web application does not use CSS or HTML attributes (width/height) to constrain the element size.</p>
+ </li>
+ <li>
+ <p>Audio channel count changes are allowed, but they may not be seamless and could trigger downmixing.</p>
+ <p class="note">This is a quality of implementation issue because changing the channel count may require reinitializing the audio device, resamplers, and channel mixers which tends to be audible.</p>
+ </li>
+ </ol>
+ </li>
+ <li>The following rules apply to all <a def-id="media-segments"></a> within a byte stream:</a>
+ <ol>
+ <li>All timestamps must be mapped to the same presentation timeline.</li>
+ <li>Segments must start with a <a def-id="random-access-point"></a> to facilitate seamless splicing at the segment boundary.</li>
+ <li>Gaps between <a def-id="media-segments"></a> that are smaller than the audio frame size are allowed and must not cause playback to stall. Such gaps must not be reflected by <a def-id="buffered"></a>.
+ <p class="note">This is intended to simplify switching between audio streams where the frame boundaries don't always line up across encodings (e.g. Vorbis).</p>
+ </li>
+ </ol>
+ </li>
+ <li>The combination of an <a def-id="init-segment"></a> and any contiguous sequence of <a def-id="media-segments"></a> associated with it must:
<ol>
<li>Identify the number and type (audio, video, text, etc.) of tracks in the Segments</li>
<li>Identify the decoding capabilities needed to decode each track (i.e. codec and codec parameters)</li>
@@ -1270,7 +1259,19 @@
</thead>
<tbody>
<tr>
- <td>28 November 2012</a></td>
+ <td>06 December 2012</a></td>
+ <td>
+ <ul>
+ <li>append() now throws a QUOTA_EXCEEDED_ERR when the SourceBuffer is full.</li>
+ <li>Added unique ID generation text to Initialization Segment Received algorithm.</li>
+ <li>Remove 2.x subsections that are already covered by algorithm text.</li>
+ <li>Rework byte stream format text so it doesn't imply that the MediaSource implementation must support all formats supported by the
+ HTMLMediaElement.</li>
+ </ul>
+ </td>
+ </tr>
+ <tr>
+ <td><a href="http://dvcs.w3.org/hg/html-media/rev/0c638da9a67a">28 November 2012</a></td>
<td>
<ul>
<li>Added transition to HAVE_METADATA when current playback position is removed.</li>
--- a/media-source/media-source.html Tue Nov 27 16:15:18 2012 -0800
+++ b/media-source/media-source.html Tue Dec 04 09:22:40 2012 -0800
@@ -12,14 +12,6 @@
.nonnormative h3 { color: inherit; background: inherit; }
.nonnormative:before { display: table; margin: -1em -0.5em -0.5em auto; width: auto; content: 'This section is non-normative.'; color: black; font-style: italic; border: solid 2px; background: white; padding: 0 0.25em; }
- .example { color: green; margin: 2em 0 2em 2em; padding: 0.5em 1em; border: none; background: #DDFFDD; }
- hr + dl.example, div.impl + dl.domintro { margin-top: 2.5em; margin-bottom: 1.5em; }
- dl.example dt, dl.domintro dt * { color: black; text-decoration: none; }
- dl.example dd { margin: 0.5em 0 1em 2em; padding: 0; }
- dl.example dd p { margin: 0.5em 0; }
-
- .example:before { display: table; margin: -1em -0.5em -0.5em auto; width: auto; content: 'This box is non-normative. Implementation requirements are given below this box.'; color: black; font-style: italic; border: solid 2px; background: white; padding: 0 0.25em; }
-
.iso-box { font-weight: bold; }
.iso-var { font-style: italic; }
@@ -405,7 +397,7 @@
</p>
<h1 class="title" id="title">Media Source Extensions</h1>
- <h2 id="w3c-editor-s-draft-28-november-2012"><abbr title="World Wide Web Consortium">W3C</abbr> Editor's Draft 28 November 2012</h2>
+ <h2 id="w3c-editor-s-draft-06-december-2012"><abbr title="World Wide Web Consortium">W3C</abbr> Editor's Draft 06 December 2012</h2>
<dl>
<dt>This version:</dt>
@@ -513,7 +505,7 @@
-</section><section id="toc"><h2 class="introductory">Table of Contents</h2><ul class="toc"><li class="tocline"><a href="#introduction" class="tocxref"><span class="secno">1. </span>Introduction</a><ul class="toc"><li class="tocline"><a href="#goals" class="tocxref"><span class="secno">1.1 </span>Goals</a></li><li class="tocline"><a href="#definitions" class="tocxref"><span class="secno">1.2 </span>Definitions</a></li></ul></li><li class="tocline"><a href="#source-buffer-model" class="tocxref"><span class="secno">2. </span>Source Buffer Model</a><ul class="toc"><li class="tocline"><a href="#source-buffer-create" class="tocxref"><span class="secno">2.1 </span>Creating Source Buffers</a></li><li class="tocline"><a href="#source-buffer-remove" class="tocxref"><span class="secno">2.2 </span>Removing Source Buffers</a></li><li class="tocline"><a href="#source-buffer-basic-append" class="tocxref"><span class="secno">2.3 </span>Basic appending model</a></li><li class="tocline"><a href="#source-buffer-init-segment-constraints" class="tocxref"><span class="secno">2.4 </span>Initialization Segment constraints</a></li><li class="tocline"><a href="#source-buffer-media-segment-constraints" class="tocxref"><span class="secno">2.5 </span>Media Segment constraints</a></li><li class="tocline"><a href="#source-buffer-first-init-segment" class="tocxref"><span class="secno">2.6 </span>Appending the first Initialization Segment</a></li><li class="tocline"><a href="#source-buffer-media-segment-unbuffered" class="tocxref"><span class="secno">2.7 </span>Appending a Media Segment to an unbuffered region</a></li><li class="tocline"><a href="#source-buffer-overlapping-segments" class="tocxref"><span class="secno">2.8 </span>Appending a Media Segment over a buffered region</a><ul class="toc"><li class="tocline"><a href="#source-buffer-overlap-complete" class="tocxref"><span class="secno">2.8.1 </span>Complete Overlap</a></li><li class="tocline"><a href="#source-buffer-overlap-start" class="tocxref"><span class="secno">2.8.2 </span>Start Overlap</a></li><li class="tocline"><a href="#source-buffer-overlap-end" class="tocxref"><span class="secno">2.8.3 </span>End Overlap</a></li><li class="tocline"><a href="#source-buffer-overlap-middle" class="tocxref"><span class="secno">2.8.4 </span>Middle Overlap</a></li></ul></li><li class="tocline"><a href="#source-buffer-to-track-buffer" class="tocxref"><span class="secno">2.9 </span>Source Buffer to Track Buffer transfer</a></li><li class="tocline"><a href="#source-buffer-segment-eviction" class="tocxref"><span class="secno">2.10 </span>Media Segment Eviction</a></li><li class="tocline"><a href="#source-buffer-timestamp-offsets" class="tocxref"><span class="secno">2.11 </span>Applying Timestamp Offsets</a></li></ul></li><li class="tocline"><a href="#mediasource" class="tocxref"><span class="secno">3. </span>MediaSource Object</a><ul class="toc"><li class="tocline"><a href="#attributes" class="tocxref"><span class="secno">3.1 </span>Attributes</a></li><li class="tocline"><a href="#methods" class="tocxref"><span class="secno">3.2 </span>Methods</a></li><li class="tocline"><a href="#mediasource-events" class="tocxref"><span class="secno">3.3 </span>Event Summary</a></li><li class="tocline"><a href="#mediasource-algorithms" class="tocxref"><span class="secno">3.4 </span>Algorithms</a><ul class="toc"><li class="tocline"><a href="#mediasource-attach" class="tocxref"><span class="secno">3.4.1 </span>Attaching to a media element</a></li><li class="tocline"><a href="#mediasource-detach" class="tocxref"><span class="secno">3.4.2 </span>Detaching from a media element</a></li><li class="tocline"><a href="#mediasource-seeking" class="tocxref"><span class="secno">3.4.3 </span>Seeking</a></li><li class="tocline"><a href="#buffer-monitoring" class="tocxref"><span class="secno">3.4.4 </span>SourceBuffer Monitoring</a></li><li class="tocline"><a href="#active-source-buffer-changes" class="tocxref"><span class="secno">3.4.5 </span>Changes to selected/enabled track state</a></li><li class="tocline"><a href="#duration-change-algorithm" class="tocxref"><span class="secno">3.4.6 </span>Duration change</a></li></ul></li></ul></li><li class="tocline"><a href="#sourcebuffer" class="tocxref"><span class="secno">4. </span>SourceBuffer Object</a><ul class="toc"><li class="tocline"><a href="#attributes-1" class="tocxref"><span class="secno">4.1 </span>Attributes</a></li><li class="tocline"><a href="#methods-1" class="tocxref"><span class="secno">4.2 </span>Methods</a></li><li class="tocline"><a href="#sourcebuffer-algorithms" class="tocxref"><span class="secno">4.3 </span>Algorithms</a><ul class="toc"><li class="tocline"><a href="#sourcebuffer-segment-parser-loop" class="tocxref"><span class="secno">4.3.1 </span>Segment Parser Loop</a></li><li class="tocline"><a href="#sourcebuffer-init-segment-received" class="tocxref"><span class="secno">4.3.2 </span>Initialization Segment Received</a></li><li class="tocline"><a href="#sourcebuffer-coded-frame-processing" class="tocxref"><span class="secno">4.3.3 </span>Coded Frame Processing</a></li></ul></li></ul></li><li class="tocline"><a href="#sourcebufferlist" class="tocxref"><span class="secno">5. </span>SourceBufferList Object</a><ul class="toc"><li class="tocline"><a href="#attributes-2" class="tocxref"><span class="secno">5.1 </span>Attributes</a></li><li class="tocline"><a href="#methods-2" class="tocxref"><span class="secno">5.2 </span>Methods</a></li><li class="tocline"><a href="#sourcebufferlist-events" class="tocxref"><span class="secno">5.3 </span>Event Summary</a></li></ul></li><li class="tocline"><a href="#url" class="tocxref"><span class="secno">6. </span>URL Object</a><ul class="toc"><li class="tocline"><a href="#methods-3" class="tocxref"><span class="secno">6.1 </span>Methods</a></li></ul></li><li class="tocline"><a href="#htmlmediaelement-attributes" class="tocxref"><span class="secno">7. </span>HTMLMediaElement attributes</a></li><li class="tocline"><a href="#byte-stream-formats" class="tocxref"><span class="secno">8. </span>Byte Stream Formats</a><ul class="toc"><li class="tocline"><a href="#webm" class="tocxref"><span class="secno">8.1 </span>WebM Byte Streams</a><ul class="toc"><li class="tocline"><a href="#webm-init-segments" class="tocxref"><span class="secno">8.1.1 </span>Initialization Segments</a></li><li class="tocline"><a href="#webm-media-segments" class="tocxref"><span class="secno">8.1.2 </span>Media Segments</a></li><li class="tocline"><a href="#webm-random-access-points" class="tocxref"><span class="secno">8.1.3 </span>Random Access Points</a></li></ul></li><li class="tocline"><a href="#iso" class="tocxref"><span class="secno">8.2 </span>ISO Base Media File Format Byte Streams</a><ul class="toc"><li class="tocline"><a href="#iso-init-segments" class="tocxref"><span class="secno">8.2.1 </span>Initialization Segments</a></li><li class="tocline"><a href="#iso-media-segments" class="tocxref"><span class="secno">8.2.2 </span>Media Segments</a></li><li class="tocline"><a href="#iso-random-access-points" class="tocxref"><span class="secno">8.2.3 </span>Random Access Points</a></li></ul></li></ul></li><li class="tocline"><a href="#examples" class="tocxref"><span class="secno">9. </span>Examples</a></li><li class="tocline"><a href="#revision-history" class="tocxref"><span class="secno">10. </span>Revision History</a></li></ul></section>
+</section><section id="toc"><h2 class="introductory">Table of Contents</h2><ul class="toc"><li class="tocline"><a href="#introduction" class="tocxref"><span class="secno">1. </span>Introduction</a><ul class="toc"><li class="tocline"><a href="#goals" class="tocxref"><span class="secno">1.1 </span>Goals</a></li><li class="tocline"><a href="#definitions" class="tocxref"><span class="secno">1.2 </span>Definitions</a></li></ul></li><li class="tocline"><a href="#source-buffer-model" class="tocxref"><span class="secno">2. </span>Source Buffer Model</a><ul class="toc"><li class="tocline"><a href="#source-buffer-basic-append" class="tocxref"><span class="secno">2.1 </span>Basic appending model</a></li><li class="tocline"><a href="#source-buffer-overlapping-segments" class="tocxref"><span class="secno">2.2 </span>Appending a Media Segment over a buffered region</a><ul class="toc"><li class="tocline"><a href="#source-buffer-overlap-complete" class="tocxref"><span class="secno">2.2.1 </span>Complete Overlap</a></li><li class="tocline"><a href="#source-buffer-overlap-start" class="tocxref"><span class="secno">2.2.2 </span>Start Overlap</a></li><li class="tocline"><a href="#source-buffer-overlap-end" class="tocxref"><span class="secno">2.2.3 </span>End Overlap</a></li><li class="tocline"><a href="#source-buffer-overlap-middle" class="tocxref"><span class="secno">2.2.4 </span>Middle Overlap</a></li></ul></li><li class="tocline"><a href="#source-buffer-to-track-buffer" class="tocxref"><span class="secno">2.3 </span>Source Buffer to Track Buffer transfer</a></li></ul></li><li class="tocline"><a href="#mediasource" class="tocxref"><span class="secno">3. </span>MediaSource Object</a><ul class="toc"><li class="tocline"><a href="#attributes" class="tocxref"><span class="secno">3.1 </span>Attributes</a></li><li class="tocline"><a href="#methods" class="tocxref"><span class="secno">3.2 </span>Methods</a></li><li class="tocline"><a href="#mediasource-events" class="tocxref"><span class="secno">3.3 </span>Event Summary</a></li><li class="tocline"><a href="#mediasource-algorithms" class="tocxref"><span class="secno">3.4 </span>Algorithms</a><ul class="toc"><li class="tocline"><a href="#mediasource-attach" class="tocxref"><span class="secno">3.4.1 </span>Attaching to a media element</a></li><li class="tocline"><a href="#mediasource-detach" class="tocxref"><span class="secno">3.4.2 </span>Detaching from a media element</a></li><li class="tocline"><a href="#mediasource-seeking" class="tocxref"><span class="secno">3.4.3 </span>Seeking</a></li><li class="tocline"><a href="#buffer-monitoring" class="tocxref"><span class="secno">3.4.4 </span>SourceBuffer Monitoring</a></li><li class="tocline"><a href="#active-source-buffer-changes" class="tocxref"><span class="secno">3.4.5 </span>Changes to selected/enabled track state</a></li><li class="tocline"><a href="#duration-change-algorithm" class="tocxref"><span class="secno">3.4.6 </span>Duration change</a></li></ul></li></ul></li><li class="tocline"><a href="#sourcebuffer" class="tocxref"><span class="secno">4. </span>SourceBuffer Object</a><ul class="toc"><li class="tocline"><a href="#attributes-1" class="tocxref"><span class="secno">4.1 </span>Attributes</a></li><li class="tocline"><a href="#methods-1" class="tocxref"><span class="secno">4.2 </span>Methods</a></li><li class="tocline"><a href="#sourcebuffer-algorithms" class="tocxref"><span class="secno">4.3 </span>Algorithms</a><ul class="toc"><li class="tocline"><a href="#sourcebuffer-segment-parser-loop" class="tocxref"><span class="secno">4.3.1 </span>Segment Parser Loop</a></li><li class="tocline"><a href="#sourcebuffer-init-segment-received" class="tocxref"><span class="secno">4.3.2 </span>Initialization Segment Received</a></li><li class="tocline"><a href="#sourcebuffer-coded-frame-processing" class="tocxref"><span class="secno">4.3.3 </span>Coded Frame Processing</a></li></ul></li></ul></li><li class="tocline"><a href="#sourcebufferlist" class="tocxref"><span class="secno">5. </span>SourceBufferList Object</a><ul class="toc"><li class="tocline"><a href="#attributes-2" class="tocxref"><span class="secno">5.1 </span>Attributes</a></li><li class="tocline"><a href="#methods-2" class="tocxref"><span class="secno">5.2 </span>Methods</a></li><li class="tocline"><a href="#sourcebufferlist-events" class="tocxref"><span class="secno">5.3 </span>Event Summary</a></li></ul></li><li class="tocline"><a href="#url" class="tocxref"><span class="secno">6. </span>URL Object</a><ul class="toc"><li class="tocline"><a href="#methods-3" class="tocxref"><span class="secno">6.1 </span>Methods</a></li></ul></li><li class="tocline"><a href="#htmlmediaelement-attributes" class="tocxref"><span class="secno">7. </span>HTMLMediaElement attributes</a></li><li class="tocline"><a href="#byte-stream-formats" class="tocxref"><span class="secno">8. </span>Byte Stream Formats</a><ul class="toc"><li class="tocline"><a href="#webm" class="tocxref"><span class="secno">8.1 </span>WebM Byte Streams</a><ul class="toc"><li class="tocline"><a href="#webm-init-segments" class="tocxref"><span class="secno">8.1.1 </span>Initialization Segments</a></li><li class="tocline"><a href="#webm-media-segments" class="tocxref"><span class="secno">8.1.2 </span>Media Segments</a></li><li class="tocline"><a href="#webm-random-access-points" class="tocxref"><span class="secno">8.1.3 </span>Random Access Points</a></li></ul></li><li class="tocline"><a href="#iso" class="tocxref"><span class="secno">8.2 </span>ISO Base Media File Format Byte Streams</a><ul class="toc"><li class="tocline"><a href="#iso-init-segments" class="tocxref"><span class="secno">8.2.1 </span>Initialization Segments</a></li><li class="tocline"><a href="#iso-media-segments" class="tocxref"><span class="secno">8.2.2 </span>Media Segments</a></li><li class="tocline"><a href="#iso-random-access-points" class="tocxref"><span class="secno">8.2.3 </span>Random Access Points</a></li></ul></li></ul></li><li class="tocline"><a href="#examples" class="tocxref"><span class="secno">9. </span>Examples</a></li><li class="tocline"><a href="#revision-history" class="tocxref"><span class="secno">10. </span>Revision History</a></li></ul></section>
<section id="introduction">
@@ -545,27 +537,14 @@
<dt id="init-segment">Initialization Segment</dt>
<dd>
<p>A sequence of bytes that contains all of the initialization information required to decode a sequence of <a href="#media-segment">media segments</a>. This includes codec initialization data, <a href="#track-id">Track ID</a> mappings for multiplexed segments, and timestamp offsets (e.g. edit lists).</p>
- <dl class="example">
- <p>Container specific examples of initialization segments:</p>
- <dt>ISO Base Media File Format</dt>
- <dd>A <span class="iso-box">moov</span> box.</dd>
- <dt>WebM</dt>
- <dd>The concatenation of the the EBML Header, Segment Header, Info element, and Tracks element.</dd>
- </dl>
+ <div class="note"><div class="note-title"><span>Note</span></div><p class="">The <a href="#byte-stream-formats">byte stream format specifications</a> contain format specific examples.</p></div>
+
+ </dd><dt id="media-segment">Media Segment</dt>
+ <dd>
+ <p>A sequence of bytes that contain packetized & timestamped media data for a portion of the presentation timeline. Media segments are always associated with the most recently appended <a href="#init-segment">initialization segment</a>.</p>
+ <div class="note"><div class="note-title"><span>Note</span></div><p class="">The <a href="#byte-stream-formats">byte stream format specifications</a> contain format specific examples.</p></div>
</dd>
- <dt id="media-segment">Media Segment</dt>
- <dd>
- <p>A sequence of bytes that contain packetized & timestamped media data for a portion of the presentation timeline. Media segments are always associated with the most recently appended <a href="#init-segment">initialization segment</a>.</p>
- <dl class="example">
- <p>Container specific examples of media segments:</p>
- <dt>ISO Base Media File Format</dt>
- <dd>A <span class="iso-box">moof</span> box followed by one or more <span class="iso-box">mdat</span> boxes.</dd>
- <dt>WebM</dt>
- <dd>A Cluster element</dd>
- </dl>
- </dd>
-
<dt id="source-buffer">Source Buffer</dt>
<dd><p>A hypothetical buffer that contains a distinct sequence of <a href="#init-segment">initialization segments</a> & <a href="#media-segment">media segments</a>. When <a href="#media-segment">media segments</a> are passed to <code><a href="#widl-SourceBuffer-append-void-Uint8Array-data">append()</a></code> they update the state of this buffer. The source buffer only allows a single <a href="#media-segment">media segment</a> to cover a specific point in the presentation timeline of each track. If a <a href="#media-segment">media segment</a> gets appended that contains media data overlapping (in presentation time) with media data from an existing segment, then the new media data will override the old media data. Since <a href="#media-segment">media segments</a> depend on <a href="#init-segment">initialization segments</a> the source buffer is also responsible for maintaining these associations. During playback, the media element pulls segment data out of the source buffers, demultiplexes it if necessary, and enqueues it into <a href="#track-buffer">track buffers</a> so it will get decoded and displayed. <code><a href="#widl-SourceBuffer-buffered">buffered</a></code> describes the time ranges that are covered by <a href="#media-segment">media segments</a> in the source buffer.</p></dd>
@@ -607,18 +586,8 @@
<!--OddPage--><h2><span class="secno">2. </span>Source Buffer Model</h2>
<p>The subsections below outline the buffering model for this proposal. It describes how to add and remove <a href="#source-buffer">source buffers</a> from the presentation and describes the various rules and behaviors associated with appending data to an individual <a href="#source-buffer">source buffer</a>. At the highest level, the web application simply creates <a href="#source-buffer">source buffers</a> and appends a sequence of <a href="#init-segment">initialization segments</a> and <a href="#media-segment">media segments</a> to update the buffer's state. The media element pulls media data out of the <a href="#source-buffer">source buffers</a>, plays it, and fires events just like it would if a normal URL was passed to the <code><a href="http://dev.w3.org/html5/spec/media-elements.html#attr-media-src">src</a></code> attribute. The web application is expected to monitor media element events to determine when it needs to append more <a href="#media-segment">media segments</a>.</p>
- <section id="source-buffer-create">
- <h3><span class="secno">2.1 </span>Creating Source Buffers</h3>
- <p><a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a> objects can be created once a <a href="#idl-def-MediaSource" class="idlType"><code>MediaSource</code></a> object enters the <code><a href="#idl-def-ReadyState">"open"</a></code> state. The application calls <code><a href="#widl-MediaSource-addSourceBuffer-SourceBuffer-DOMString-type">addSourceBuffer()</a></code> with a type string that indicates the format of the data it intends to append to the new SourceBuffer. If the user agent supports the format and has sufficient resources, a new <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a> object is created, added to <code><a href="#widl-MediaSource-sourceBuffers">sourceBuffers</a></code>, and returned by the method. If the user agent doesn't support the specified format or can't support another <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a> then it will throw an appropriate exception to signal why the request couldn't be satisfied.</p>
- </section>
-
- <section id="source-buffer-remove">
- <h3><span class="secno">2.2 </span>Removing Source Buffers</h3>
- <p>Removing a <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a> with <code><a href="#widl-MediaSource-removeSourceBuffer-void-SourceBuffer-sourceBuffer">removeSourceBuffer()</a></code> releases all resources associated with the object. This includes destroying the all the segment data, <a href="#track-buffer">track buffers</a>, and decoders. The media element will also remove the appropriate tracks from <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-audiotracks">audioTracks</a></code>, <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-videotracks">videoTracks</a></code>, & <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-texttracks">textTracks</a></code> and fire the necessary <a href="http://dev.w3.org/html5/spec/media-elements.html#handler-tracklist-onchange">change</a> events. Playback may become degraded or stop if the currently selected <code><a href="http://dev.w3.org/html5/spec/media-elements.html#videotrack">VideoTrack</a></code> or the only enabled <code><a href="http://dev.w3.org/html5/spec/media-elements.html#audiotrack">AudioTracks</a></code> are removed.</p>
- </section>
-
<section id="source-buffer-basic-append">
- <h3><span class="secno">2.3 </span>Basic appending model</h3>
+ <h3><span class="secno">2.1 </span>Basic appending model</h3>
<p>Updating the state of a <a href="#source-buffer">source buffer</a> requires appending at least one <a href="#init-segment">initialization segment</a> and one or more <a href="#media-segment">media segments</a> via <code><a href="#widl-SourceBuffer-append-void-Uint8Array-data">append()</a></code>. The following list outlines some of the basic rules for appending segments.
</p><ul>
<li>The first segment appended must be an <a href="#init-segment">initialization segment</a>.</li>
@@ -634,97 +603,43 @@
<p></p>
</section>
- <section id="source-buffer-init-segment-constraints">
- <h3><span class="secno">2.4 </span>Initialization Segment constraints</h3>
- <p>To simplify the implementation and facilitate interoperability, a few constraints are placed on the <a href="#init-segment">initialization segments</a> that are appended to a specific <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a>:
- </p><ul>
- <li>The number and type of tracks must be consistent across all <a href="#init-segment">initialization segments</a>. <br>For example, if the first <a href="#init-segment">initialization segment</a> has 2 audio tracks and 1 video track, then all <a href="#init-segment">initialization segments</a> that follow, for this <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a> must describe 2 audio tracks and 1 video track.</li>
- <li>
- <a href="#track-id">Track IDs</a> do not need to be the same across <a href="#init-segment">initialization segments</a> only if the segment describes one track of each type.<br> For example, if an <a href="#init-segment">initialization segment</a> describes a single audio track and a single video track, the internal <a href="#track-id">Track IDs</a> do not need to be the same.</li>
- <li>
- <a href="#track-id">Track IDs</a> must be the same across <a href="#init-segment">initialization segments</a> if multiple tracks for a single type are described. (e.g. 2 audio tracks).</li>
- <li>Codecs changes are not allowed. <br> For example, you can't have an <a href="#init-segment">initialization segment</a> that specifies a single AAC track and then follows it with one that contains AMR-WB. Support for multiple codecs is handled with multiple <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a> objects.</li>
- <li>Video frame size changes are allowed and must be supported seamlessly.<div class="note"><div class="note-title"><span>Note</span></div><p class="">This will cause the <video> display region to change size if you don't use CSS or HTML attributes (width/height) to constrain the element size.</p></div>
- </li>
- <li>Audio channel count changes are allowed, but they may not be seamless and could trigger downmixing.<div class="note"><div class="note-title"><span>Note</span></div><p class="">This is a quality of implementation issue because changing the channel count may require reinitializing the audio device, resamplers, and channel mixers which tends to be audible.</p></div>
- </li>
- </ul>
- <p></p>
- </section>
-
- <section id="source-buffer-media-segment-constraints">
- <h3><span class="secno">2.5 </span>Media Segment constraints</h3>
- <p>To simplify the implementation and facilitate interoperability, a few constraints are placed on the <a href="#media-segment">media segments</a> that are appended to a specific <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a>:
- </p><ul>
- <li>All timestamps must be mapped to the same presentation timeline.</li>
- <li>Segments must start with a <a href="#random-access-point">random access point</a> to facilitate seamless splicing at the segment boundary.</li>
- <li>Gaps between <a href="#media-segment">media segments</a> that are smaller than the audio frame size are allowed and must not cause playback to stall. Such gaps must not be reflected by <code><a href="#widl-SourceBuffer-buffered">buffered</a></code>.
- <div class="note"><div class="note-title"><span>Note</span></div><p class="">This is intended to simplify switching between audio streams where the frame boundaries don't always line up across encodings (e.g. Vorbis).</p></div>
- </li>
- </ul>
- <p></p>
- </section>
-
- <section id="source-buffer-first-init-segment">
- <h3><span class="secno">2.6 </span>Appending the first Initialization Segment</h3>
- <p>Once a new <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a> has been created, it expects an <a href="#init-segment">initialization segment</a> to be appended first. This first segment indicates the number and type of streams contained in the <a href="#media-segment">media segments</a> that follow. This allows the media element to configure the necessary decoders and output devices. This first segment can also cause a <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-readystate">HTMLMediaElement.readyState</a></code> transition to <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-have_metadata">HAVE_METADATA</a></code> if this is the first <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a>, or if it is the first track of a specific type (i.e. first audio, first video track, or first text track). If neither of the conditions hold then the tracks for this new <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a> will just appear as disabled tracks and won't affect the current <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-readystate">HTMLMediaElement.readyState</a></code> until they are selected. The media element will also add the appropriate tracks to the <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-audiotracks">audioTracks</a></code>, <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-videotracks">videoTracks</a></code>, & <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-texttracks">textTracks</a></code> collections and fire the necessary <a href="http://dev.w3.org/html5/spec/media-elements.html#handler-tracklist-onchange">change</a> events. The description for <code><a href="#widl-SourceBuffer-append-void-Uint8Array-data">append()</a></code> contains all the details.</p>
- </section>
-
- <section id="source-buffer-media-segment-unbuffered">
- <h3><span class="secno">2.7 </span>Appending a Media Segment to an unbuffered region</h3>
- <p>If a <a href="#media-segment">media segment</a> is appended to a time range that is not covered by existing segments in the <a href="#source-buffer">source buffer</a>, then its data is copied directly into the <a href="#source-buffer">source buffer</a>. Addition of this data may trigger <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-readystate">HTMLMediaElement.readyState</a></code> transitions depending on what other data is buffered and whether the media element has determined if it can start playback. Calls to <code><a href="#widl-SourceBuffer-buffered">buffered</a></code> will always reflect the current <code><a href="http://dev.w3.org/html5/spec/media-elements.html#timeranges">TimeRanges</a></code> buffered in the <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a>.</p>
- </section>
-
<section id="source-buffer-overlapping-segments">
- <h3><span class="secno">2.8 </span>Appending a Media Segment over a buffered region</h3>
+ <h3><span class="secno">2.2 </span>Appending a Media Segment over a buffered region</h3>
<p>There are several ways that <a href="#media-segment">media segments</a> can overlap segments in the <a href="#source-buffer">source buffer</a>. Behavior for the different overlap situations are described below. If more than one overlap applies, then the <a href="#source-buffer-overlap-start">start overlap</a> gets resolved first, followed by any <a href="#source-buffer-overlap-complete">complete overlaps</a>, and finally the <a href="#source-buffer-overlap-end">end overlap</a>. If a segment contains multiple tracks then the overlap is resolved independently for each track.</p>
<section id="source-buffer-overlap-complete">
- <h4><span class="secno">2.8.1 </span>Complete Overlap</h4>
+ <h4><span class="secno">2.2.1 </span>Complete Overlap</h4>
<img src="complete_overlap.png">
<p>The figure above shows how the <a href="#source-buffer">source buffer</a> gets updated when a new <a href="#media-segment">media segment</a> completely overlaps a segment in the buffer. In this case, the new segment completely replaces the old segment.</p>
</section>
<section id="source-buffer-overlap-start">
- <h4><span class="secno">2.8.2 </span>Start Overlap</h4>
+ <h4><span class="secno">2.2.2 </span>Start Overlap</h4>
<img src="start_overlap.png">
<p>The figure above shows how the <a href="#source-buffer">source buffer</a> gets updated when the beginning of a new <a href="#media-segment">media segment</a> overlaps a segment in the buffer. In this case the new segment replaces all the old media data in the overlapping region. Since <a href="#media-segment">media segments</a> are constrained to starting with <a href="#random-access-point">random access points</a>, this provides a seamless transition between segments.</p>
<p>When an audio frame in the <a href="#source-buffer">source buffer</a> overlaps with the start of the new <a href="#media-segment">media segment</a> special behavior is required. At a minimum implementations must support dropping the old audio frame that overlaps the start of the new segment and insert silence for the small gap that is created. Higher quality implementations may support crossfading or crosslapping between the overlapping audio frames. No matter which strategy is implemented, no gaps are created in the ranges reported by <code><a href="#widl-SourceBuffer-buffered">buffered</a></code> and playback must never stall at the overlap.</p>
</section>
<section id="source-buffer-overlap-end">
- <h4><span class="secno">2.8.3 </span>End Overlap</h4>
+ <h4><span class="secno">2.2.3 </span>End Overlap</h4>
<img src="end_overlap.png">
<p>The figure above shows how the <a href="#source-buffer">source buffer</a> gets updated when the end of a new <a href="#media-segment">media segment</a> overlaps a segment in the buffer. In this case, the media element tries to keep as much of the old segment as possible. The amount saved depends on where the closest <a href="#random-access-point">random access point</a>, in the old segment, is to the end of the new segment. In the case of audio, if the gap is smaller than the size of an audio frame, then the media element should insert silence for this gap and not reflect it in <code><a href="#widl-SourceBuffer-buffered">buffered</a></code>.</p>
<p>An implementation may keep old segment data before the end of the new segment to avoid creating a gap if it wishes. Doing this though can significantly increase implementation complexity and could cause delays at the splice point. The key property that must be preserved is the entirety of the new segment gets added to the <a href="#source-buffer">source buffer</a> and it is up to the implementation how much of the old segment data is retained. The web application can use <code><a href="#widl-SourceBuffer-buffered">buffered</a></code> to determine how much of the old segment was preserved.</p>
</section>
<section id="source-buffer-overlap-middle">
- <h4><span class="secno">2.8.4 </span>Middle Overlap</h4>
+ <h4><span class="secno">2.2.4 </span>Middle Overlap</h4>
<img src="middle_overlap.png">
<p>The figure above shows how the <a href="#source-buffer">source buffer</a> gets updated when the new <a href="#media-segment">media segment</a> is in the middle of the old segment. This condition is handled by first resolving the <a href="#source-buffer-overlap-start">start overlap</a> and then resolving the <a href="#source-buffer-overlap-end">end overlap</a>.</p>
</section>
</section>
<section id="source-buffer-to-track-buffer">
- <h3><span class="secno">2.9 </span>Source Buffer to Track Buffer transfer</h3>
+ <h3><span class="secno">2.3 </span>Source Buffer to Track Buffer transfer</h3>
<p>The <a href="#source-buffer">source buffer</a> represents the media that the web application would like the media element to play. The <a href="#track-buffer">track buffer</a> contains the data that will actually get decoded and rendered. In most cases the <a href="#track-buffer">track buffer</a> will simply contain a subset of the <a href="#source-buffer">source buffer</a> near the current playback position. These two buffers start to diverge though when <a href="#media-segment">media segments</a> that overlap or are very close to the current playback position are appended. Depending on the contents of the new <a href="#media-segment">media segment</a> it may not be possible to switch to the new data immediately because there isn't a <a href="#random-access-point">random access point</a> close enough to the current playback position. The quality of the implementation determines how much data is considered "in the <a href="#track-buffer">track buffer</a>". It should transfer data to the <a href="#track-buffer">track buffer</a> as late as possible whilst maintaining seamless playback. Some implementations may be able to instantiate multiple decoders or decode the new data significantly faster than real-time to achieve a seamless splice immediately. Other implementations may delay until the next <a href="#random-access-point">random access point</a> before switching to the newly appended data. Notice that this difference in behavior is only observable when appending close to the current playback position. The <a href="#track-buffer">track buffer</a> represents a media subsegment, like a group of pictures or something with similar decode dependencies, that the media element commits to playing. This commitment may be influenced by a variety of things like limited decoding resources, hardware decode buffers, a jitter buffer, or the desire to limit implementation complexity.</p>
<p>Here is an example to help clarify the role of the <a href="#track-buffer">track buffer</a>. Say the current playback position has a timestamp of 8 and the media element pulled frames with timestamp 9 & 10 into the track buffer. The web application then appends a higher quality <a href="#media-segment">media segment</a> that starts with a <a href="#random-access-point">random access point</a> at timestamp 9. The <a href="#source-buffer">source buffer</a> will get updated with the higher quality data, but the media element won't be able to switch to this higher quality data until the next <a href="#random-access-point">random access point</a> at timestamp 20. This is because a frame for timestamp 9 is already in the track buffer. As you can see the track buffer represents the "point of no return." for decoding. If a seek occurs the media element may choose to use the higher quality data since a seek might imply flushing the <a href="#track-buffer">track buffer</a> and the user expects a break in playback.</p>
</section>
-
-
- <section id="source-buffer-segment-eviction">
- <h3><span class="secno">2.10 </span>Media Segment Eviction</h3>
- <p>When a new <a href="#media-segment">media segment</a> is appended, memory constraints may cause previously appended segments to get evicted from the <a href="#source-buffer">source buffer</a>. The eviction algorithm is implementation dependent, but segments that aren't likely to be needed soon are the most likely to get evicted. The <code><a href="#widl-SourceBuffer-buffered">buffered</a></code> attribute allows the web application to monitor what time ranges are currently buffered in the <a href="#source-buffer">source buffer</a>.</p>
- </section>
-
- <section id="source-buffer-timestamp-offsets">
- <h3><span class="secno">2.11 </span>Applying Timestamp Offsets</h3>
- <p>For some use cases like ad-insertion or seamless playlists, the web application may want to insert a <a href="#media-segment">media segment</a> in the presentation timeline at a location that is different than what the internal timestamps indicate. This can be accomplished by using the <code><a href="#widl-SourceBuffer-timestampOffset">timestampOffset</a></code> attribute on the <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a> object. The value of <code><a href="#widl-SourceBuffer-timestampOffset">timestampOffset</a></code> is added to all timestamps inside a <a href="#media-segment">media segment</a> before the contents of that segment are added to the <a href="#source-buffer">source buffer</a>. The <code><a href="#widl-SourceBuffer-timestampOffset">timestampOffset</a></code> applies to an entire media segment. An exception is thrown if the application tries to update the attribute when only part of a media segment has been appended. Both positive or negative offsets can be assigned to <code><a href="#widl-SourceBuffer-timestampOffset">timestampOffset</a></code>. If an offset causes a <a href="#media-segment">media segment</a> timestamp to get converted to a time before the <a href="#presentation-start-time">presentation start time</a>, playback will terminate with a <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-mediaerror-media_err_decode">MediaError.MEDIA_ERR_DECODE</a></code> error.</p>
-
- <p>Here is a simple example to clarify how <code><a href="#widl-SourceBuffer-timestampOffset">timestampOffset</a></code> can be used. Say I have two sounds I want to play in sequence. The first sound is 5 seconds long and the second one is 10 seconds. Both sound files have timestamps that start at 0. First append the <a href="#init-segment">initialization segment</a> and all <a href="#media-segment">media segments</a> for the first sound. Now set <code><a href="#widl-SourceBuffer-timestampOffset">timestampOffset</a></code> to 5 seconds. Finally append the <a href="#init-segment">initialization segment</a> and <a href="#media-segment">media segments</a> for the second sound. This will result in a 15 second presentation that plays the two sounds in sequence.</p>
- </section>
</section>
<section id="mediasource">
@@ -1135,9 +1050,9 @@
<li>If this object has been removed from the <code><a href="#widl-MediaSource-sourceBuffers">sourceBuffers</a></code> attribute of the <a href="#parent-media-source">parent media source</a> then throw an <code><a href="http://dom.spec.whatwg.org/#dom-domexception-invalid_state_err">INVALID_STATE_ERR</a></code> exception and abort these steps.</li>
<li>If the <code><a href="#widl-MediaSource-readyState">readyState</a></code> attribute of the <a href="#parent-media-source">parent media source</a> is not in the <code><a href="#idl-def-ReadyState">"open"</a></code> state then throw an <code><a href="http://dom.spec.whatwg.org/#dom-domexception-invalid_state_err">INVALID_STATE_ERR</a></code> exception and abort these steps.</li>
<li>The media element aborts parsing the current segment.</li>
- <li>If the <a href="#sourcebuffer-append-state">append state</a> equals <a href="#sourcebuffer-parsing-media-segment">PARSING_MEDIA_SEGMENT</a> and the <a href="#sourcebuffer-input-buffer">input buffer</a> contains some complete <a href="#coded-frame">coded frames</a>, then run the <a href="#sourcebuffer-coded-frame-processing">coded frame processing algorithm</a> as if the media segment only contained these frames.</li>
- <li>Remove all bytes from the <a href="#sourcebuffer-input-buffer">input buffer</a>.</li>
- <li>Set <a href="#sourcebuffer-append-state">append state</a> to <a href="#sourcebuffer-waiting-for-segment">WAITING_FOR_SEGMENT</a>.</li>
+ <li>If the <var><a href="#sourcebuffer-append-state">append state</a></var> equals <a href="#sourcebuffer-parsing-media-segment">PARSING_MEDIA_SEGMENT</a> and the <var><a href="#sourcebuffer-input-buffer">input buffer</a></var> contains some complete <a href="#coded-frame">coded frames</a>, then run the <a href="#sourcebuffer-coded-frame-processing">coded frame processing algorithm</a> as if the media segment only contained these frames.</li>
+ <li>Remove all bytes from the <var><a href="#sourcebuffer-input-buffer">input buffer</a></var>.</li>
+ <li>Set <var><a href="#sourcebuffer-append-state">append state</a></var> to <a href="#sourcebuffer-waiting-for-segment">WAITING_FOR_SEGMENT</a>.</li>
</ol>
<div><em>No parameters.</em></div><div><em>Return type: </em><code><a>void</a></code></div></dd><dt id="widl-SourceBuffer-append-void-Uint8Array-data"><code>append</code></dt><dd>
<p>Appends segment data to the source buffer.</p>
@@ -1157,7 +1072,11 @@
</ol>
</li>
<li>If <var>data</var>.byteLength is 0, then abort these steps.</li>
- <li>Add <var>data</var> to the end of the <a href="#sourcebuffer-input-buffer">input buffer</a>
+ <li>
+ <p>If the <var><a href="#sourcebuffer-buffer-full-flag">buffer full flag</a></var> equals true, then throw a <code><a href="http://dom.spec.whatwg.org/#dom-domexception-quota_exceeded_err">QUOTA_EXCEEDED_ERR</a></code> exception and abort these step.</p>
+ <div class="note"><div class="note-title"><span>Note</span></div><p class="">The web application must use <code><a href="#widl-SourceBuffer-remove-void-double-start-double-end">remove()</a></code> to free up space in the <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a>.</p></div>
+ </li>
+ <li>Add <var>data</var> to the end of the <var><a href="#sourcebuffer-input-buffer">input buffer</a></var>
</li>
<li>Run the <a href="#sourcebuffer-segment-parser-loop">segment parser loop</a>.</li>
</ol>
@@ -1185,6 +1104,8 @@
</li>
</ol>
</li>
+ <li>If <var><a href="#sourcebuffer-buffer-full-flag">buffer full flag</a></var> equals true and this object is ready to accept more bytes, then set
+ the <var><a href="#sourcebuffer-buffer-full-flag">buffer full flag</a></var> to false.</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">start</td><td class="prmType"><code><a>double</a></code></td><td class="prmNullFalse">✘</td><td class="prmOptFalse">✘</td><td class="prmDesc"></td></tr><tr><td class="prmName">end</td><td class="prmType"><code><a>double</a></code></td><td class="prmNullFalse">✘</td><td class="prmOptFalse">✘</td><td class="prmDesc"></td></tr></table><div><em>Return type: </em><code><a>void</a></code></div></dd></dl></section>
@@ -1220,39 +1141,43 @@
<p>The <dfn id="sourcebuffer-input-buffer">input buffer</dfn> is a byte buffer that is used to hold unparsed bytes across <code><a href="#widl-SourceBuffer-append-void-Uint8Array-data">append()</a></code> calls. The buffer is empty when the SourceBuffer object is created.</p>
- <p>While the <a href="#sourcebuffer-input-buffer">input buffer</a> is not empty, run the following steps in a loop:</p>
+ <p>The <dfn id="sourcebuffer-buffer-full-flag">buffer full flag</dfn> keeps track of whether <code><a href="#widl-SourceBuffer-append-void-Uint8Array-data">append()</a></code> is allowed to accept more
+ bytes. It is set to false when the SourceBuffer object is created and gets updated as data is appended and removed.</p>
+
+ <p>While the <var><a href="#sourcebuffer-input-buffer">input buffer</a></var> is not empty, run the following steps in a loop:</p>
<ol>
- <li>If the <a href="#sourcebuffer-input-buffer">input buffer</a> starts with bytes that violate the <a href="#byte-stream-formats">byte stream format specifications</a>, then call <code><a href="#widl-MediaSource-endOfStream-void-EndOfStreamError-error">endOfStream("decode")</a></code>, and abort this algorithm.</li>
- <li>Remove any bytes that the <a href="#byte-stream-formats">byte stream format specifications</a> say should be ignored from the start of the <a href="#sourcebuffer-input-buffer">input buffer</a>.</li>
+ <li>If the <var><a href="#sourcebuffer-input-buffer">input buffer</a></var> starts with bytes that violate the <a href="#byte-stream-formats">byte stream format specifications</a>, then call <code><a href="#widl-MediaSource-endOfStream-void-EndOfStreamError-error">endOfStream("decode")</a></code>, and abort this algorithm.</li>
+ <li>Remove any bytes that the <a href="#byte-stream-formats">byte stream format specifications</a> say should be ignored from the start of the <var><a href="#sourcebuffer-input-buffer">input buffer</a></var>.</li>
<li>
- <p>If the <a href="#sourcebuffer-append-state">append state</a> equals <a href="#sourcebuffer-waiting-for-segment">WAITING_FOR_SEGMENT</a>, then run the following steps:</p>
+ <p>If the <var><a href="#sourcebuffer-append-state">append state</a></var> equals <a href="#sourcebuffer-waiting-for-segment">WAITING_FOR_SEGMENT</a>, then run the following steps:</p>
<ol>
- <li>If the beginning of the <a href="#sourcebuffer-input-buffer">input buffer</a> indicates the start of an <a href="#init-segment">initialization segment</a>, set the <a href="#sourcebuffer-append-state">append state</a> to <a href="#sourcebuffer-parsing-init-segment">PARSING_INIT_SEGMENT</a>.</li>
- <li>If the beginning of the <a href="#sourcebuffer-input-buffer">input buffer</a> indicates the start of an <a href="#media-segment">media segment</a>, set <a href="#sourcebuffer-append-state">append state</a> to <a href="#sourcebuffer-parsing-media-segment">PARSING_MEDIA_SEGMENT</a>.</li>
+ <li>If the beginning of the <var><a href="#sourcebuffer-input-buffer">input buffer</a></var> indicates the start of an <a href="#init-segment">initialization segment</a>, set the <var><a href="#sourcebuffer-append-state">append state</a></var> to <a href="#sourcebuffer-parsing-init-segment">PARSING_INIT_SEGMENT</a>.</li>
+ <li>If the beginning of the <var><a href="#sourcebuffer-input-buffer">input buffer</a></var> indicates the start of an <a href="#media-segment">media segment</a>, set <var><a href="#sourcebuffer-append-state">append state</a></var> to <a href="#sourcebuffer-parsing-media-segment">PARSING_MEDIA_SEGMENT</a>.</li>
<li>Return to the top of the loop.</li>
</ol>
</li>
<li>
- <p>If the <a href="#sourcebuffer-append-state">append state</a> equals <a href="#sourcebuffer-parsing-init-segment">PARSING_INIT_SEGMENT</a>, then run the following steps:</p>
+ <p>If the <var><a href="#sourcebuffer-append-state">append state</a></var> equals <a href="#sourcebuffer-parsing-init-segment">PARSING_INIT_SEGMENT</a>, then run the following steps:</p>
<ol>
- <li>If the <a href="#sourcebuffer-input-buffer">input buffer</a> does not contain a complete <a href="#init-segment">initialization segment</a> yet, then exit the loop.</li>
+ <li>If the <var><a href="#sourcebuffer-input-buffer">input buffer</a></var> does not contain a complete <a href="#init-segment">initialization segment</a> yet, then exit the loop.</li>
<li>Run the <a href="#sourcebuffer-init-segment-received">initialization segment received algorithm</a>.</li>
- <li>Remove the <a href="#init-segment">initialization segment</a> bytes from the beginning of the <a href="#sourcebuffer-input-buffer">input buffer</a>.</li>
- <li>Set <a href="#sourcebuffer-append-state">append state</a> to <a href="#sourcebuffer-waiting-for-segment">WAITING_FOR_SEGMENT</a>.</li>
+ <li>Remove the <a href="#init-segment">initialization segment</a> bytes from the beginning of the <var><a href="#sourcebuffer-input-buffer">input buffer</a></var>.</li>
+ <li>Set <var><a href="#sourcebuffer-append-state">append state</a></var> to <a href="#sourcebuffer-waiting-for-segment">WAITING_FOR_SEGMENT</a>.</li>
<li>Return to the top of the loop.</li>
</ol>
</li>
<li>
- <p>If the <a href="#sourcebuffer-append-state">append state</a> equals <a href="#sourcebuffer-parsing-media-segment">PARSING_MEDIA_SEGMENT</a>, then run the following steps:</p>
+ <p>If the <var><a href="#sourcebuffer-append-state">append state</a></var> equals <a href="#sourcebuffer-parsing-media-segment">PARSING_MEDIA_SEGMENT</a>, then run the following steps:</p>
<ol>
<li>
- <p>If the <a href="#sourcebuffer-input-buffer">input buffer</a> does not contain a complete <a href="#media-segment">media segment</a> header yet, then exit the loop.</p>
+ <p>If the <var><a href="#sourcebuffer-input-buffer">input buffer</a></var> does not contain a complete <a href="#media-segment">media segment</a> header yet, then exit the loop.</p>
<div class="note"><div class="note-title"><span>Note</span></div><p class="">Implementations may choose to implement this state as an incremental parser so that it is not necessary to have the entire media segment before running the <a href="#sourcebuffer-coded-frame-processing">coded frame processing algorithm</a>.</p></div>
</li>
<li>Run the <a href="#sourcebuffer-coded-frame-processing">coded frame processing algorithm</a>.</li>
- <li>Remove the <a href="#media-segment">media segment</a> bytes from the beginning of the <a href="#sourcebuffer-input-buffer">input buffer</a>.</li>
+ <li>Remove the <a href="#media-segment">media segment</a> bytes from the beginning of the <var><a href="#sourcebuffer-input-buffer">input buffer</a></var>.</li>
+ <li>If this <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a> is full and cannot accept more media data, then set the <var><a href="#sourcebuffer-buffer-full-flag">buffer full flag</a></var> to true.</li>
<li>
- <p>Set <a href="#sourcebuffer-append-state">append state</a> to <a href="#sourcebuffer-waiting-for-segment">WAITING_FOR_SEGMENT</a>.</p>
+ <p>Set <var><a href="#sourcebuffer-append-state">append state</a></var> to <a href="#sourcebuffer-waiting-for-segment">WAITING_FOR_SEGMENT</a>.</p>
<div class="note"><div class="note-title"><span>Note</span></div><p class="">Incremental parsers should only do this transition after the entire media segment has been received.</p></div>
</li>
<li>Return to the top of the loop.</li>
@@ -1264,6 +1189,7 @@
<section id="sourcebuffer-init-segment-received">
<h4><span class="secno">4.3.2 </span>Initialization Segment Received</h4>
<p>The following steps are run when the <a href="#sourcebuffer-segment-parser-loop">segment parser loop</a> successfully parses a complete <a href="#init-segment">initialization segment</a>:</p>
+ <p>Each SourceBuffer object has an internal <dfn id="first-init-segment-flag">first initialization segment flag</dfn> that tracks whether the first <a href="#init-segment">initialization segment</a> has been appended. This flag is set to false when the SourceBuffer is created and updated by the algorithm below.</p>
<ol>
<li>Update the <code><a href="#widl-MediaSource-duration">duration</a></code> attribute if it currently equals NaN:</li>
<dl class="switch">
@@ -1272,58 +1198,87 @@
<dt>Otherwise:</dt>
<dd>Run the <a href="#duration-change-algorithm">duration change algorithm</a> with <var>new duration</var> set to positive Infinity.</dd>
</dl>
- <li>Handle state transitions:</li>
- <dl class="switch">
- <dt>If the <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-readystate">HTMLMediaElement.readyState</a></code> attribute is <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-have_nothing">HAVE_NOTHING</a></code>:</dt>
- <dd>
- <ol>
- <li>Set the <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-readystate">HTMLMediaElement.readyState</a></code> attribute to <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-have_metadata">HAVE_METADATA</a></code>.</li>
- <li>
- <a href="http://dev.w3.org/html5/spec/webappapis.html#queue-a-task">Queue a task</a> to <a href="http://dev.w3.org/html5/spec/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="http://dev.w3.org/html5/spec/media-elements.html#event-media-loadedmetadata">loadedmetadata</a></code> at the media element.</li>
- </ol>
- </dd>
- <dt>If the <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-readystate">HTMLMediaElement.readyState</a></code> attribute is greater than <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-have_current_data">HAVE_CURRENT_DATA</a></code> and the <a href="#init-segment">initialization segment</a> contains the first video or first audio track in the presentation:</dt>
- <dd>
- Set the <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-readystate">HTMLMediaElement.readyState</a></code> attribute to <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-have_metadata">HAVE_METADATA</a></code>.
- </dd>
- <dt>Otherwise:</dt>
- <dd>Continue</dd>
- </dl>
- <li>Update <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-audiotracks">audioTracks</a></code>
+ <li>If the <a href="#init-segment">initialization segment</a> has no audio, video, or text tracks, then call <code><a href="#widl-MediaSource-endOfStream-void-EndOfStreamError-error">endOfStream("decode")</a></code> and abort these steps.</li>
+ <li>
+ <p>If the <var><a href="#first-init-segment-flag">first initialization segment flag</a></var> is true, then verify the following properties. If any of the checks fail then call <code><a href="#widl-MediaSource-endOfStream-void-EndOfStreamError-error">endOfStream("decode")</a></code> and abort these steps.</p>
+ <ul>
+ <li>The number of audio, video, and text tracks match what was in the first <a href="#init-segment">initialization segment</a>.</li>
+ <li>The codecs for each track, match what was specified in the first <a href="#init-segment">initialization segment</a>.</li>
+ <li>If more than one track for a single type are present (ie 2 audio tracks), then the <a href="#track-id">Track IDs</a> match the ones in the
+ first <a href="#init-segment">initialization segment</a>.</li>
+ </ul>
</li>
- <dl class="switch">
- <dt>If <a href="#init-segment">initialization segment</a> contains the first audio track:</dt>
- <dd>
- <ol>
- <li>Add an <code><a href="http://dev.w3.org/html5/spec/media-elements.html#audiotrack">AudioTrack</a></code> and mark it as enabled.</li>
- <li>Add this <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a> to <code><a href="#widl-MediaSource-activeSourceBuffers">activeSourceBuffers</a></code>.</li>
- </ol>
- </dd>
- <dt>If <a href="#init-segment">initialization segment</a> contains audio tracks beyond those already in the presentation:</dt>
- <dd>Add a disabled <code><a href="http://dev.w3.org/html5/spec/media-elements.html#audiotrack">AudioTrack</a></code> for each audio track in the <a href="#init-segment">initialization segment</a>.</dd>
- </dl>
- <li>Update <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-videotracks">videoTracks</a></code>:</li>
- <dl class="switch">
- <dt>If <a href="#init-segment">initialization segment</a> contains the first video track:</dt>
- <dd>
- <ol>
- <li>Add a <code><a href="http://dev.w3.org/html5/spec/media-elements.html#videotrack">VideoTrack</a></code> and mark it as selected.</li>
- <li>Add this <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a> to <code><a href="#widl-MediaSource-activeSourceBuffers">activeSourceBuffers</a></code>.</li>
- </ol>
- </dd>
- <dt>If <a href="#init-segment">initialization segment</a> contains the video tracks beyond those already in the presentation:</dt>
- <dd>Add a disabled <code><a href="http://dev.w3.org/html5/spec/media-elements.html#videotrack">VideoTrack</a></code> for each video track in the <a href="#init-segment">initialization segment</a>.</dd>
- </dl>
- <li>Update <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-texttracks">textTracks</a></code>
+ <li>Let <var>active track flag</var> equal false.</li>
+ <li>
+ <p>If the <var><a href="#first-init-segment-flag">first initialization segment flag</a></var> is false, then run the following steps:</p>
+ <ol>
+ <li>
+ <p>For each audio track in the <a href="#init-segment">initialization segment</a>, run following steps:</p>
+ <ol>
+ <li>Let <var>new audio track</var> be a new <code><a href="http://dev.w3.org/html5/spec/media-elements.html#audiotrack">AudioTrack</a></code> object.</li>
+ <li>Generate a unique ID and assign it to the <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-audiotrack-id">id</a></code> property on <var>new audio track</var>.</li>
+ <li>
+ <p>
+ If <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-audiotracks">audioTracks</a></code>.<code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-audiotracklist-length">length</a></code> equals 0, then run
+ the following steps:
+ </p>
+ <ol>
+ <li>Set the <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-audiotrack-enabled">enabled</a></code> property on <var>new audio track</var> to true.</li>
+ <li>Set <var>active track flag</var> to true.</li>
+ </ol>
+ </li>
+ <li>Add <var>new audio track</var> to <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-audiotracks">audioTracks</a></code>.</li>
+ </ol>
+ </li>
+ <li>
+ <p>For each video track in the <a href="#init-segment">initialization segment</a>, run following steps:</p>
+ <ol>
+ <li>Let <var>new video track</var> be a new <code><a href="http://dev.w3.org/html5/spec/media-elements.html#videotrack">VideoTrack</a></code> object.</li>
+ <li>Generate a unique ID and assign it to the <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-videotrack-id">id</a></code> property on <var>new video track</var>.</li>
+ <li>
+ <p>
+ If <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-videotracks">videoTracks</a></code>.<code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-videotracklist-length">length</a></code> equals 0, then run
+ the following steps:
+ </p>
+ <ol>
+ <li>Set the <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-videtrack-selected">selected</a></code> property on <var>new video track</var> to true.</li>
+ <li>Set <var>active track flag</var> to true.</li>
+ </ol>
+ </li>
+ <li>Add <var>new video track</var> to <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-videotracks">videoTracks</a></code>.</li>
+ </ol>
+ </li>
+ <li>
+ <p>For each text track in the <a href="#init-segment">initialization segment</a>, run following steps:</p>
+ <ol>
+ <li>
+ Let <var>new text track</var> be a new <code><a href="http://dev.w3.org/html5/spec/media-elements.html#texttrack">TextTrack</a></code> object with its properties populated with the appropriate
+ information from the <a href="#init-segment">initialization segment</a>.</li>
+ <li>
+ If the <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-texttrack-mode">mode</a></code> property on <var>new text track</var> equals <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-texttrack-showing">"showing"</a></code> or
+ <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-texttrack-hidden">"hidden"</a></code>, then set <var>active track flag</var> to true.
+ </li>
+ <li>Add <var>new text track</var> to <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-texttracks">textTracks</a></code>.</li>
+ </ol>
+ </li>
+ <li>If <var>active track flag</var> equals true, then add this <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a> to <code><a href="#widl-MediaSource-activeSourceBuffers">activeSourceBuffers</a></code>.</li>
+ <li>Set <var><a href="#first-init-segment-flag">first initialization segment flag</a></var> to true.</li>
+ </ol>
</li>
- <dl class="switch">
- <dd>
- <ol>
- <li>Add a <code><a href="http://dev.w3.org/html5/spec/media-elements.html#texttrack">TextTrack</a></code> for each text track in the <a href="#init-segment">initialization segment</a>.</li>
- <li>If the text track <a href="http://dev.w3.org/html5/spec/media-elements.html#dom-texttrack-mode">mode</a> is <a href="http://dev.w3.org/html5/spec/media-elements.html#dom-texttrack-showing">"showing"</a> or <a href="http://dev.w3.org/html5/spec/media-elements.html#dom-texttrack-hidden">"hidden"</a> then add this <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a> to <code><a href="#widl-MediaSource-activeSourceBuffers">activeSourceBuffers</a></code>.</li>
- </ol>
- </dd>
- </dl>
+ <li>
+ <p>If the <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-readystate">HTMLMediaElement.readyState</a></code> attribute is <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-have_nothing">HAVE_NOTHING</a></code>, then run the following steps:</p>
+ <ol>
+ <li>
+ If one or more objects in <code><a href="#widl-MediaSource-activeSourceBuffers">activeSourceBuffers</a></code> have <var><a href="#first-init-segment-flag">first initialization segment flag</a></var> set to false, then abort
+ these steps.</li>
+ <li>Set the <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-readystate">HTMLMediaElement.readyState</a></code> attribute to <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-have_metadata">HAVE_METADATA</a></code>.</li>
+ <li><a href="http://dev.w3.org/html5/spec/webappapis.html#queue-a-task">Queue a task</a> to <a href="http://dev.w3.org/html5/spec/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="http://dev.w3.org/html5/spec/media-elements.html#event-media-loadedmetadata">loadedmetadata</a></code> at the media element.</li>
+ </ol>
+ </li>
+ <li>
+ If the <var>active track flag</var> equals true and the <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-readystate">HTMLMediaElement.readyState</a></code> attribute is greater than
+ <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-have_current_data">HAVE_CURRENT_DATA</a></code>, then set the <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-readystate">HTMLMediaElement.readyState</a></code> attribute to <code><a href="http://dev.w3.org/html5/spec/media-elements.html#dom-media-have_metadata">HAVE_METADATA</a></code>.
+ </li>
</ol>
</section>
@@ -1471,12 +1426,46 @@
<section id="byte-stream-formats">
<!--OddPage--><h2><span class="secno">8. </span>Byte Stream Formats</h2>
- <p>The bytes provided through <code><a href="#widl-SourceBuffer-append-void-Uint8Array-data">append()</a></code> for a <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a> form a logical byte stream. The format of this byte stream depends on the media container format in use and is defined in a byte stream format specification. Byte stream format specifications based on WebM and the ISO Base Media File Format are provided below. If these formats are supported then the byte stream formats described below must be supported.</p>
+ <p>The bytes provided through <code><a href="#widl-SourceBuffer-append-void-Uint8Array-data">append()</a></code> for a <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a> form a logical byte stream. The format of this byte stream depends on the media container format in use and is defined in a byte stream format specification. Byte stream format specifications based on WebM and the ISO Base Media File Format are provided below. These format specifications are intended to be the authoritative source for how data from these containers is formatted and passed to a <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a>. If a <a href="#idl-def-MediaSource" class="idlType"><code>MediaSource</code></a> implementation claims to support any of these container formats, then it must implement the corresponding byte stream format specification described below.</p>
<p>This section provides general requirements for all byte stream formats:</p>
<ul>
<li>A byte stream format specification must define <a href="#init-segment">initialization segments</a> and <a href="#media-segment">media segments</a>.</li>
<li>It must be possible to identify segment boundaries and segment type (initialization or media) by examining the byte stream alone.</li>
- <li>The combination of an Initialization Segment and any contiguous sequence of Media Segments associated with it must:
+ <li>The following rules apply to all <a href="#init-segment">initialization segments</a> within a byte stream:
+ <ol>
+ <li>
+ <p>The number and type of tracks must be consistent.</p>
+ <p>For example, if the first <a href="#init-segment">initialization segment</a> has 2 audio tracks and 1 video track, then all <a href="#init-segment">initialization segments</a> that follow it in the byte stream must describe 2 audio tracks and 1 video track.</p>
+ </li>
+ <li>
+ <p><a href="#track-id">Track IDs</a> do not need to be the same across <a href="#init-segment">initialization segments</a> if the segment describes only one track of each type.</p>
+ <p>For example, if an <a href="#init-segment">initialization segment</a> describes a single audio track and a single video track, the internal <a href="#track-id">Track IDs</a> do not need to be the same.</p>
+ </li>
+ <li><a href="#track-id">Track IDs</a> must be the same across <a href="#init-segment">initialization segments</a> if the segment describes multiple tracks of a single type. (e.g. 2 audio tracks).</li>
+ <li>
+ <p>Codecs changes are not allowed.</p>
+ <p>For example, a byte stream that starts with an <a href="#init-segment">initialization segment</a> that specifies a single AAC track and later contains an <a href="#init-segment">initialization segment</a> that specifies a single AMR-WB track is not allowed. Support for multiple codecs is handled with multiple <a href="#idl-def-SourceBuffer" class="idlType"><code>SourceBuffer</code></a> objects.</p>
+ </li>
+ <li>
+ <p>Video frame size changes are allowed and must be supported seamlessly.</p>
+ <div class="note"><div class="note-title"><span>Note</span></div><p class="">This will cause the <video> display region to change size if the web application does not use CSS or HTML attributes (width/height) to constrain the element size.</p></div>
+ </li>
+ <li>
+ <p>Audio channel count changes are allowed, but they may not be seamless and could trigger downmixing.</p>
+ <div class="note"><div class="note-title"><span>Note</span></div><p class="">This is a quality of implementation issue because changing the channel count may require reinitializing the audio device, resamplers, and channel mixers which tends to be audible.</p></div>
+ </li>
+ </ol>
+ </li>
+ <li>The following rules apply to all <a href="#media-segment">media segments</a> within a byte stream:
+ <ol>
+ <li>All timestamps must be mapped to the same presentation timeline.</li>
+ <li>Segments must start with a <a href="#random-access-point">random access point</a> to facilitate seamless splicing at the segment boundary.</li>
+ <li>Gaps between <a href="#media-segment">media segments</a> that are smaller than the audio frame size are allowed and must not cause playback to stall. Such gaps must not be reflected by <code><a href="#widl-SourceBuffer-buffered">buffered</a></code>.
+ <div class="note"><div class="note-title"><span>Note</span></div><p class="">This is intended to simplify switching between audio streams where the frame boundaries don't always line up across encodings (e.g. Vorbis).</p></div>
+ </li>
+ </ol>
+ </li>
+ <li>The combination of an <a href="#init-segment">initialization segment</a> and any contiguous sequence of <a href="#media-segment">media segments</a> associated with it must:
<ol>
<li>Identify the number and type (audio, video, text, etc.) of tracks in the Segments</li>
<li>Identify the decoding capabilities needed to decode each track (i.e. codec and codec parameters)</li>
@@ -1659,7 +1648,19 @@
</thead>
<tbody>
<tr>
- <td>28 November 2012</td>
+ <td>06 December 2012</td>
+ <td>
+ <ul>
+ <li>append() now throws a QUOTA_EXCEEDED_ERR when the SourceBuffer is full.</li>
+ <li>Added unique ID generation text to Initialization Segment Received algorithm.</li>
+ <li>Remove 2.x subsections that are already covered by algorithm text.</li>
+ <li>Rework byte stream format text so it doesn't imply that the MediaSource implementation must support all formats supported by the
+ HTMLMediaElement.</li>
+ </ul>
+ </td>
+ </tr>
+ <tr>
+ <td><a href="http://dvcs.w3.org/hg/html-media/rev/0c638da9a67a">28 November 2012</a></td>
<td>
<ul>
<li>Added transition to HAVE_METADATA when current playback position is removed.</li>
--- a/media-source/media-source.js Tue Nov 27 16:15:18 2012 -0800
+++ b/media-source/media-source.js Tue Dec 04 09:22:40 2012 -0800
@@ -31,6 +31,10 @@
link_helper(doc, df, '#'+ id, text);
}
+ function var_helper(doc, df, id, text) {
+ df.appendChild($("<var/>").wrapInner($("<a/>").attr({href: id}).text(text))[0]);
+ }
+
function link_helper(doc, df, id, text) {
df.appendChild($("<a/>").attr({href: id}).text(text)[0]);
}
@@ -65,8 +69,9 @@
'eos-decode': { func: idlref_helper, fragment: 'widl-MediaSource-endOfStream-void-EndOfStreamError-error', link_text: 'endOfStream("decode")', },
'readyState': { func: idlref_helper, fragment: 'widl-MediaSource-readyState', link_text: 'readyState', },
'duration': { func: idlref_helper, fragment: 'widl-MediaSource-duration', link_text: 'duration', },
+ 'abort': { func: idlref_helper, fragment: 'widl-SourceBuffer-abort-void', link_text: 'abort()', },
'append': { func: idlref_helper, fragment: 'widl-SourceBuffer-append-void-Uint8Array-data', link_text: 'append()', },
- 'abort': { func: idlref_helper, fragment: 'widl-SourceBuffer-abort-void', link_text: 'abort()', },
+ 'remove': { func: idlref_helper, fragment: 'widl-SourceBuffer-remove-void-double-start-double-end', link_text: 'remove()', },
'buffered': { func: idlref_helper, fragment: 'widl-SourceBuffer-buffered', link_text: 'buffered', },
'timestampOffset': { func: idlref_helper, fragment: 'widl-SourceBuffer-timestampOffset', link_text: 'timestampOffset', },
'length': { func: idlref_helper, fragment: 'widl-SourceBufferList-length', link_text: 'length', },
@@ -105,15 +110,17 @@
'duration-change-algorithm': { func: link_helper, fragment: '#duration-change-algorithm', link_text: 'duration change algorithm', },
'segment-parser-loop': { func: link_helper, fragment: '#sourcebuffer-segment-parser-loop', link_text: 'segment parser loop', },
- 'append-state': { func: link_helper, fragment: '#sourcebuffer-append-state', link_text: 'append state', },
+ 'append-state': { func: var_helper, fragment: '#sourcebuffer-append-state', link_text: 'append state', },
'waiting-for-segment': { func: link_helper, fragment: '#sourcebuffer-waiting-for-segment', link_text: 'WAITING_FOR_SEGMENT', },
'parsing-init-segment': { func: link_helper, fragment: '#sourcebuffer-parsing-init-segment', link_text: 'PARSING_INIT_SEGMENT', },
'parsing-media-segment': { func: link_helper, fragment: '#sourcebuffer-parsing-media-segment', link_text: 'PARSING_MEDIA_SEGMENT', },
'byte-stream-format-specs': { func: link_helper, fragment: '#byte-stream-formats', link_text: 'byte stream format specifications', },
'init-segment-received-algorithm': { func: link_helper, fragment: '#sourcebuffer-init-segment-received', link_text: 'initialization segment received algorithm', },
'coded-frame-processing-algorithm': { func: link_helper, fragment: '#sourcebuffer-coded-frame-processing', link_text: 'coded frame processing algorithm', },
- 'input-buffer': { func: link_helper, fragment: '#sourcebuffer-input-buffer', link_text: 'input buffer', },
+ 'input-buffer': { func: var_helper, fragment: '#sourcebuffer-input-buffer', link_text: 'input buffer', },
+ 'buffer-full-flag': { func: var_helper, fragment: '#sourcebuffer-buffer-full-flag', link_text: 'buffer full flag', },
'MediaSource-object-URL': { func: link_helper, fragment: '#mediasource-object-url', link_text: 'MediaSource object URL', },
+ 'first-init-segment-flag': { func: var_helper, fragment: '#first-init-segment-flag', link_text: 'first initialization segment flag', },
'FileAPI': { func: fileapi_helper, fragment: '', link_text: 'File API', },
'blob-uri': { func: fileapi_helper, fragment: 'url', link_text: 'Blob URI', },
@@ -134,13 +141,22 @@
'media-src': { func: code_videoref_helper, fragment: 'attr-media-src', link_text: 'src', },
'timerange': { func: code_videoref_helper, fragment: 'timeranges', link_text: 'TimeRange', },
'timeranges': { func: code_videoref_helper, fragment: 'timeranges', link_text: 'TimeRanges', },
+ 'timeranges-length': { func: code_videoref_helper, fragment: 'dom-timeranges-length', link_text: 'length', },
'video-track': { func: code_videoref_helper, fragment: 'videotrack', link_text: 'VideoTrack', },
+ 'videotrack-id': { func: code_videoref_helper, fragment: 'dom-videotrack-id', link_text: 'id', },
+ 'videotrack-selected': { func: code_videoref_helper, fragment: 'dom-videtrack-selected', link_text: 'selected', },
+ 'videotracklist-length': { func: code_videoref_helper, fragment: 'dom-videotracklist-length', link_text: 'length', },
'videotracks': { func: code_videoref_helper, fragment: 'dom-media-videotracks', link_text: 'videoTracks', },
'audio-track': { func: code_videoref_helper, fragment: 'audiotrack', link_text: 'AudioTrack', },
- 'audio-tracks': { func: code_videoref_helper, fragment: 'audiotrack', link_text: 'AudioTracks', },
+ 'audiotracklist-length': { func: code_videoref_helper, fragment: 'dom-audiotracklist-length', link_text: 'length', },
'audiotracks': { func: code_videoref_helper, fragment: 'dom-media-audiotracks', link_text: 'audioTracks', },
+ 'audiotrack-id': { func: code_videoref_helper, fragment: 'dom-audiotrack-id', link_text: 'id', },
+ 'audiotrack-enabled': { func: code_videoref_helper, fragment: 'dom-audiotrack-enabled', link_text: 'enabled', },
'text-track': { func: code_videoref_helper, fragment: 'texttrack', link_text: 'TextTrack', },
'texttracks': { func: code_videoref_helper, fragment: 'dom-media-texttracks', link_text: 'textTracks', },
+ 'texttrack-mode': { func: code_videoref_helper, fragment: 'dom-texttrack-mode', link_text: 'mode', },
+ 'texttrack-showing': { func: code_videoref_helper, fragment: 'dom-texttrack-showing', link_text: '"showing"', },
+ 'texttrack-hidden': { func: code_videoref_helper, fragment: 'dom-texttrack-hidden', link_text: '"hidden"', },
'ready-state': { func: code_videoref_helper, fragment: 'dom-media-readystate', link_text: 'HTMLMediaElement.readyState', },
'have-nothing': { func: code_videoref_helper, fragment: 'dom-media-have_nothing', link_text: 'HAVE_NOTHING', },
'have-metadata': { func: code_videoref_helper, fragment: 'dom-media-have_metadata', link_text: 'HAVE_METADATA', },