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

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: Pass currentTime from blink level, instead of using GetMediaTimeCB Created 5 years, 6 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"
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
philipj_slow 2015/07/02 09:48:21 Section numbers tend to change, but they are consi
servolk 2015/07/07 23:01:52 Acknowledged.
523 // 1. If the SourceBuffer has been removed from the sourceBuffers attribute of the parent media source then throw an InvalidStateError exception and abort these steps.
philipj_slow 2015/07/02 09:48:21 This is indented more than (some of) the steps tha
servolk 2015/07/07 23:01:52 Done.
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 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.
philipj_slow 2015/07/02 09:48:21 https://www.w3.org/Bugs/Public/show_bug.cgi?id=288
servolk 2015/07/07 23:01:52 Done.
531 if (m_source->getHTMLMediaElement()->error()) {
532 exceptionState.throwDOMException(InvalidStateError, "Error detected in H TMLMediaElement this SourceBuffer is attached to.");
philipj_slow 2015/07/02 09:48:21 This error message doesn't appear in any test expe
servolk 2015/07/07 23:01:52 Done.
533 TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::prepareAppend", this);
534 return false;
535 }
536
537 // 4. If the readyState attribute of the parent media source is in the "end ed" state then run the following steps:
538 // 1. Set the readyState attribute of the parent media source to "open"
539 // 2. Queue a task to fire a simple event named sourceopen at the parent media source .
philipj_slow 2015/07/02 09:48:21 https://www.w3.org/Bugs/Public/show_bug.cgi?id=288
servolk 2015/07/07 23:01:52 Done.
540 m_source->openIfInEndedState();
541
542 // 5. Run the coded frame eviction algorithm.
543 if (!evictCodedFrames()) {
544 // 6. If the buffer full flag equals true, then throw a QUOTA_EXCEEDED_ ERR exception and abort these steps.
545 exceptionState.throwDOMException(QuotaExceededError, "The SourceBuffer i s full, and cannot free space to append additional buffers.");
546 TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::prepareAppend", this);
547 return false;
548 }
549
550 TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::prepareAppend", this);
551 return true;
552 }
553
554 bool SourceBuffer::evictCodedFrames()
555 {
556 double currentTime = m_source->getHTMLMediaElement()->currentTime();
philipj_slow 2015/07/02 09:48:21 Can m_source or m_source->getHTMLMediaElement() be
servolk 2015/07/07 23:01:52 It shouldn't be null here, since evictCodedFrame i
557 return m_webSourceBuffer->evictCodedFrames(currentTime);
558 }
559
516 void SourceBuffer::appendBufferInternal(const unsigned char* data, unsigned size , ExceptionState& exceptionState) 560 void SourceBuffer::appendBufferInternal(const unsigned char* data, unsigned size , ExceptionState& exceptionState)
517 { 561 {
562 TRACE_EVENT_ASYNC_BEGIN1("media", "SourceBuffer::appendBuffer", this, "size" , size);
518 // Section 3.2 appendBuffer() 563 // 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 564 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-sou rce.html#widl-SourceBuffer-appendBuffer-void-ArrayBufferView-data
520 565
521 // 1. Run the prepare append algorithm. 566 // 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 567 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. 568 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; 569 return;
527 570 }
528 TRACE_EVENT_ASYNC_BEGIN1("media", "SourceBuffer::appendBuffer", this, "size" , size); 571 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 572
535 // 2. Add data to the end of the input buffer. 573 // 2. Add data to the end of the input buffer.
536 ASSERT(data || size == 0); 574 ASSERT(data || size == 0);
537 if (data) 575 if (data)
538 m_pendingAppendData.append(data, size); 576 m_pendingAppendData.append(data, size);
539 m_pendingAppendDataOffset = 0; 577 m_pendingAppendDataOffset = 0;
540 578
541 // 3. Set the updating attribute to true. 579 // 3. Set the updating attribute to true.
542 m_updating = true; 580 m_updating = true;
543 581
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 661
624 // 11. Queue a task to fire a simple event named update at this SourceBuffer object. 662 // 11. Queue a task to fire a simple event named update at this SourceBuffer object.
625 scheduleEvent(EventTypeNames::update); 663 scheduleEvent(EventTypeNames::update);
626 664
627 // 12. Queue a task to fire a simple event named updateend at this SourceBuf fer object. 665 // 12. Queue a task to fire a simple event named updateend at this SourceBuf fer object.
628 scheduleEvent(EventTypeNames::updateend); 666 scheduleEvent(EventTypeNames::updateend);
629 } 667 }
630 668
631 void SourceBuffer::appendStreamInternal(Stream* stream, ExceptionState& exceptio nState) 669 void SourceBuffer::appendStreamInternal(Stream* stream, ExceptionState& exceptio nState)
632 { 670 {
671 TRACE_EVENT_ASYNC_BEGIN0("media", "SourceBuffer::appendStream", this);
672
633 // Section 3.2 appendStream() 673 // 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 674 // 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.) 675 // (0. If the stream has been neutered, then throw an InvalidAccessError exc eption and abort these steps.)
636 if (stream->isNeutered()) { 676 if (stream->isNeutered()) {
637 exceptionState.throwDOMException(InvalidAccessError, "The stream provide d has been neutered."); 677 exceptionState.throwDOMException(InvalidAccessError, "The stream provide d has been neutered.");
678 TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendStream", this);
638 return; 679 return;
639 } 680 }
640 681
641 // 1. Run the prepare append algorithm. 682 // 1. Run the prepare append algorithm.
642 // Section 3.5.4 Prepare Append Algorithm. 683 if (!prepareAppend(exceptionState)) {
643 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-so urce.html#sourcebuffer-prepare-append 684 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; 685 return;
648 686 }
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 687
656 // 2. Set the updating attribute to true. 688 // 2. Set the updating attribute to true.
657 m_updating = true; 689 m_updating = true;
658 690
659 // 3. Queue a task to fire a simple event named updatestart at this SourceBu ffer object. 691 // 3. Queue a task to fire a simple event named updatestart at this SourceBu ffer object.
660 scheduleEvent(EventTypeNames::updatestart); 692 scheduleEvent(EventTypeNames::updatestart);
661 693
662 // 4. Asynchronously run the stream append loop algorithm with stream and ma xSize. 694 // 4. Asynchronously run the stream append loop algorithm with stream and ma xSize.
663
664 stream->neuter(); 695 stream->neuter();
665 m_loader = adoptPtr(new FileReaderLoader(FileReaderLoader::ReadByClient, thi s)); 696 m_loader = adoptPtr(new FileReaderLoader(FileReaderLoader::ReadByClient, thi s));
666 m_stream = stream; 697 m_stream = stream;
667 m_appendStreamAsyncPartRunner.runAsync(); 698 m_appendStreamAsyncPartRunner.runAsync();
668 } 699 }
669 700
670 void SourceBuffer::appendStreamAsyncPart() 701 void SourceBuffer::appendStreamAsyncPart()
671 { 702 {
672 ASSERT(m_updating); 703 ASSERT(m_updating);
673 ASSERT(m_loader); 704 ASSERT(m_loader);
674 ASSERT(m_stream); 705 ASSERT(m_stream);
706 TRACE_EVENT_ASYNC_STEP_INTO0("media", "SourceBuffer::appendStream", this, "a ppendStreamAsyncPart");
675 707
676 // Section 3.5.6 Stream Append Loop 708 // 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 709 // http://w3c.github.io/media-source/#sourcebuffer-stream-append-loop
678 710
679 // 1. If maxSize is set, then let bytesLeft equal maxSize. 711 // 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. 712 // 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) { 713 if (m_streamMaxSizeValid && !m_streamMaxSize) {
682 appendStreamDone(true); 714 appendStreamDone(true);
683 return; 715 return;
684 } 716 }
685 717
686 // Steps 3-11 are handled by m_loader. 718 // 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). 719 // 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); 720 m_loader->start(executionContext(), *m_stream, m_streamMaxSizeValid ? m_stre amMaxSize : 0);
689 } 721 }
690 722
691 void SourceBuffer::appendStreamDone(bool success) 723 void SourceBuffer::appendStreamDone(bool success)
692 { 724 {
693 ASSERT(m_updating); 725 ASSERT(m_updating);
694 ASSERT(m_loader); 726 ASSERT(m_loader);
695 ASSERT(m_stream); 727 ASSERT(m_stream);
696 728
697 clearAppendStreamState(); 729 clearAppendStreamState();
698 730
699 if (!success) { 731 if (!success) {
700 // Section 3.5.3 Append Error Algorithm 732 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); 733 TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendStream", this);
713 return; 734 return;
714 } 735 }
715 736
716 // Section 3.5.6 Stream Append Loop 737 // Section 3.5.6 Stream Append Loop
717 // Steps 1-11 are handled by appendStreamAsyncPart(), |m_loader|, and |m_web SourceBuffer|. 738 // Steps 1-11 are handled by appendStreamAsyncPart(), |m_loader|, and |m_web SourceBuffer|.
739
718 // 12. Loop Done: Set the updating attribute to false. 740 // 12. Loop Done: Set the updating attribute to false.
719 m_updating = false; 741 m_updating = false;
720 742
721 // 13. Queue a task to fire a simple event named update at this SourceBuffer object. 743 // 13. Queue a task to fire a simple event named update at this SourceBuffer object.
722 scheduleEvent(EventTypeNames::update); 744 scheduleEvent(EventTypeNames::update);
723 745
724 // 14. Queue a task to fire a simple event named updateend at this SourceBuf fer object. 746 // 14. Queue a task to fire a simple event named updateend at this SourceBuf fer object.
725 scheduleEvent(EventTypeNames::updateend); 747 scheduleEvent(EventTypeNames::updateend);
726 TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendStream", this); 748 TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendStream", this);
727 } 749 }
728 750
729 void SourceBuffer::clearAppendStreamState() 751 void SourceBuffer::clearAppendStreamState()
730 { 752 {
731 m_streamMaxSizeValid = false; 753 m_streamMaxSizeValid = false;
732 m_streamMaxSize = 0; 754 m_streamMaxSize = 0;
733 m_loader.clear(); 755 m_loader.clear();
734 m_stream = nullptr; 756 m_stream = nullptr;
735 } 757 }
736 758
759 void SourceBuffer::appendError(bool decodeError)
760 {
761 // Section 3.5.3 Append Error Algorithm
762 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-sou rce.html#sourcebuffer-append-error
763 //
764 // 1. Run the reset parser state algorithm. (Handled by caller)
philipj_slow 2015/07/02 09:48:21 Is there anything that can be asserted to check th
servolk 2015/07/07 23:01:52 TBH, initially I just copied this block of code fr
765 // 2. Set the updating attribute to false.
766 m_updating = false;
767
768 // 3. Queue a task to fire a simple event named error at this SourceBuffer o bject.
769 scheduleEvent(EventTypeNames::error);
770
771 // 4. Queue a task to fire a simple event named updateend at this SourceBuff er object.
772 scheduleEvent(EventTypeNames::updateend);
773
774 // 5. If decode error is true, then run the end of stream algorithm with the
775 // error parameter set to "decode".
776 if (decodeError) {
philipj_slow 2015/07/02 09:48:22 Don't need the {} for one line.
servolk 2015/07/07 23:01:52 Done.
777 m_source->endOfStream("decode", ASSERT_NO_EXCEPTION);
778 }
779 }
780
737 void SourceBuffer::didStartLoading() 781 void SourceBuffer::didStartLoading()
738 { 782 {
739 WTF_LOG(Media, "SourceBuffer::didStartLoading() %p", this); 783 WTF_LOG(Media, "SourceBuffer::didStartLoading() %p", this);
740 } 784 }
741 785
742 void SourceBuffer::didReceiveDataForClient(const char* data, unsigned dataLength ) 786 void SourceBuffer::didReceiveDataForClient(const char* data, unsigned dataLength )
743 { 787 {
744 WTF_LOG(Media, "SourceBuffer::didReceiveDataForClient(%d) %p", dataLength, t his); 788 WTF_LOG(Media, "SourceBuffer::didReceiveDataForClient(%d) %p", dataLength, t his);
745 ASSERT(m_updating); 789 ASSERT(m_updating);
746 ASSERT(m_loader); 790 ASSERT(m_loader);
747 m_webSourceBuffer->append(reinterpret_cast<const unsigned char*>(data), data Length, &m_timestampOffset); 791 m_webSourceBuffer->append(reinterpret_cast<const unsigned char*>(data), data Length, &m_timestampOffset);
748 } 792 }
749 793
750 void SourceBuffer::didFinishLoading() 794 void SourceBuffer::didFinishLoading()
751 { 795 {
752 WTF_LOG(Media, "SourceBuffer::didFinishLoading() %p", this); 796 WTF_LOG(Media, "SourceBuffer::didFinishLoading() %p", this);
753 appendStreamDone(true); 797 // Section 3.5.6 Stream Append Loop
798 // Steps 1-9 are handled by appendStreamAsyncPart(), |m_loader|, and |m_webS ourceBuffer|.
799
800 // 10. Run the coded frame eviction algorithm.
801 bool evictCodedFramesResult = evictCodedFrames();
802
803 // (will be done inside appendStreamDone)
804 // 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.
philipj_slow 2015/07/02 09:48:21 This and some other comments is a bit long, if you
servolk 2015/07/07 23:01:52 I was just trying to be consistent with the rest o
philipj_slow 2015/07/08 12:47:43 Looks like different parts of this file use differ
servolk 2015/07/08 19:03:47 Acknowledged.
805 appendStreamDone(evictCodedFramesResult);
754 } 806 }
755 807
756 void SourceBuffer::didFail(FileError::ErrorCode errorCode) 808 void SourceBuffer::didFail(FileError::ErrorCode errorCode)
757 { 809 {
758 WTF_LOG(Media, "SourceBuffer::didFail(%d) %p", errorCode, this); 810 WTF_LOG(Media, "SourceBuffer::didFail(%d) %p", errorCode, this);
759 appendStreamDone(false); 811 appendStreamDone(false);
760 } 812 }
761 813
762 DEFINE_TRACE(SourceBuffer) 814 DEFINE_TRACE(SourceBuffer)
763 { 815 {
764 visitor->trace(m_source); 816 visitor->trace(m_source);
765 visitor->trace(m_stream); 817 visitor->trace(m_stream);
766 visitor->trace(m_trackDefaults); 818 visitor->trace(m_trackDefaults);
767 visitor->trace(m_asyncEventQueue); 819 visitor->trace(m_asyncEventQueue);
768 RefCountedGarbageCollectedEventTargetWithInlineData<SourceBuffer>::trace(vis itor); 820 RefCountedGarbageCollectedEventTargetWithInlineData<SourceBuffer>::trace(vis itor);
769 ActiveDOMObject::trace(visitor); 821 ActiveDOMObject::trace(visitor);
770 } 822 }
771 823
772 } // namespace blink 824 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698