OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 22 matching lines...) Expand all Loading... | |
33 | 33 |
34 #include "bindings/core/v8/ExceptionMessages.h" | 34 #include "bindings/core/v8/ExceptionMessages.h" |
35 #include "bindings/core/v8/ExceptionState.h" | 35 #include "bindings/core/v8/ExceptionState.h" |
36 #include "core/dom/DOMArrayBuffer.h" | 36 #include "core/dom/DOMArrayBuffer.h" |
37 #include "core/dom/DOMArrayBufferView.h" | 37 #include "core/dom/DOMArrayBufferView.h" |
38 #include "core/dom/ExceptionCode.h" | 38 #include "core/dom/ExceptionCode.h" |
39 #include "core/dom/ExecutionContext.h" | 39 #include "core/dom/ExecutionContext.h" |
40 #include "core/events/Event.h" | 40 #include "core/events/Event.h" |
41 #include "core/events/GenericEventQueue.h" | 41 #include "core/events/GenericEventQueue.h" |
42 #include "core/fileapi/FileReaderLoader.h" | 42 #include "core/fileapi/FileReaderLoader.h" |
43 #include "core/html/HTMLMediaElement.h" | |
44 #include "core/html/MediaError.h" | |
philipj_slow
2015/07/08 12:47:44
Is this include needed, or is it enough to forward
servolk
2015/07/08 19:03:48
This is needed, we can't get away with just a forw
philipj_slow
2015/07/09 09:49:23
Acknowledged.
| |
43 #include "core/html/TimeRanges.h" | 45 #include "core/html/TimeRanges.h" |
44 #include "core/streams/Stream.h" | 46 #include "core/streams/Stream.h" |
45 #include "modules/mediasource/MediaSource.h" | 47 #include "modules/mediasource/MediaSource.h" |
46 #include "platform/Logging.h" | 48 #include "platform/Logging.h" |
47 #include "platform/TraceEvent.h" | 49 #include "platform/TraceEvent.h" |
48 #include "public/platform/WebSourceBuffer.h" | 50 #include "public/platform/WebSourceBuffer.h" |
49 #include "wtf/MathExtras.h" | 51 #include "wtf/MathExtras.h" |
50 | 52 |
51 #include <limits> | 53 #include <limits> |
52 | 54 |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
506 void SourceBuffer::scheduleEvent(const AtomicString& eventName) | 508 void SourceBuffer::scheduleEvent(const AtomicString& eventName) |
507 { | 509 { |
508 ASSERT(m_asyncEventQueue); | 510 ASSERT(m_asyncEventQueue); |
509 | 511 |
510 RefPtrWillBeRawPtr<Event> event = Event::create(eventName); | 512 RefPtrWillBeRawPtr<Event> event = Event::create(eventName); |
511 event->setTarget(this); | 513 event->setTarget(this); |
512 | 514 |
513 m_asyncEventQueue->enqueueEvent(event.release()); | 515 m_asyncEventQueue->enqueueEvent(event.release()); |
514 } | 516 } |
515 | 517 |
518 bool SourceBuffer::prepareAppend(ExceptionState& exceptionState) | |
519 { | |
520 TRACE_EVENT_ASYNC_BEGIN0("media", "SourceBuffer::prepareAppend", this); | |
521 // http://w3c.github.io/media-source/#sourcebuffer-prepare-append | |
522 // 3.5.4 Prepare Append Algorithm | |
523 // 1. If the SourceBuffer has been removed from the sourceBuffers attribute of the parent media source then throw an InvalidStateError exception and abort t hese steps. | |
524 // 2. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps. | |
525 if (throwExceptionIfRemovedOrUpdating(isRemoved(), m_updating, exceptionStat e)) { | |
526 TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::prepareAppend", this); | |
527 return false; | |
528 } | |
529 | |
530 // 3. If the HTMLMediaElement.error attribute is not null, then throw an Inv alidStateError exception and abort these steps. | |
531 ASSERT(m_source); | |
532 ASSERT(m_source->mediaElement()); | |
533 if (m_source->mediaElement()->error()) { | |
534 exceptionState.throwDOMException(InvalidStateError, "The HTMLMediaElemen t.error attribute is not null."); | |
535 TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::prepareAppend", this); | |
536 return false; | |
537 } | |
538 | |
539 // 4. If the readyState attribute of the parent media source is in the "ende d" state then run the following steps: | |
540 // 1. Set the readyState attribute of the parent media source to "open" | |
541 // 2. Queue a task to fire a simple event named sourceopen at the parent media source. | |
542 m_source->openIfInEndedState(); | |
543 | |
544 // 5. Run the coded frame eviction algorithm. | |
545 if (!evictCodedFrames()) { | |
546 // 6. If the buffer full flag equals true, then throw a QUOTA_EXCEEDED_E RR exception and abort these steps. | |
547 exceptionState.throwDOMException(QuotaExceededError, "The SourceBuffer i s full, and cannot free space to append additional buffers."); | |
548 TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::prepareAppend", this); | |
549 return false; | |
550 } | |
551 | |
552 TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::prepareAppend", this); | |
553 return true; | |
554 } | |
555 | |
556 bool SourceBuffer::evictCodedFrames() | |
557 { | |
558 ASSERT(m_source); | |
559 ASSERT(m_source->mediaElement()); | |
560 double currentTime = m_source->mediaElement()->currentTime(); | |
561 return m_webSourceBuffer->evictCodedFrames(currentTime); | |
562 } | |
563 | |
516 void SourceBuffer::appendBufferInternal(const unsigned char* data, unsigned size , ExceptionState& exceptionState) | 564 void SourceBuffer::appendBufferInternal(const unsigned char* data, unsigned size , ExceptionState& exceptionState) |
517 { | 565 { |
566 TRACE_EVENT_ASYNC_BEGIN1("media", "SourceBuffer::appendBuffer", this, "size" , size); | |
518 // Section 3.2 appendBuffer() | 567 // Section 3.2 appendBuffer() |
519 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-sou rce.html#widl-SourceBuffer-appendBuffer-void-ArrayBufferView-data | 568 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-sou rce.html#widl-SourceBuffer-appendBuffer-void-ArrayBufferView-data |
520 | 569 |
521 // 1. Run the prepare append algorithm. | 570 // 1. Run the prepare append algorithm. |
522 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-sou rce.html#sourcebuffer-prepare-append | 571 if (!prepareAppend(exceptionState)) { |
523 // 1. If this object has been removed from the sourceBuffers attribute of t he parent media source then throw an InvalidStateError exception and abort these steps. | 572 TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendBuffer", this); |
524 // 2. If the updating attribute equals true, then throw an InvalidStateErro r exception and abort these steps. | |
525 if (throwExceptionIfRemovedOrUpdating(isRemoved(), m_updating, exceptionStat e)) | |
526 return; | 573 return; |
527 | 574 } |
528 TRACE_EVENT_ASYNC_BEGIN1("media", "SourceBuffer::appendBuffer", this, "size" , size); | 575 TRACE_EVENT_ASYNC_STEP_INTO0("media", "SourceBuffer::appendBuffer", this, "p repareAppend"); |
529 | |
530 // 3. If the readyState attribute of the parent media source is in the "end ed" state then run the following steps: ... | |
531 m_source->openIfInEndedState(); | |
532 | |
533 // Steps 4-5 - end "prepare append" algorithm. | |
534 | 576 |
535 // 2. Add data to the end of the input buffer. | 577 // 2. Add data to the end of the input buffer. |
536 ASSERT(data || size == 0); | 578 ASSERT(data || size == 0); |
537 if (data) | 579 if (data) |
538 m_pendingAppendData.append(data, size); | 580 m_pendingAppendData.append(data, size); |
539 m_pendingAppendDataOffset = 0; | 581 m_pendingAppendDataOffset = 0; |
540 | 582 |
541 // 3. Set the updating attribute to true. | 583 // 3. Set the updating attribute to true. |
542 m_updating = true; | 584 m_updating = true; |
543 | 585 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
623 | 665 |
624 // 11. Queue a task to fire a simple event named update at this SourceBuffer object. | 666 // 11. Queue a task to fire a simple event named update at this SourceBuffer object. |
625 scheduleEvent(EventTypeNames::update); | 667 scheduleEvent(EventTypeNames::update); |
626 | 668 |
627 // 12. Queue a task to fire a simple event named updateend at this SourceBuf fer object. | 669 // 12. Queue a task to fire a simple event named updateend at this SourceBuf fer object. |
628 scheduleEvent(EventTypeNames::updateend); | 670 scheduleEvent(EventTypeNames::updateend); |
629 } | 671 } |
630 | 672 |
631 void SourceBuffer::appendStreamInternal(Stream* stream, ExceptionState& exceptio nState) | 673 void SourceBuffer::appendStreamInternal(Stream* stream, ExceptionState& exceptio nState) |
632 { | 674 { |
675 TRACE_EVENT_ASYNC_BEGIN0("media", "SourceBuffer::appendStream", this); | |
676 | |
633 // Section 3.2 appendStream() | 677 // Section 3.2 appendStream() |
634 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-sou rce.html#widl-SourceBuffer-appendStream-void-Stream-stream-unsigned-long-long-ma xSize | 678 // http://w3c.github.io/media-source/#widl-SourceBuffer-appendStream-void-Re adableStream-stream-unsigned-long-long-maxSize |
635 // (0. If the stream has been neutered, then throw an InvalidAccessError exc eption and abort these steps.) | 679 // (0. If the stream has been neutered, then throw an InvalidAccessError exc eption and abort these steps.) |
636 if (stream->isNeutered()) { | 680 if (stream->isNeutered()) { |
637 exceptionState.throwDOMException(InvalidAccessError, "The stream provide d has been neutered."); | 681 exceptionState.throwDOMException(InvalidAccessError, "The stream provide d has been neutered."); |
682 TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendStream", this); | |
638 return; | 683 return; |
639 } | 684 } |
640 | 685 |
641 // 1. Run the prepare append algorithm. | 686 // 1. Run the prepare append algorithm. |
642 // Section 3.5.4 Prepare Append Algorithm. | 687 if (!prepareAppend(exceptionState)) { |
643 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-so urce.html#sourcebuffer-prepare-append | 688 TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendStream", this); |
644 // 1. If this object has been removed from the sourceBuffers attribute of t he parent media source then throw an InvalidStateError exception and abort these steps. | |
645 // 2. If the updating attribute equals true, then throw an InvalidStateErro r exception and abort these steps. | |
646 if (throwExceptionIfRemovedOrUpdating(isRemoved(), m_updating, exceptionStat e)) | |
647 return; | 689 return; |
648 | 690 } |
649 TRACE_EVENT_ASYNC_BEGIN0("media", "SourceBuffer::appendStream", this); | |
650 | |
651 // 3. If the readyState attribute of the parent media source is in the "end ed" state then run the following steps: ... | |
652 m_source->openIfInEndedState(); | |
653 | |
654 // Steps 4-5 of the prepare append algorithm are handled by m_webSourceBuffe r. | |
655 | 691 |
656 // 2. Set the updating attribute to true. | 692 // 2. Set the updating attribute to true. |
657 m_updating = true; | 693 m_updating = true; |
658 | 694 |
659 // 3. Queue a task to fire a simple event named updatestart at this SourceBu ffer object. | 695 // 3. Queue a task to fire a simple event named updatestart at this SourceBu ffer object. |
660 scheduleEvent(EventTypeNames::updatestart); | 696 scheduleEvent(EventTypeNames::updatestart); |
661 | 697 |
662 // 4. Asynchronously run the stream append loop algorithm with stream and ma xSize. | 698 // 4. Asynchronously run the stream append loop algorithm with stream and ma xSize. |
663 | |
664 stream->neuter(); | 699 stream->neuter(); |
665 m_loader = FileReaderLoader::create(FileReaderLoader::ReadByClient, this); | 700 m_loader = FileReaderLoader::create(FileReaderLoader::ReadByClient, this); |
666 m_stream = stream; | 701 m_stream = stream; |
667 m_appendStreamAsyncPartRunner.runAsync(); | 702 m_appendStreamAsyncPartRunner.runAsync(); |
668 } | 703 } |
669 | 704 |
670 void SourceBuffer::appendStreamAsyncPart() | 705 void SourceBuffer::appendStreamAsyncPart() |
671 { | 706 { |
672 ASSERT(m_updating); | 707 ASSERT(m_updating); |
673 ASSERT(m_loader); | 708 ASSERT(m_loader); |
674 ASSERT(m_stream); | 709 ASSERT(m_stream); |
710 TRACE_EVENT_ASYNC_STEP_INTO0("media", "SourceBuffer::appendStream", this, "a ppendStreamAsyncPart"); | |
675 | 711 |
676 // Section 3.5.6 Stream Append Loop | 712 // Section 3.5.6 Stream Append Loop |
677 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-sou rce.html#sourcebuffer-stream-append-loop | 713 // http://w3c.github.io/media-source/#sourcebuffer-stream-append-loop |
678 | 714 |
679 // 1. If maxSize is set, then let bytesLeft equal maxSize. | 715 // 1. If maxSize is set, then let bytesLeft equal maxSize. |
680 // 2. Loop Top: If maxSize is set and bytesLeft equals 0, then jump to the l oop done step below. | 716 // 2. Loop Top: If maxSize is set and bytesLeft equals 0, then jump to the l oop done step below. |
681 if (m_streamMaxSizeValid && !m_streamMaxSize) { | 717 if (m_streamMaxSizeValid && !m_streamMaxSize) { |
682 appendStreamDone(true); | 718 appendStreamDone(true); |
683 return; | 719 return; |
684 } | 720 } |
685 | 721 |
686 // Steps 3-11 are handled by m_loader. | 722 // Steps 3-11 are handled by m_loader. |
687 // Note: Passing 0 here signals that maxSize was not set. (i.e. Read all the data in the stream). | 723 // Note: Passing 0 here signals that maxSize was not set. (i.e. Read all the data in the stream). |
688 m_loader->start(executionContext(), *m_stream, m_streamMaxSizeValid ? m_stre amMaxSize : 0); | 724 m_loader->start(executionContext(), *m_stream, m_streamMaxSizeValid ? m_stre amMaxSize : 0); |
689 } | 725 } |
690 | 726 |
691 void SourceBuffer::appendStreamDone(bool success) | 727 void SourceBuffer::appendStreamDone(bool success) |
692 { | 728 { |
693 ASSERT(m_updating); | 729 ASSERT(m_updating); |
694 ASSERT(m_loader); | 730 ASSERT(m_loader); |
695 ASSERT(m_stream); | 731 ASSERT(m_stream); |
696 | 732 |
697 clearAppendStreamState(); | 733 clearAppendStreamState(); |
698 | 734 |
699 if (!success) { | 735 if (!success) { |
700 // Section 3.5.3 Append Error Algorithm | 736 appendError(false); |
701 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media -source.html#sourcebuffer-append-error | |
702 // | |
703 // 1. Run the reset parser state algorithm. (Handled by caller) | |
704 // 2. Set the updating attribute to false. | |
705 m_updating = false; | |
706 | |
707 // 3. Queue a task to fire a simple event named error at this SourceBuff er object. | |
708 scheduleEvent(EventTypeNames::error); | |
709 | |
710 // 4. Queue a task to fire a simple event named updateend at this Source Buffer object. | |
711 scheduleEvent(EventTypeNames::updateend); | |
712 TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendStream", this); | 737 TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendStream", this); |
713 return; | 738 return; |
714 } | 739 } |
715 | 740 |
716 // Section 3.5.6 Stream Append Loop | 741 // Section 3.5.6 Stream Append Loop |
717 // Steps 1-11 are handled by appendStreamAsyncPart(), |m_loader|, and |m_web SourceBuffer|. | 742 // Steps 1-11 are handled by appendStreamAsyncPart(), |m_loader|, and |m_web SourceBuffer|. |
743 | |
718 // 12. Loop Done: Set the updating attribute to false. | 744 // 12. Loop Done: Set the updating attribute to false. |
719 m_updating = false; | 745 m_updating = false; |
720 | 746 |
721 // 13. Queue a task to fire a simple event named update at this SourceBuffer object. | 747 // 13. Queue a task to fire a simple event named update at this SourceBuffer object. |
722 scheduleEvent(EventTypeNames::update); | 748 scheduleEvent(EventTypeNames::update); |
723 | 749 |
724 // 14. Queue a task to fire a simple event named updateend at this SourceBuf fer object. | 750 // 14. Queue a task to fire a simple event named updateend at this SourceBuf fer object. |
725 scheduleEvent(EventTypeNames::updateend); | 751 scheduleEvent(EventTypeNames::updateend); |
726 TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendStream", this); | 752 TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendStream", this); |
727 } | 753 } |
728 | 754 |
729 void SourceBuffer::clearAppendStreamState() | 755 void SourceBuffer::clearAppendStreamState() |
730 { | 756 { |
731 m_streamMaxSizeValid = false; | 757 m_streamMaxSizeValid = false; |
732 m_streamMaxSize = 0; | 758 m_streamMaxSize = 0; |
733 m_loader.clear(); | 759 m_loader.clear(); |
734 m_stream = nullptr; | 760 m_stream = nullptr; |
735 } | 761 } |
736 | 762 |
763 void SourceBuffer::appendError(bool decodeError) | |
764 { | |
765 // Section 3.5.3 Append Error Algorithm | |
766 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-sou rce.html#sourcebuffer-append-error | |
767 // | |
philipj_slow
2015/07/08 12:47:44
Blank line instead?
servolk
2015/07/08 19:03:47
Done.
| |
768 // 1. Run the reset parser state algorithm. | |
769 m_webSourceBuffer->abort(); | |
philipj_slow
2015/07/08 12:47:44
The web-facing SourceBuffer.abort() does more than
servolk
2015/07/08 19:03:47
Yes, this is a bit confusing. Note that I'm not ca
philipj_slow
2015/07/09 09:49:23
Understood. Do you think resetParserState() would
servolk
2015/07/10 01:11:28
Yes, I think it might a good idea to rename the cu
wolenetz
2015/08/12 22:42:03
Rename to resetParserState of WebSourceBuffer::abo
servolk
2015/08/21 02:51:25
Ok, I think renaming WebSourceBuffer::abort into r
| |
770 | |
771 // 2. Set the updating attribute to false. | |
772 m_updating = false; | |
773 | |
774 // 3. Queue a task to fire a simple event named error at this SourceBuffer o bject. | |
775 scheduleEvent(EventTypeNames::error); | |
776 | |
777 // 4. Queue a task to fire a simple event named updateend at this SourceBuff er object. | |
778 scheduleEvent(EventTypeNames::updateend); | |
779 | |
780 // 5. If decode error is true, then run the end of stream algorithm with the | |
781 // error parameter set to "decode". | |
782 if (decodeError) | |
783 m_source->endOfStream("decode", ASSERT_NO_EXCEPTION); | |
784 } | |
785 | |
737 void SourceBuffer::didStartLoading() | 786 void SourceBuffer::didStartLoading() |
738 { | 787 { |
739 WTF_LOG(Media, "SourceBuffer::didStartLoading() %p", this); | 788 WTF_LOG(Media, "SourceBuffer::didStartLoading() %p", this); |
740 } | 789 } |
741 | 790 |
742 void SourceBuffer::didReceiveDataForClient(const char* data, unsigned dataLength ) | 791 void SourceBuffer::didReceiveDataForClient(const char* data, unsigned dataLength ) |
743 { | 792 { |
744 WTF_LOG(Media, "SourceBuffer::didReceiveDataForClient(%d) %p", dataLength, t his); | 793 WTF_LOG(Media, "SourceBuffer::didReceiveDataForClient(%d) %p", dataLength, t his); |
745 ASSERT(m_updating); | 794 ASSERT(m_updating); |
746 ASSERT(m_loader); | 795 ASSERT(m_loader); |
747 m_webSourceBuffer->append(reinterpret_cast<const unsigned char*>(data), data Length, &m_timestampOffset); | 796 m_webSourceBuffer->append(reinterpret_cast<const unsigned char*>(data), data Length, &m_timestampOffset); |
748 } | 797 } |
749 | 798 |
750 void SourceBuffer::didFinishLoading() | 799 void SourceBuffer::didFinishLoading() |
751 { | 800 { |
752 WTF_LOG(Media, "SourceBuffer::didFinishLoading() %p", this); | 801 WTF_LOG(Media, "SourceBuffer::didFinishLoading() %p", this); |
753 appendStreamDone(true); | 802 // Section 3.5.6 Stream Append Loop |
803 // Steps 1-9 are handled by appendStreamAsyncPart(), |m_loader|, and |m_webS ourceBuffer|. | |
804 | |
805 // 10. Run the coded frame eviction algorithm. | |
806 bool evictCodedFramesResult = evictCodedFrames(); | |
807 | |
808 // (will be done inside appendStreamDone) | |
809 // 11. If the buffer full flag equals true, then run the append error algori thm with the decode error parameter set to false and abort this algorithm. | |
810 appendStreamDone(evictCodedFramesResult); | |
754 } | 811 } |
755 | 812 |
756 void SourceBuffer::didFail(FileError::ErrorCode errorCode) | 813 void SourceBuffer::didFail(FileError::ErrorCode errorCode) |
757 { | 814 { |
758 WTF_LOG(Media, "SourceBuffer::didFail(%d) %p", errorCode, this); | 815 WTF_LOG(Media, "SourceBuffer::didFail(%d) %p", errorCode, this); |
759 appendStreamDone(false); | 816 appendStreamDone(false); |
760 } | 817 } |
761 | 818 |
762 DEFINE_TRACE(SourceBuffer) | 819 DEFINE_TRACE(SourceBuffer) |
763 { | 820 { |
764 visitor->trace(m_source); | 821 visitor->trace(m_source); |
765 visitor->trace(m_stream); | 822 visitor->trace(m_stream); |
766 visitor->trace(m_trackDefaults); | 823 visitor->trace(m_trackDefaults); |
767 visitor->trace(m_asyncEventQueue); | 824 visitor->trace(m_asyncEventQueue); |
768 RefCountedGarbageCollectedEventTargetWithInlineData<SourceBuffer>::trace(vis itor); | 825 RefCountedGarbageCollectedEventTargetWithInlineData<SourceBuffer>::trace(vis itor); |
769 ActiveDOMObject::trace(visitor); | 826 ActiveDOMObject::trace(visitor); |
770 } | 827 } |
771 | 828 |
772 } // namespace blink | 829 } // namespace blink |
OLD | NEW |