- add third_party src.
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / modules / mediasource / SourceBuffer.cpp
1 /*
2  * Copyright (C) 2013 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
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
13  * distribution.
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.
17  *
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.
29  */
30
31 #include "config.h"
32 #include "modules/mediasource/SourceBuffer.h"
33
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 "core/platform/graphics/SourceBufferPrivate.h"
43 #include "modules/mediasource/MediaSource.h"
44 #include "platform/Logging.h"
45 #include "platform/TraceEvent.h"
46 #include "wtf/ArrayBuffer.h"
47 #include "wtf/ArrayBufferView.h"
48 #include "wtf/MathExtras.h"
49
50 #include <limits>
51
52 namespace WebCore {
53
54 PassRefPtr<SourceBuffer> SourceBuffer::create(PassOwnPtr<SourceBufferPrivate> sourceBufferPrivate, MediaSource* source, GenericEventQueue* asyncEventQueue)
55 {
56     RefPtr<SourceBuffer> sourceBuffer(adoptRef(new SourceBuffer(sourceBufferPrivate, source, asyncEventQueue)));
57     sourceBuffer->suspendIfNeeded();
58     return sourceBuffer.release();
59 }
60
61 SourceBuffer::SourceBuffer(PassOwnPtr<SourceBufferPrivate> sourceBufferPrivate, MediaSource* source, GenericEventQueue* asyncEventQueue)
62     : ActiveDOMObject(source->executionContext())
63     , m_private(sourceBufferPrivate)
64     , m_source(source)
65     , m_asyncEventQueue(asyncEventQueue)
66     , m_updating(false)
67     , m_timestampOffset(0)
68     , m_appendWindowStart(0)
69     , m_appendWindowEnd(std::numeric_limits<double>::infinity())
70     , m_appendBufferAsyncPartRunner(this, &SourceBuffer::appendBufferAsyncPart)
71     , m_pendingRemoveStart(-1)
72     , m_pendingRemoveEnd(-1)
73     , m_removeAsyncPartRunner(this, &SourceBuffer::removeAsyncPart)
74     , m_streamMaxSizeValid(false)
75     , m_streamMaxSize(0)
76     , m_appendStreamAsyncPartRunner(this, &SourceBuffer::appendStreamAsyncPart)
77 {
78     ASSERT(m_private);
79     ASSERT(m_source);
80     ScriptWrappable::init(this);
81 }
82
83 SourceBuffer::~SourceBuffer()
84 {
85     ASSERT(isRemoved());
86     ASSERT(!m_loader);
87     ASSERT(!m_stream);
88 }
89
90 PassRefPtr<TimeRanges> SourceBuffer::buffered(ExceptionState& es) const
91 {
92     // Section 3.1 buffered attribute steps.
93     // 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an
94     //    InvalidStateError exception and abort these steps.
95     if (isRemoved()) {
96         es.throwUninformativeAndGenericDOMException(InvalidStateError);
97         return 0;
98     }
99
100     // 2. Return a new static normalized TimeRanges object for the media segments buffered.
101     return m_private->buffered();
102 }
103
104 double SourceBuffer::timestampOffset() const
105 {
106     return m_timestampOffset;
107 }
108
109 void SourceBuffer::setTimestampOffset(double offset, ExceptionState& es)
110 {
111     // Section 3.1 timestampOffset attribute setter steps.
112     // 1. Let new timestamp offset equal the new value being assigned to this attribute.
113     // 2. If this object has been removed from the sourceBuffers attribute of the parent media source, then throw an
114     //    InvalidStateError exception and abort these steps.
115     // 3. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
116     if (isRemoved() || m_updating) {
117         es.throwUninformativeAndGenericDOMException(InvalidStateError);
118         return;
119     }
120
121     // 4. If the readyState attribute of the parent media source is in the "ended" state then run the following steps:
122     // 4.1 Set the readyState attribute of the parent media source to "open"
123     // 4.2 Queue a task to fire a simple event named sourceopen at the parent media source.
124     m_source->openIfInEndedState();
125
126     // 5. If this object is waiting for the end of a media segment to be appended, then throw an InvalidStateError
127     // and abort these steps.
128     //
129     // FIXME: Add step 6 text when mode attribute is implemented.
130     if (!m_private->setTimestampOffset(offset)) {
131         es.throwUninformativeAndGenericDOMException(InvalidStateError);
132         return;
133     }
134
135     // 7. Update the attribute to new timestamp offset.
136     m_timestampOffset = offset;
137 }
138
139 double SourceBuffer::appendWindowStart() const
140 {
141     return m_appendWindowStart;
142 }
143
144 void SourceBuffer::setAppendWindowStart(double start, ExceptionState& es)
145 {
146     // Enforce throwing an exception on restricted double values.
147     if (std::isnan(start)
148         || start == std::numeric_limits<double>::infinity()
149         || start == -std::numeric_limits<double>::infinity()) {
150         es.throwUninformativeAndGenericDOMException(TypeMismatchError);
151         return;
152     }
153
154     // Section 3.1 appendWindowStart attribute setter steps.
155     // 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an
156     //    InvalidStateError exception and abort these steps.
157     // 2. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
158     if (isRemoved() || m_updating) {
159         es.throwUninformativeAndGenericDOMException(InvalidStateError);
160         return;
161     }
162
163     // 3. If the new value is less than 0 or greater than or equal to appendWindowEnd then throw an InvalidAccessError
164     //    exception and abort these steps.
165     if (start < 0 || start >= m_appendWindowEnd) {
166         es.throwUninformativeAndGenericDOMException(InvalidAccessError);
167         return;
168     }
169
170     m_private->setAppendWindowStart(start);
171
172     // 4. Update the attribute to the new value.
173     m_appendWindowStart = start;
174 }
175
176 double SourceBuffer::appendWindowEnd() const
177 {
178     return m_appendWindowEnd;
179 }
180
181 void SourceBuffer::setAppendWindowEnd(double end, ExceptionState& es)
182 {
183     // Section 3.1 appendWindowEnd attribute setter steps.
184     // 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an
185     //    InvalidStateError exception and abort these steps.
186     // 2. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
187     if (isRemoved() || m_updating) {
188         es.throwUninformativeAndGenericDOMException(InvalidStateError);
189         return;
190     }
191
192     // 3. If the new value equals NaN, then throw an InvalidAccessError and abort these steps.
193     // 4. If the new value is less than or equal to appendWindowStart then throw an InvalidAccessError
194     //    exception and abort these steps.
195     if (std::isnan(end) || end <= m_appendWindowStart) {
196         es.throwUninformativeAndGenericDOMException(InvalidAccessError);
197         return;
198     }
199
200     m_private->setAppendWindowEnd(end);
201
202     // 5. Update the attribute to the new value.
203     m_appendWindowEnd = end;
204 }
205
206 void SourceBuffer::appendBuffer(PassRefPtr<ArrayBuffer> data, ExceptionState& es)
207 {
208     // Section 3.2 appendBuffer()
209     // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-appendBuffer-void-ArrayBufferView-data
210     // 1. If data is null then throw an InvalidAccessError exception and abort these steps.
211     if (!data) {
212         es.throwUninformativeAndGenericDOMException(InvalidAccessError);
213         return;
214     }
215
216     appendBufferInternal(static_cast<const unsigned char*>(data->data()), data->byteLength(), es);
217 }
218
219 void SourceBuffer::appendBuffer(PassRefPtr<ArrayBufferView> data, ExceptionState& es)
220 {
221     // Section 3.2 appendBuffer()
222     // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-appendBuffer-void-ArrayBufferView-data
223     // 1. If data is null then throw an InvalidAccessError exception and abort these steps.
224     if (!data) {
225         es.throwUninformativeAndGenericDOMException(InvalidAccessError);
226         return;
227     }
228
229     appendBufferInternal(static_cast<const unsigned char*>(data->baseAddress()), data->byteLength(), es);
230 }
231
232 void SourceBuffer::appendStream(PassRefPtr<Stream> stream, ExceptionState& es)
233 {
234     m_streamMaxSizeValid = false;
235     appendStreamInternal(stream, es);
236 }
237
238 void SourceBuffer::appendStream(PassRefPtr<Stream> stream, unsigned long long maxSize, ExceptionState& es)
239 {
240     m_streamMaxSizeValid = maxSize > 0;
241     if (m_streamMaxSizeValid)
242         m_streamMaxSize = maxSize;
243     appendStreamInternal(stream, es);
244 }
245
246 void SourceBuffer::abort(ExceptionState& es)
247 {
248     // Section 3.2 abort() method steps.
249     // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-abort-void
250     // 1. If this object has been removed from the sourceBuffers attribute of the parent media source
251     //    then throw an InvalidStateError exception and abort these steps.
252     // 2. If the readyState attribute of the parent media source is not in the "open" state
253     //    then throw an InvalidStateError exception and abort these steps.
254     if (isRemoved() || !m_source->isOpen()) {
255         es.throwUninformativeAndGenericDOMException(InvalidStateError);
256         return;
257     }
258
259     // 3. If the sourceBuffer.updating attribute equals true, then run the following steps: ...
260     abortIfUpdating();
261
262     // 4. Run the reset parser state algorithm.
263     m_private->abort();
264
265     // 5. Set appendWindowStart to 0.
266     setAppendWindowStart(0, es);
267
268     // 6. Set appendWindowEnd to positive Infinity.
269     setAppendWindowEnd(std::numeric_limits<double>::infinity(), es);
270 }
271
272 void SourceBuffer::remove(double start, double end, ExceptionState& es)
273 {
274     // Section 3.2 remove() method steps.
275     // 1. If start is negative or greater than duration, then throw an InvalidAccessError exception and abort these steps.
276     // 2. If end is less than or equal to start, then throw an InvalidAccessError exception and abort these steps.
277     if (start < 0 || (m_source && (std::isnan(m_source->duration()) || start > m_source->duration())) || end <= start) {
278         es.throwUninformativeAndGenericDOMException(InvalidAccessError);
279         return;
280     }
281
282     // 3. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an
283     //    InvalidStateError exception and abort these steps.
284     // 4. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
285     if (isRemoved() || m_updating) {
286         es.throwUninformativeAndGenericDOMException(InvalidStateError);
287         return;
288     }
289
290     TRACE_EVENT_ASYNC_BEGIN0("media", "SourceBuffer::remove", this);
291
292     // 5. If the readyState attribute of the parent media source is in the "ended" state then run the following steps:
293     // 5.1. Set the readyState attribute of the parent media source to "open"
294     // 5.2. Queue a task to fire a simple event named sourceopen at the parent media source .
295     m_source->openIfInEndedState();
296
297     // 6. Set the updating attribute to true.
298     m_updating = true;
299
300     // 7. Queue a task to fire a simple event named updatestart at this SourceBuffer object.
301     scheduleEvent(EventTypeNames::updatestart);
302
303     // 8. Return control to the caller and run the rest of the steps asynchronously.
304     m_pendingRemoveStart = start;
305     m_pendingRemoveEnd = end;
306     m_removeAsyncPartRunner.runAsync();
307 }
308
309 void SourceBuffer::abortIfUpdating()
310 {
311     // Section 3.2 abort() method step 3 substeps.
312     // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-abort-void
313
314     if (!m_updating)
315         return;
316
317     const char* traceEventName = 0;
318     if (!m_pendingAppendData.isEmpty()) {
319         traceEventName = "SourceBuffer::appendBuffer";
320     } else if (m_stream) {
321         traceEventName = "SourceBuffer::appendStream";
322     } else if (m_pendingRemoveStart != -1) {
323         traceEventName = "SourceBuffer::remove";
324     } else {
325         ASSERT_NOT_REACHED();
326     }
327
328     // 3.1. Abort the buffer append and stream append loop algorithms if they are running.
329     m_appendBufferAsyncPartRunner.stop();
330     m_pendingAppendData.clear();
331
332     m_removeAsyncPartRunner.stop();
333     m_pendingRemoveStart = -1;
334     m_pendingRemoveEnd = -1;
335
336     m_appendStreamAsyncPartRunner.stop();
337     clearAppendStreamState();
338
339     // 3.2. Set the updating attribute to false.
340     m_updating = false;
341
342     // 3.3. Queue a task to fire a simple event named abort at this SourceBuffer object.
343     scheduleEvent(EventTypeNames::abort);
344
345     // 3.4. Queue a task to fire a simple event named updateend at this SourceBuffer object.
346     scheduleEvent(EventTypeNames::updateend);
347
348     TRACE_EVENT_ASYNC_END0("media", traceEventName, this);
349 }
350
351 void SourceBuffer::removedFromMediaSource()
352 {
353     if (isRemoved())
354         return;
355
356     abortIfUpdating();
357
358     m_private->removedFromMediaSource();
359     m_source = 0;
360     m_asyncEventQueue = 0;
361 }
362
363 bool SourceBuffer::hasPendingActivity() const
364 {
365     return m_source;
366 }
367
368 void SourceBuffer::suspend()
369 {
370     m_appendBufferAsyncPartRunner.suspend();
371     m_removeAsyncPartRunner.suspend();
372     m_appendStreamAsyncPartRunner.suspend();
373 }
374
375 void SourceBuffer::resume()
376 {
377     m_appendBufferAsyncPartRunner.resume();
378     m_removeAsyncPartRunner.resume();
379     m_appendStreamAsyncPartRunner.resume();
380 }
381
382 void SourceBuffer::stop()
383 {
384     m_appendBufferAsyncPartRunner.stop();
385     m_removeAsyncPartRunner.stop();
386     m_appendStreamAsyncPartRunner.stop();
387 }
388
389 ExecutionContext* SourceBuffer::executionContext() const
390 {
391     return ActiveDOMObject::executionContext();
392 }
393
394 const AtomicString& SourceBuffer::interfaceName() const
395 {
396     return EventTargetNames::SourceBuffer;
397 }
398
399 bool SourceBuffer::isRemoved() const
400 {
401     return !m_source;
402 }
403
404 void SourceBuffer::scheduleEvent(const AtomicString& eventName)
405 {
406     ASSERT(m_asyncEventQueue);
407
408     RefPtr<Event> event = Event::create(eventName);
409     event->setTarget(this);
410
411     m_asyncEventQueue->enqueueEvent(event.release());
412 }
413
414 void SourceBuffer::appendBufferInternal(const unsigned char* data, unsigned size, ExceptionState& es)
415 {
416     // Section 3.2 appendBuffer()
417     // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-appendBuffer-void-ArrayBufferView-data
418
419     // Step 1 is enforced by the caller.
420     // 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.
421     // 3. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
422     if (isRemoved() || m_updating) {
423         es.throwUninformativeAndGenericDOMException(InvalidStateError);
424         return;
425     }
426
427     TRACE_EVENT_ASYNC_BEGIN0("media", "SourceBuffer::appendBuffer", this);
428
429     // 4. If the readyState attribute of the parent media source is in the "ended" state then run the following steps: ...
430     m_source->openIfInEndedState();
431
432     // Steps 5-6
433
434     // 7. Add data to the end of the input buffer.
435     m_pendingAppendData.append(data, size);
436
437     // 8. Set the updating attribute to true.
438     m_updating = true;
439
440     // 9. Queue a task to fire a simple event named updatestart at this SourceBuffer object.
441     scheduleEvent(EventTypeNames::updatestart);
442
443     // 10. Asynchronously run the buffer append algorithm.
444     m_appendBufferAsyncPartRunner.runAsync();
445
446     TRACE_EVENT_ASYNC_STEP0("media", "SourceBuffer::appendBuffer", this, "waiting");
447 }
448
449 void SourceBuffer::appendBufferAsyncPart()
450 {
451     ASSERT(m_updating);
452
453     TRACE_EVENT_ASYNC_STEP0("media", "SourceBuffer::appendBuffer", this, "appending");
454
455     // Section 3.5.4 Buffer Append Algorithm
456     // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#sourcebuffer-buffer-append
457
458     // 1. Run the segment parser loop algorithm.
459     // Step 2 doesn't apply since we run Step 1 synchronously here.
460     size_t appendSize = m_pendingAppendData.size();
461     if (!appendSize) {
462         // Resize buffer for 0 byte appends so we always have a valid pointer.
463         // We need to convey all appends, even 0 byte ones to |m_private| so
464         // that it can clear its end of stream state if necessary.
465         m_pendingAppendData.resize(1);
466     }
467     m_private->append(m_pendingAppendData.data(), appendSize);
468
469     // 3. Set the updating attribute to false.
470     m_updating = false;
471     m_pendingAppendData.clear();
472
473     // 4. Queue a task to fire a simple event named update at this SourceBuffer object.
474     scheduleEvent(EventTypeNames::update);
475
476     // 5. Queue a task to fire a simple event named updateend at this SourceBuffer object.
477     scheduleEvent(EventTypeNames::updateend);
478     TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendBuffer", this);
479 }
480
481 void SourceBuffer::removeAsyncPart()
482 {
483     ASSERT(m_updating);
484     ASSERT(m_pendingRemoveStart >= 0);
485     ASSERT(m_pendingRemoveStart < m_pendingRemoveEnd);
486
487     // Section 3.2 remove() method steps
488     // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-remove-void-double-start-double-end
489
490     // 9. Run the coded frame removal algorithm with start and end as the start and end of the removal range.
491     m_private->remove(m_pendingRemoveStart, m_pendingRemoveEnd);
492
493     // 10. Set the updating attribute to false.
494     m_updating = false;
495     m_pendingRemoveStart = -1;
496     m_pendingRemoveEnd = -1;
497
498     // 11. Queue a task to fire a simple event named update at this SourceBuffer object.
499     scheduleEvent(EventTypeNames::update);
500
501     // 12. Queue a task to fire a simple event named updateend at this SourceBuffer object.
502     scheduleEvent(EventTypeNames::updateend);
503 }
504
505 void SourceBuffer::appendStreamInternal(PassRefPtr<Stream> stream, ExceptionState& es)
506 {
507     // Section 3.2 appendStream()
508     // 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
509     // 1. If stream is null then throw an InvalidAccessError exception and abort these steps.
510     if (!stream || stream->isNeutered()) {
511         es.throwUninformativeAndGenericDOMException(InvalidAccessError);
512         return;
513     }
514
515     // 2. Run the prepare append algorithm.
516     //  Section 3.5.4 Prepare Append Algorithm.
517     //  https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#sourcebuffer-prepare-append
518     //  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.
519     //  2. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
520     if (isRemoved() || m_updating) {
521         es.throwUninformativeAndGenericDOMException(InvalidStateError);
522         return;
523     }
524
525     TRACE_EVENT_ASYNC_BEGIN0("media", "SourceBuffer::appendStream", this);
526
527     //  3. If the readyState attribute of the parent media source is in the "ended" state then run the following steps: ...
528     m_source->openIfInEndedState();
529
530     //  Steps 4-5 of the prepare append algorithm are handled by m_private.
531
532     // 3. Set the updating attribute to true.
533     m_updating = true;
534
535     // 4. Queue a task to fire a simple event named updatestart at this SourceBuffer object.
536     scheduleEvent(EventTypeNames::updatestart);
537
538     // 5. Asynchronously run the stream append loop algorithm with stream and maxSize.
539
540     stream->neuter();
541     m_loader = adoptPtr(new FileReaderLoader(FileReaderLoader::ReadByClient, this));
542     m_stream = stream;
543     m_appendStreamAsyncPartRunner.runAsync();
544 }
545
546 void SourceBuffer::appendStreamAsyncPart()
547 {
548     ASSERT(m_updating);
549     ASSERT(m_loader);
550     ASSERT(m_stream);
551
552     // Section 3.5.6 Stream Append Loop
553     // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#sourcebuffer-stream-append-loop
554
555     // 1. If maxSize is set, then let bytesLeft equal maxSize.
556     // 2. Loop Top: If maxSize is set and bytesLeft equals 0, then jump to the loop done step below.
557     if (m_streamMaxSizeValid && !m_streamMaxSize) {
558         appendStreamDone(true);
559         return;
560     }
561
562     // Steps 3-11 are handled by m_loader.
563     // Note: Passing 0 here signals that maxSize was not set. (i.e. Read all the data in the stream).
564     m_loader->start(executionContext(), *m_stream, m_streamMaxSizeValid ? m_streamMaxSize : 0);
565 }
566
567 void SourceBuffer::appendStreamDone(bool success)
568 {
569     ASSERT(m_updating);
570     ASSERT(m_loader);
571     ASSERT(m_stream);
572
573     clearAppendStreamState();
574
575     if (!success) {
576         // Section 3.5.3 Append Error Algorithm
577         // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#sourcebuffer-append-error
578         //
579         // 1. Run the reset parser state algorithm. (Handled by caller)
580         // 2. Set the updating attribute to false.
581         m_updating = false;
582
583         // 3. Queue a task to fire a simple event named error at this SourceBuffer object.
584         scheduleEvent(EventTypeNames::error);
585
586         // 4. Queue a task to fire a simple event named updateend at this SourceBuffer object.
587         scheduleEvent(EventTypeNames::updateend);
588         TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendStream", this);
589         return;
590     }
591
592     // Section 3.5.6 Stream Append Loop
593     // Steps 1-11 are handled by appendStreamAsyncPart(), |m_loader|, and |m_private|.
594     // 12. Loop Done: Set the updating attribute to false.
595     m_updating = false;
596
597     // 13. Queue a task to fire a simple event named update at this SourceBuffer object.
598     scheduleEvent(EventTypeNames::update);
599
600     // 14. Queue a task to fire a simple event named updateend at this SourceBuffer object.
601     scheduleEvent(EventTypeNames::updateend);
602     TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendStream", this);
603 }
604
605 void SourceBuffer::clearAppendStreamState()
606 {
607     m_streamMaxSizeValid = false;
608     m_streamMaxSize = 0;
609     m_loader.clear();
610     m_stream = 0;
611 }
612
613 void SourceBuffer::didStartLoading()
614 {
615     LOG(Media, "SourceBuffer::didStartLoading() %p", this);
616 }
617
618 void SourceBuffer::didReceiveDataForClient(const char* data, unsigned dataLength)
619 {
620     LOG(Media, "SourceBuffer::didReceiveDataForClient(%d) %p", dataLength, this);
621     ASSERT(m_updating);
622     ASSERT(m_loader);
623
624     m_private->append(reinterpret_cast<const unsigned char*>(data), dataLength);
625 }
626
627 void SourceBuffer::didFinishLoading()
628 {
629     LOG(Media, "SourceBuffer::didFinishLoading() %p", this);
630     appendStreamDone(true);
631 }
632
633 void SourceBuffer::didFail(FileError::ErrorCode errorCode)
634 {
635     LOG(Media, "SourceBuffer::didFail(%d) %p", errorCode, this);
636     appendStreamDone(false);
637 }
638
639 } // namespace WebCore