2 * Copyright (C) 2013 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "modules/mediasource/SourceBuffer.h"
34 #include "bindings/v8/ExceptionState.h"
35 #include "core/dom/ExceptionCode.h"
36 #include "core/dom/ExecutionContext.h"
37 #include "core/events/Event.h"
38 #include "core/events/GenericEventQueue.h"
39 #include "core/fileapi/FileReaderLoader.h"
40 #include "core/fileapi/Stream.h"
41 #include "core/html/TimeRanges.h"
42 #include "modules/mediasource/MediaSource.h"
43 #include "platform/Logging.h"
44 #include "platform/TraceEvent.h"
45 #include "public/platform/WebSourceBuffer.h"
46 #include "wtf/ArrayBuffer.h"
47 #include "wtf/ArrayBufferView.h"
48 #include "wtf/MathExtras.h"
52 using blink::WebSourceBuffer;
56 DEFINE_GC_INFO(SourceBuffer);
58 PassRefPtrWillBeRawPtr<SourceBuffer> SourceBuffer::create(PassOwnPtr<WebSourceBuffer> webSourceBuffer, MediaSource* source, GenericEventQueue* asyncEventQueue)
60 RefPtrWillBeRawPtr<SourceBuffer> sourceBuffer(adoptRefCountedWillBeRefCountedGarbageCollected(new SourceBuffer(webSourceBuffer, source, asyncEventQueue)));
61 sourceBuffer->suspendIfNeeded();
62 return sourceBuffer.release();
65 SourceBuffer::SourceBuffer(PassOwnPtr<WebSourceBuffer> webSourceBuffer, MediaSource* source, GenericEventQueue* asyncEventQueue)
66 : ActiveDOMObject(source->executionContext())
67 , m_webSourceBuffer(webSourceBuffer)
69 , m_asyncEventQueue(asyncEventQueue)
70 , m_mode(segmentsKeyword())
72 , m_timestampOffset(0)
73 , m_appendWindowStart(0)
74 , m_appendWindowEnd(std::numeric_limits<double>::infinity())
75 , m_appendBufferAsyncPartRunner(this, &SourceBuffer::appendBufferAsyncPart)
76 , m_pendingRemoveStart(-1)
77 , m_pendingRemoveEnd(-1)
78 , m_removeAsyncPartRunner(this, &SourceBuffer::removeAsyncPart)
79 , m_streamMaxSizeValid(false)
81 , m_appendStreamAsyncPartRunner(this, &SourceBuffer::appendStreamAsyncPart)
83 ASSERT(m_webSourceBuffer);
85 ScriptWrappable::init(this);
88 SourceBuffer::~SourceBuffer()
95 const AtomicString& SourceBuffer::segmentsKeyword()
97 DEFINE_STATIC_LOCAL(const AtomicString, segments, ("segments", AtomicString::ConstructFromLiteral));
101 const AtomicString& SourceBuffer::sequenceKeyword()
103 DEFINE_STATIC_LOCAL(const AtomicString, sequence, ("sequence", AtomicString::ConstructFromLiteral));
107 void SourceBuffer::setMode(const AtomicString& newMode, ExceptionState& exceptionState)
109 // Section 3.1 On setting mode attribute steps.
110 // 1. Let new mode equal the new value being assigned to this attribute.
111 // 2. If new mode does not equal "segments" or "sequence", then throw an INVALID_ACCESS_ERR exception and abort
113 // Step 2 is unnecessary: IDL enforcement prevents this case and should just return immediately to script
114 // without calling this method in this case.
115 // 3. If this object has been removed from the sourceBuffers attribute of the parent media source, then throw
116 // an INVALID_STATE_ERR exception and abort these steps.
117 // 4. If the updating attribute equals true, then throw an INVALID_STATE_ERR exception and abort these steps.
118 if (isRemoved() || m_updating) {
119 exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
123 // 5. If the readyState attribute of the parent media source is in the "ended" state then run the following steps:
124 // 5.1 Set the readyState attribute of the parent media source to "open"
125 // 5.2 Queue a task to fire a simple event named sourceopen at the parent media source.
126 m_source->openIfInEndedState();
128 // 6. If the append state equals PARSING_MEDIA_SEGMENT, then throw an INVALID_STATE_ERR and abort these steps.
129 // 7. If the new mode equals "sequence", then set the group start timestamp to the highest presentation end timestamp.
130 WebSourceBuffer::AppendMode appendMode = WebSourceBuffer::AppendModeSegments;
131 if (newMode == sequenceKeyword())
132 appendMode = WebSourceBuffer::AppendModeSequence;
133 if (!m_webSourceBuffer->setMode(appendMode)) {
134 exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
138 // 8. Update the attribute to new mode.
142 PassRefPtr<TimeRanges> SourceBuffer::buffered(ExceptionState& exceptionState) const
144 // Section 3.1 buffered attribute steps.
145 // 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an
146 // InvalidStateError exception and abort these steps.
148 exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
152 // 2. Return a new static normalized TimeRanges object for the media segments buffered.
153 return TimeRanges::create(m_webSourceBuffer->buffered());
156 double SourceBuffer::timestampOffset() const
158 return m_timestampOffset;
161 void SourceBuffer::setTimestampOffset(double offset, ExceptionState& exceptionState)
163 // Section 3.1 timestampOffset attribute setter steps.
164 // 1. Let new timestamp offset equal the new value being assigned to this attribute.
165 // 2. If this object has been removed from the sourceBuffers attribute of the parent media source, then throw an
166 // InvalidStateError exception and abort these steps.
167 // 3. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
168 if (isRemoved() || m_updating) {
169 exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
173 // 4. If the readyState attribute of the parent media source is in the "ended" state then run the following steps:
174 // 4.1 Set the readyState attribute of the parent media source to "open"
175 // 4.2 Queue a task to fire a simple event named sourceopen at the parent media source.
176 m_source->openIfInEndedState();
178 // 5. If the append state equals PARSING_MEDIA_SEGMENT, then throw an INVALID_STATE_ERR and abort these steps.
179 // 6. If the mode attribute equals "sequence", then set the group start timestamp to new timestamp offset.
180 if (!m_webSourceBuffer->setTimestampOffset(offset)) {
181 exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
185 // 7. Update the attribute to new timestamp offset.
186 m_timestampOffset = offset;
189 double SourceBuffer::appendWindowStart() const
191 return m_appendWindowStart;
194 void SourceBuffer::setAppendWindowStart(double start, ExceptionState& exceptionState)
196 // Enforce throwing an exception on restricted double values.
197 if (std::isnan(start)
198 || start == std::numeric_limits<double>::infinity()
199 || start == -std::numeric_limits<double>::infinity()) {
200 exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError);
204 // Section 3.1 appendWindowStart attribute setter steps.
205 // 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an
206 // InvalidStateError exception and abort these steps.
207 // 2. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
208 if (isRemoved() || m_updating) {
209 exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
213 // 3. If the new value is less than 0 or greater than or equal to appendWindowEnd then throw an InvalidAccessError
214 // exception and abort these steps.
215 if (start < 0 || start >= m_appendWindowEnd) {
216 exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
220 m_webSourceBuffer->setAppendWindowStart(start);
222 // 4. Update the attribute to the new value.
223 m_appendWindowStart = start;
226 double SourceBuffer::appendWindowEnd() const
228 return m_appendWindowEnd;
231 void SourceBuffer::setAppendWindowEnd(double end, ExceptionState& exceptionState)
233 // Section 3.1 appendWindowEnd attribute setter steps.
234 // 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an
235 // InvalidStateError exception and abort these steps.
236 // 2. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
237 if (isRemoved() || m_updating) {
238 exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
242 // 3. If the new value equals NaN, then throw an InvalidAccessError and abort these steps.
243 // 4. If the new value is less than or equal to appendWindowStart then throw an InvalidAccessError
244 // exception and abort these steps.
245 if (std::isnan(end) || end <= m_appendWindowStart) {
246 exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
250 m_webSourceBuffer->setAppendWindowEnd(end);
252 // 5. Update the attribute to the new value.
253 m_appendWindowEnd = end;
256 void SourceBuffer::appendBuffer(PassRefPtr<ArrayBuffer> data, ExceptionState& exceptionState)
258 // Section 3.2 appendBuffer()
259 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-appendBuffer-void-ArrayBufferView-data
260 // 1. If data is null then throw an InvalidAccessError exception and abort these steps.
262 exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
266 appendBufferInternal(static_cast<const unsigned char*>(data->data()), data->byteLength(), exceptionState);
269 void SourceBuffer::appendBuffer(PassRefPtr<ArrayBufferView> data, ExceptionState& exceptionState)
271 // Section 3.2 appendBuffer()
272 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-appendBuffer-void-ArrayBufferView-data
273 // 1. If data is null then throw an InvalidAccessError exception and abort these steps.
275 exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
279 appendBufferInternal(static_cast<const unsigned char*>(data->baseAddress()), data->byteLength(), exceptionState);
282 void SourceBuffer::appendStream(PassRefPtr<Stream> stream, ExceptionState& exceptionState)
284 m_streamMaxSizeValid = false;
285 appendStreamInternal(stream, exceptionState);
288 void SourceBuffer::appendStream(PassRefPtr<Stream> stream, unsigned long long maxSize, ExceptionState& exceptionState)
290 m_streamMaxSizeValid = maxSize > 0;
291 if (m_streamMaxSizeValid)
292 m_streamMaxSize = maxSize;
293 appendStreamInternal(stream, exceptionState);
296 void SourceBuffer::abort(ExceptionState& exceptionState)
298 // Section 3.2 abort() method steps.
299 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-abort-void
300 // 1. If this object has been removed from the sourceBuffers attribute of the parent media source
301 // then throw an InvalidStateError exception and abort these steps.
302 // 2. If the readyState attribute of the parent media source is not in the "open" state
303 // then throw an InvalidStateError exception and abort these steps.
304 if (isRemoved() || !m_source->isOpen()) {
305 exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
309 // 3. If the sourceBuffer.updating attribute equals true, then run the following steps: ...
312 // 4. Run the reset parser state algorithm.
313 m_webSourceBuffer->abort();
315 // 5. Set appendWindowStart to 0.
316 setAppendWindowStart(0, exceptionState);
318 // 6. Set appendWindowEnd to positive Infinity.
319 setAppendWindowEnd(std::numeric_limits<double>::infinity(), exceptionState);
322 void SourceBuffer::remove(double start, double end, ExceptionState& exceptionState)
324 // Section 3.2 remove() method steps.
325 // 1. If start is negative or greater than duration, then throw an InvalidAccessError exception and abort these steps.
326 // 2. If end is less than or equal to start, then throw an InvalidAccessError exception and abort these steps.
327 if (start < 0 || (m_source && (std::isnan(m_source->duration()) || start > m_source->duration())) || end <= start) {
328 exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
332 // 3. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an
333 // InvalidStateError exception and abort these steps.
334 // 4. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
335 if (isRemoved() || m_updating) {
336 exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
340 TRACE_EVENT_ASYNC_BEGIN0("media", "SourceBuffer::remove", this);
342 // 5. If the readyState attribute of the parent media source is in the "ended" state then run the following steps:
343 // 5.1. Set the readyState attribute of the parent media source to "open"
344 // 5.2. Queue a task to fire a simple event named sourceopen at the parent media source .
345 m_source->openIfInEndedState();
347 // 6. Set the updating attribute to true.
350 // 7. Queue a task to fire a simple event named updatestart at this SourceBuffer object.
351 scheduleEvent(EventTypeNames::updatestart);
353 // 8. Return control to the caller and run the rest of the steps asynchronously.
354 m_pendingRemoveStart = start;
355 m_pendingRemoveEnd = end;
356 m_removeAsyncPartRunner.runAsync();
359 void SourceBuffer::abortIfUpdating()
361 // Section 3.2 abort() method step 3 substeps.
362 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-abort-void
367 const char* traceEventName = 0;
368 if (!m_pendingAppendData.isEmpty()) {
369 traceEventName = "SourceBuffer::appendBuffer";
370 } else if (m_stream) {
371 traceEventName = "SourceBuffer::appendStream";
372 } else if (m_pendingRemoveStart != -1) {
373 traceEventName = "SourceBuffer::remove";
375 ASSERT_NOT_REACHED();
378 // 3.1. Abort the buffer append and stream append loop algorithms if they are running.
379 m_appendBufferAsyncPartRunner.stop();
380 m_pendingAppendData.clear();
382 m_removeAsyncPartRunner.stop();
383 m_pendingRemoveStart = -1;
384 m_pendingRemoveEnd = -1;
386 m_appendStreamAsyncPartRunner.stop();
387 clearAppendStreamState();
389 // 3.2. Set the updating attribute to false.
392 // 3.3. Queue a task to fire a simple event named abort at this SourceBuffer object.
393 scheduleEvent(EventTypeNames::abort);
395 // 3.4. Queue a task to fire a simple event named updateend at this SourceBuffer object.
396 scheduleEvent(EventTypeNames::updateend);
398 TRACE_EVENT_ASYNC_END0("media", traceEventName, this);
401 void SourceBuffer::removedFromMediaSource()
408 m_webSourceBuffer->removedFromMediaSource();
409 m_webSourceBuffer.clear();
411 m_asyncEventQueue = 0;
414 bool SourceBuffer::hasPendingActivity() const
419 void SourceBuffer::suspend()
421 m_appendBufferAsyncPartRunner.suspend();
422 m_removeAsyncPartRunner.suspend();
423 m_appendStreamAsyncPartRunner.suspend();
426 void SourceBuffer::resume()
428 m_appendBufferAsyncPartRunner.resume();
429 m_removeAsyncPartRunner.resume();
430 m_appendStreamAsyncPartRunner.resume();
433 void SourceBuffer::stop()
435 m_appendBufferAsyncPartRunner.stop();
436 m_removeAsyncPartRunner.stop();
437 m_appendStreamAsyncPartRunner.stop();
440 ExecutionContext* SourceBuffer::executionContext() const
442 return ActiveDOMObject::executionContext();
445 const AtomicString& SourceBuffer::interfaceName() const
447 return EventTargetNames::SourceBuffer;
450 bool SourceBuffer::isRemoved() const
455 void SourceBuffer::scheduleEvent(const AtomicString& eventName)
457 ASSERT(m_asyncEventQueue);
459 RefPtr<Event> event = Event::create(eventName);
460 event->setTarget(this);
462 m_asyncEventQueue->enqueueEvent(event.release());
465 void SourceBuffer::appendBufferInternal(const unsigned char* data, unsigned size, ExceptionState& exceptionState)
467 // Section 3.2 appendBuffer()
468 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-appendBuffer-void-ArrayBufferView-data
470 // Step 1 is enforced by the caller.
471 // 2. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an InvalidStateError exception and abort these steps.
472 // 3. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
473 if (isRemoved() || m_updating) {
474 exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
478 TRACE_EVENT_ASYNC_BEGIN0("media", "SourceBuffer::appendBuffer", this);
480 // 4. If the readyState attribute of the parent media source is in the "ended" state then run the following steps: ...
481 m_source->openIfInEndedState();
485 // 7. Add data to the end of the input buffer.
486 m_pendingAppendData.append(data, size);
488 // 8. Set the updating attribute to true.
491 // 9. Queue a task to fire a simple event named updatestart at this SourceBuffer object.
492 scheduleEvent(EventTypeNames::updatestart);
494 // 10. Asynchronously run the buffer append algorithm.
495 m_appendBufferAsyncPartRunner.runAsync();
497 TRACE_EVENT_ASYNC_STEP_INTO0("media", "SourceBuffer::appendBuffer", this, "waiting");
500 void SourceBuffer::appendBufferAsyncPart()
504 TRACE_EVENT_ASYNC_STEP_INTO0("media", "SourceBuffer::appendBuffer", this, "appending");
506 // Section 3.5.4 Buffer Append Algorithm
507 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#sourcebuffer-buffer-append
509 // 1. Run the segment parser loop algorithm.
510 // Step 2 doesn't apply since we run Step 1 synchronously here.
511 size_t appendSize = m_pendingAppendData.size();
513 // Resize buffer for 0 byte appends so we always have a valid pointer.
514 // We need to convey all appends, even 0 byte ones to |m_webSourceBuffer|
515 // so that it can clear its end of stream state if necessary.
516 m_pendingAppendData.resize(1);
518 m_webSourceBuffer->append(m_pendingAppendData.data(), appendSize);
520 // 3. Set the updating attribute to false.
522 m_pendingAppendData.clear();
524 // 4. Queue a task to fire a simple event named update at this SourceBuffer object.
525 scheduleEvent(EventTypeNames::update);
527 // 5. Queue a task to fire a simple event named updateend at this SourceBuffer object.
528 scheduleEvent(EventTypeNames::updateend);
529 TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendBuffer", this);
532 void SourceBuffer::removeAsyncPart()
535 ASSERT(m_pendingRemoveStart >= 0);
536 ASSERT(m_pendingRemoveStart < m_pendingRemoveEnd);
538 // Section 3.2 remove() method steps
539 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-remove-void-double-start-double-end
541 // 9. Run the coded frame removal algorithm with start and end as the start and end of the removal range.
542 m_webSourceBuffer->remove(m_pendingRemoveStart, m_pendingRemoveEnd);
544 // 10. Set the updating attribute to false.
546 m_pendingRemoveStart = -1;
547 m_pendingRemoveEnd = -1;
549 // 11. Queue a task to fire a simple event named update at this SourceBuffer object.
550 scheduleEvent(EventTypeNames::update);
552 // 12. Queue a task to fire a simple event named updateend at this SourceBuffer object.
553 scheduleEvent(EventTypeNames::updateend);
556 void SourceBuffer::appendStreamInternal(PassRefPtr<Stream> stream, ExceptionState& exceptionState)
558 // Section 3.2 appendStream()
559 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-appendStream-void-Stream-stream-unsigned-long-long-maxSize
560 // 1. If stream is null then throw an InvalidAccessError exception and abort these steps.
561 if (!stream || stream->isNeutered()) {
562 exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
566 // 2. Run the prepare append algorithm.
567 // Section 3.5.4 Prepare Append Algorithm.
568 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#sourcebuffer-prepare-append
569 // 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an InvalidStateError exception and abort these steps.
570 // 2. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
571 if (isRemoved() || m_updating) {
572 exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
576 TRACE_EVENT_ASYNC_BEGIN0("media", "SourceBuffer::appendStream", this);
578 // 3. If the readyState attribute of the parent media source is in the "ended" state then run the following steps: ...
579 m_source->openIfInEndedState();
581 // Steps 4-5 of the prepare append algorithm are handled by m_webSourceBuffer.
583 // 3. Set the updating attribute to true.
586 // 4. Queue a task to fire a simple event named updatestart at this SourceBuffer object.
587 scheduleEvent(EventTypeNames::updatestart);
589 // 5. Asynchronously run the stream append loop algorithm with stream and maxSize.
592 m_loader = adoptPtr(new FileReaderLoader(FileReaderLoader::ReadByClient, this));
594 m_appendStreamAsyncPartRunner.runAsync();
597 void SourceBuffer::appendStreamAsyncPart()
603 // Section 3.5.6 Stream Append Loop
604 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#sourcebuffer-stream-append-loop
606 // 1. If maxSize is set, then let bytesLeft equal maxSize.
607 // 2. Loop Top: If maxSize is set and bytesLeft equals 0, then jump to the loop done step below.
608 if (m_streamMaxSizeValid && !m_streamMaxSize) {
609 appendStreamDone(true);
613 // Steps 3-11 are handled by m_loader.
614 // Note: Passing 0 here signals that maxSize was not set. (i.e. Read all the data in the stream).
615 m_loader->start(executionContext(), *m_stream, m_streamMaxSizeValid ? m_streamMaxSize : 0);
618 void SourceBuffer::appendStreamDone(bool success)
624 clearAppendStreamState();
627 // Section 3.5.3 Append Error Algorithm
628 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#sourcebuffer-append-error
630 // 1. Run the reset parser state algorithm. (Handled by caller)
631 // 2. Set the updating attribute to false.
634 // 3. Queue a task to fire a simple event named error at this SourceBuffer object.
635 scheduleEvent(EventTypeNames::error);
637 // 4. Queue a task to fire a simple event named updateend at this SourceBuffer object.
638 scheduleEvent(EventTypeNames::updateend);
639 TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendStream", this);
643 // Section 3.5.6 Stream Append Loop
644 // Steps 1-11 are handled by appendStreamAsyncPart(), |m_loader|, and |m_webSourceBuffer|.
645 // 12. Loop Done: Set the updating attribute to false.
648 // 13. Queue a task to fire a simple event named update at this SourceBuffer object.
649 scheduleEvent(EventTypeNames::update);
651 // 14. Queue a task to fire a simple event named updateend at this SourceBuffer object.
652 scheduleEvent(EventTypeNames::updateend);
653 TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendStream", this);
656 void SourceBuffer::clearAppendStreamState()
658 m_streamMaxSizeValid = false;
664 void SourceBuffer::didStartLoading()
666 WTF_LOG(Media, "SourceBuffer::didStartLoading() %p", this);
669 void SourceBuffer::didReceiveDataForClient(const char* data, unsigned dataLength)
671 WTF_LOG(Media, "SourceBuffer::didReceiveDataForClient(%d) %p", dataLength, this);
675 m_webSourceBuffer->append(reinterpret_cast<const unsigned char*>(data), dataLength);
678 void SourceBuffer::didFinishLoading()
680 WTF_LOG(Media, "SourceBuffer::didFinishLoading() %p", this);
681 appendStreamDone(true);
684 void SourceBuffer::didFail(FileError::ErrorCode errorCode)
686 WTF_LOG(Media, "SourceBuffer::didFail(%d) %p", errorCode, this);
687 appendStreamDone(false);
690 void SourceBuffer::trace(Visitor* visitor)
692 visitor->trace(m_source);
695 } // namespace WebCore