Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Side by Side Diff: Source/modules/mediasource/SourceBuffer.cpp

Issue 1013923002: Fix MSE GC, make it less aggressive, more spec-compliant (Blink CL) (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: CR feedback Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698