LCOV - code coverage report
Current view: top level - dom/media/mediasource - SourceBuffer.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 325 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 49 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "SourceBuffer.h"
       8             : 
       9             : #include "AsyncEventRunner.h"
      10             : #include "MediaData.h"
      11             : #include "MediaSourceDemuxer.h"
      12             : #include "MediaSourceUtils.h"
      13             : #include "mozilla/ErrorResult.h"
      14             : #include "mozilla/FloatingPoint.h"
      15             : #include "mozilla/Preferences.h"
      16             : #include "mozilla/dom/MediaSourceBinding.h"
      17             : #include "mozilla/dom/TimeRanges.h"
      18             : #include "nsError.h"
      19             : #include "nsIEventTarget.h"
      20             : #include "nsIRunnable.h"
      21             : #include "nsThreadUtils.h"
      22             : #include "mozilla/Logging.h"
      23             : #include <time.h>
      24             : #include "TimeUnits.h"
      25             : 
      26             : // GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
      27             : // GetTickCount() and conflicts with MediaDecoder::GetCurrentTime implementation.
      28             : #ifdef GetCurrentTime
      29             : #undef GetCurrentTime
      30             : #endif
      31             : 
      32             : struct JSContext;
      33             : class JSObject;
      34             : 
      35             : extern mozilla::LogModule* GetMediaSourceLog();
      36             : extern mozilla::LogModule* GetMediaSourceAPILog();
      37             : 
      38             : #define MSE_DEBUG(arg, ...) MOZ_LOG(GetMediaSourceLog(), mozilla::LogLevel::Debug, ("SourceBuffer(%p:%s)::%s: " arg, this, mType.OriginalString().Data(), __func__, ##__VA_ARGS__))
      39             : #define MSE_DEBUGV(arg, ...) MOZ_LOG(GetMediaSourceLog(), mozilla::LogLevel::Verbose, ("SourceBuffer(%p:%s)::%s: " arg, this, mType.OriginalString().Data(), __func__, ##__VA_ARGS__))
      40             : #define MSE_API(arg, ...) MOZ_LOG(GetMediaSourceAPILog(), mozilla::LogLevel::Debug, ("SourceBuffer(%p:%s)::%s: " arg, this, mType.OriginalString().Data(), __func__, ##__VA_ARGS__))
      41             : 
      42             : namespace mozilla {
      43             : 
      44             : using media::TimeUnit;
      45             : typedef SourceBufferAttributes::AppendState AppendState;
      46             : 
      47             : namespace dom {
      48             : 
      49             : void
      50           0 : SourceBuffer::SetMode(SourceBufferAppendMode aMode, ErrorResult& aRv)
      51             : {
      52           0 :   MOZ_ASSERT(NS_IsMainThread());
      53           0 :   MSE_API("SetMode(aMode=%" PRIu32 ")", static_cast<uint32_t>(aMode));
      54           0 :   if (!IsAttached() || mUpdating) {
      55           0 :     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
      56           0 :     return;
      57             :   }
      58           0 :   if (mCurrentAttributes.mGenerateTimestamps &&
      59             :       aMode == SourceBufferAppendMode::Segments) {
      60           0 :     aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
      61           0 :     return;
      62             :   }
      63           0 :   MOZ_ASSERT(mMediaSource->ReadyState() != MediaSourceReadyState::Closed);
      64           0 :   if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
      65           0 :     mMediaSource->SetReadyState(MediaSourceReadyState::Open);
      66             :   }
      67           0 :   if (mCurrentAttributes.GetAppendState() == AppendState::PARSING_MEDIA_SEGMENT){
      68           0 :     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
      69           0 :     return;
      70             :   }
      71             : 
      72           0 :   if (aMode == SourceBufferAppendMode::Sequence) {
      73             :     // Will set GroupStartTimestamp to GroupEndTimestamp.
      74           0 :     mCurrentAttributes.RestartGroupStartTimestamp();
      75             :   }
      76             : 
      77           0 :   mCurrentAttributes.SetAppendMode(aMode);
      78             : }
      79             : 
      80             : void
      81           0 : SourceBuffer::SetTimestampOffset(double aTimestampOffset, ErrorResult& aRv)
      82             : {
      83           0 :   MOZ_ASSERT(NS_IsMainThread());
      84           0 :   MSE_API("SetTimestampOffset(aTimestampOffset=%f)", aTimestampOffset);
      85           0 :   if (!IsAttached() || mUpdating) {
      86           0 :     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
      87           0 :     return;
      88             :   }
      89           0 :   MOZ_ASSERT(mMediaSource->ReadyState() != MediaSourceReadyState::Closed);
      90           0 :   if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
      91           0 :     mMediaSource->SetReadyState(MediaSourceReadyState::Open);
      92             :   }
      93           0 :   if (mCurrentAttributes.GetAppendState() == AppendState::PARSING_MEDIA_SEGMENT){
      94           0 :     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
      95           0 :     return;
      96             :   }
      97           0 :   mCurrentAttributes.SetApparentTimestampOffset(aTimestampOffset);
      98           0 :   if (mCurrentAttributes.GetAppendMode() == SourceBufferAppendMode::Sequence) {
      99           0 :     mCurrentAttributes.SetGroupStartTimestamp(mCurrentAttributes.GetTimestampOffset());
     100             :   }
     101             : }
     102             : 
     103             : TimeRanges*
     104           0 : SourceBuffer::GetBuffered(ErrorResult& aRv)
     105             : {
     106           0 :   MOZ_ASSERT(NS_IsMainThread());
     107             :   // http://w3c.github.io/media-source/index.html#widl-SourceBuffer-buffered
     108             :   // 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.
     109           0 :   if (!IsAttached()) {
     110           0 :     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     111           0 :     return nullptr;
     112             :   }
     113           0 :   bool rangeChanged = true;
     114           0 :   media::TimeIntervals intersection = mTrackBuffersManager->Buffered();
     115           0 :   MSE_DEBUGV("intersection=%s", DumpTimeRanges(intersection).get());
     116           0 :   if (mBuffered) {
     117           0 :     media::TimeIntervals currentValue(mBuffered);
     118           0 :     rangeChanged = (intersection != currentValue);
     119           0 :     MSE_DEBUGV("currentValue=%s", DumpTimeRanges(currentValue).get());
     120             :   }
     121             :   // 5. If intersection ranges does not contain the exact same range information as the current value of this attribute, then update the current value of this attribute to intersection ranges.
     122           0 :   if (rangeChanged) {
     123           0 :     mBuffered = new TimeRanges(ToSupports(this));
     124           0 :     intersection.ToTimeRanges(mBuffered);
     125             :   }
     126             :   // 6. Return the current value of this attribute.
     127           0 :   return mBuffered;
     128             : }
     129             : 
     130             : media::TimeIntervals
     131           0 : SourceBuffer::GetTimeIntervals()
     132             : {
     133           0 :   return mTrackBuffersManager->Buffered();
     134             : }
     135             : 
     136             : void
     137           0 : SourceBuffer::SetAppendWindowStart(double aAppendWindowStart, ErrorResult& aRv)
     138             : {
     139           0 :   MOZ_ASSERT(NS_IsMainThread());
     140           0 :   MSE_API("SetAppendWindowStart(aAppendWindowStart=%f)", aAppendWindowStart);
     141           0 :   if (!IsAttached() || mUpdating) {
     142           0 :     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     143           0 :     return;
     144             :   }
     145           0 :   if (aAppendWindowStart < 0 ||
     146           0 :       aAppendWindowStart >= mCurrentAttributes.GetAppendWindowEnd()) {
     147           0 :     aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
     148           0 :     return;
     149             :   }
     150           0 :   mCurrentAttributes.SetAppendWindowStart(aAppendWindowStart);
     151             : }
     152             : 
     153             : void
     154           0 : SourceBuffer::SetAppendWindowEnd(double aAppendWindowEnd, ErrorResult& aRv)
     155             : {
     156           0 :   MOZ_ASSERT(NS_IsMainThread());
     157           0 :   MSE_API("SetAppendWindowEnd(aAppendWindowEnd=%f)", aAppendWindowEnd);
     158           0 :   if (!IsAttached() || mUpdating) {
     159           0 :     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     160           0 :     return;
     161             :   }
     162           0 :   if (IsNaN(aAppendWindowEnd) ||
     163           0 :       aAppendWindowEnd <= mCurrentAttributes.GetAppendWindowStart()) {
     164           0 :     aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
     165           0 :     return;
     166             :   }
     167           0 :   mCurrentAttributes.SetAppendWindowEnd(aAppendWindowEnd);
     168             : }
     169             : 
     170             : void
     171           0 : SourceBuffer::AppendBuffer(const ArrayBuffer& aData, ErrorResult& aRv)
     172             : {
     173           0 :   MOZ_ASSERT(NS_IsMainThread());
     174           0 :   MSE_API("AppendBuffer(ArrayBuffer)");
     175           0 :   aData.ComputeLengthAndData();
     176           0 :   AppendData(aData.Data(), aData.Length(), aRv);
     177           0 : }
     178             : 
     179             : void
     180           0 : SourceBuffer::AppendBuffer(const ArrayBufferView& aData, ErrorResult& aRv)
     181             : {
     182           0 :   MOZ_ASSERT(NS_IsMainThread());
     183           0 :   MSE_API("AppendBuffer(ArrayBufferView)");
     184           0 :   aData.ComputeLengthAndData();
     185           0 :   AppendData(aData.Data(), aData.Length(), aRv);
     186           0 : }
     187             : 
     188             : void
     189           0 : SourceBuffer::Abort(ErrorResult& aRv)
     190             : {
     191           0 :   MOZ_ASSERT(NS_IsMainThread());
     192           0 :   MSE_API("Abort()");
     193           0 :   if (!IsAttached()) {
     194           0 :     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     195           0 :     return;
     196             :   }
     197           0 :   if (mMediaSource->ReadyState() != MediaSourceReadyState::Open) {
     198           0 :     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     199           0 :     return;
     200             :   }
     201           0 :   if (mPendingRemoval.Exists()) {
     202           0 :     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     203           0 :     return;
     204             :   }
     205           0 :   AbortBufferAppend();
     206           0 :   ResetParserState();
     207           0 :   mCurrentAttributes.SetAppendWindowStart(0);
     208           0 :   mCurrentAttributes.SetAppendWindowEnd(PositiveInfinity<double>());
     209             : }
     210             : 
     211             : void
     212           0 : SourceBuffer::AbortBufferAppend()
     213             : {
     214           0 :   if (mUpdating) {
     215           0 :     mCompletionPromise.DisconnectIfExists();
     216           0 :     if (mPendingAppend.Exists()) {
     217           0 :       mPendingAppend.Disconnect();
     218           0 :       mTrackBuffersManager->AbortAppendData();
     219             :     }
     220           0 :     AbortUpdating();
     221             :   }
     222           0 : }
     223             : 
     224             : void
     225           0 : SourceBuffer::ResetParserState()
     226             : {
     227           0 :   mTrackBuffersManager->ResetParserState(mCurrentAttributes);
     228           0 : }
     229             : 
     230             : void
     231           0 : SourceBuffer::Remove(double aStart, double aEnd, ErrorResult& aRv)
     232             : {
     233           0 :   MOZ_ASSERT(NS_IsMainThread());
     234           0 :   MSE_API("Remove(aStart=%f, aEnd=%f)", aStart, aEnd);
     235           0 :   if (!IsAttached()) {
     236           0 :     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     237           0 :     return;
     238             :   }
     239           0 :   if (mUpdating) {
     240           0 :     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     241           0 :     return;
     242             :   }
     243           0 :   if (IsNaN(mMediaSource->Duration()) ||
     244           0 :       aStart < 0 || aStart > mMediaSource->Duration() ||
     245           0 :       aEnd <= aStart || IsNaN(aEnd)) {
     246           0 :     aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
     247           0 :     return;
     248             :   }
     249           0 :   if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
     250           0 :     mMediaSource->SetReadyState(MediaSourceReadyState::Open);
     251             :   }
     252             : 
     253           0 :   RangeRemoval(aStart, aEnd);
     254             : }
     255             : 
     256             : void
     257           0 : SourceBuffer::RangeRemoval(double aStart, double aEnd)
     258             : {
     259           0 :   StartUpdating();
     260             : 
     261           0 :   RefPtr<SourceBuffer> self = this;
     262           0 :     mTrackBuffersManager->RangeRemoval(TimeUnit::FromSeconds(aStart),
     263             :                                        TimeUnit::FromSeconds(aEnd))
     264           0 :       ->Then(mAbstractMainThread, __func__,
     265           0 :              [self] (bool) {
     266           0 :                self->mPendingRemoval.Complete();
     267           0 :                self->StopUpdating();
     268           0 :              },
     269           0 :              []() { MOZ_ASSERT(false); })
     270           0 :       ->Track(mPendingRemoval);
     271           0 : }
     272             : 
     273             : void
     274           0 : SourceBuffer::Detach()
     275             : {
     276           0 :   MOZ_ASSERT(NS_IsMainThread());
     277           0 :   MSE_DEBUG("Detach");
     278           0 :   if (!mMediaSource) {
     279           0 :     MSE_DEBUG("Already detached");
     280           0 :     return;
     281             :   }
     282           0 :   AbortBufferAppend();
     283           0 :   if (mTrackBuffersManager) {
     284           0 :     mTrackBuffersManager->Detach();
     285           0 :     mMediaSource->GetDecoder()->GetDemuxer()->DetachSourceBuffer(
     286           0 :       mTrackBuffersManager.get());
     287             :   }
     288           0 :   mTrackBuffersManager = nullptr;
     289           0 :   mMediaSource = nullptr;
     290             : }
     291             : 
     292             : void
     293           0 : SourceBuffer::Ended()
     294             : {
     295           0 :   MOZ_ASSERT(NS_IsMainThread());
     296           0 :   MOZ_ASSERT(IsAttached());
     297           0 :   MSE_DEBUG("Ended");
     298           0 :   mTrackBuffersManager->Ended();
     299           0 : }
     300             : 
     301           0 : SourceBuffer::SourceBuffer(MediaSource* aMediaSource,
     302           0 :                            const MediaContainerType& aType)
     303             :   : DOMEventTargetHelper(aMediaSource->GetParentObject())
     304             :   , mMediaSource(aMediaSource)
     305             :   , mAbstractMainThread(aMediaSource->AbstractMainThread())
     306           0 :   , mCurrentAttributes(aType.Type() == MEDIAMIMETYPE("audio/mpeg") ||
     307           0 :                        aType.Type() == MEDIAMIMETYPE("audio/aac"))
     308             :   , mUpdating(false)
     309             :   , mActive(false)
     310           0 :   , mType(aType)
     311             : {
     312           0 :   MOZ_ASSERT(NS_IsMainThread());
     313           0 :   MOZ_ASSERT(aMediaSource);
     314             : 
     315             :   mTrackBuffersManager =
     316           0 :     new TrackBuffersManager(aMediaSource->GetDecoder(), aType);
     317             : 
     318           0 :   MSE_DEBUG("Create mTrackBuffersManager=%p",
     319             :             mTrackBuffersManager.get());
     320             : 
     321           0 :   ErrorResult dummy;
     322           0 :   if (mCurrentAttributes.mGenerateTimestamps) {
     323           0 :     SetMode(SourceBufferAppendMode::Sequence, dummy);
     324             :   } else {
     325           0 :     SetMode(SourceBufferAppendMode::Segments, dummy);
     326             :   }
     327           0 :   mMediaSource->GetDecoder()->GetDemuxer()->AttachSourceBuffer(
     328           0 :     mTrackBuffersManager.get());
     329           0 : }
     330             : 
     331           0 : SourceBuffer::~SourceBuffer()
     332             : {
     333           0 :   MOZ_ASSERT(NS_IsMainThread());
     334           0 :   MOZ_ASSERT(!mMediaSource);
     335           0 :   MSE_DEBUG("");
     336           0 : }
     337             : 
     338             : MediaSource*
     339           0 : SourceBuffer::GetParentObject() const
     340             : {
     341           0 :   return mMediaSource;
     342             : }
     343             : 
     344             : JSObject*
     345           0 : SourceBuffer::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     346             : {
     347           0 :   return SourceBufferBinding::Wrap(aCx, this, aGivenProto);
     348             : }
     349             : 
     350             : void
     351           0 : SourceBuffer::DispatchSimpleEvent(const char* aName)
     352             : {
     353           0 :   MOZ_ASSERT(NS_IsMainThread());
     354           0 :   MSE_API("Dispatch event '%s'", aName);
     355           0 :   DispatchTrustedEvent(NS_ConvertUTF8toUTF16(aName));
     356           0 : }
     357             : 
     358             : void
     359           0 : SourceBuffer::QueueAsyncSimpleEvent(const char* aName)
     360             : {
     361           0 :   MSE_DEBUG("Queuing event '%s'", aName);
     362           0 :   nsCOMPtr<nsIRunnable> event = new AsyncEventRunner<SourceBuffer>(this, aName);
     363           0 :   mAbstractMainThread->Dispatch(event.forget());
     364           0 : }
     365             : 
     366             : void
     367           0 : SourceBuffer::StartUpdating()
     368             : {
     369           0 :   MOZ_ASSERT(NS_IsMainThread());
     370           0 :   MOZ_ASSERT(!mUpdating);
     371           0 :   mUpdating = true;
     372           0 :   QueueAsyncSimpleEvent("updatestart");
     373           0 : }
     374             : 
     375             : void
     376           0 : SourceBuffer::StopUpdating()
     377             : {
     378           0 :   MOZ_ASSERT(NS_IsMainThread());
     379           0 :   if (!mUpdating) {
     380             :     // The buffer append or range removal algorithm  has been interrupted by
     381             :     // abort().
     382           0 :     return;
     383             :   }
     384           0 :   mUpdating = false;
     385           0 :   QueueAsyncSimpleEvent("update");
     386           0 :   QueueAsyncSimpleEvent("updateend");
     387             : }
     388             : 
     389             : void
     390           0 : SourceBuffer::AbortUpdating()
     391             : {
     392           0 :   MOZ_ASSERT(NS_IsMainThread());
     393           0 :   mUpdating = false;
     394           0 :   QueueAsyncSimpleEvent("abort");
     395           0 :   QueueAsyncSimpleEvent("updateend");
     396           0 : }
     397             : 
     398             : void
     399           0 : SourceBuffer::CheckEndTime()
     400             : {
     401           0 :   MOZ_ASSERT(NS_IsMainThread());
     402             :   // Check if we need to update mMediaSource duration
     403           0 :   double endTime = mCurrentAttributes.GetGroupEndTimestamp().ToSeconds();
     404           0 :   double duration = mMediaSource->Duration();
     405           0 :   if (endTime > duration) {
     406           0 :     mMediaSource->SetDuration(endTime);
     407             :   }
     408           0 : }
     409             : 
     410             : void
     411           0 : SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
     412             : {
     413           0 :   MSE_DEBUG("AppendData(aLength=%u)", aLength);
     414             : 
     415           0 :   RefPtr<MediaByteBuffer> data = PrepareAppend(aData, aLength, aRv);
     416           0 :   if (!data) {
     417           0 :     return;
     418             :   }
     419           0 :   StartUpdating();
     420             : 
     421           0 :   mTrackBuffersManager->AppendData(data.forget(), mCurrentAttributes)
     422           0 :     ->Then(mAbstractMainThread, __func__, this,
     423             :            &SourceBuffer::AppendDataCompletedWithSuccess,
     424           0 :            &SourceBuffer::AppendDataErrored)
     425           0 :     ->Track(mPendingAppend);
     426             : }
     427             : 
     428             : void
     429           0 : SourceBuffer::AppendDataCompletedWithSuccess(const SourceBufferTask::AppendBufferResult& aResult)
     430             : {
     431           0 :   MOZ_ASSERT(mUpdating);
     432           0 :   mPendingAppend.Complete();
     433             : 
     434           0 :   if (aResult.first()) {
     435           0 :     if (!mActive) {
     436           0 :       mActive = true;
     437           0 :       MSE_DEBUG("Init segment received");
     438           0 :       RefPtr<SourceBuffer> self = this;
     439           0 :       mMediaSource->SourceBufferIsActive(this)
     440           0 :         ->Then(mAbstractMainThread, __func__,
     441           0 :                [self, this]() {
     442           0 :                  MSE_DEBUG("Complete AppendBuffer operation");
     443           0 :                  mCompletionPromise.Complete();
     444           0 :                  StopUpdating();
     445           0 :                })
     446           0 :         ->Track(mCompletionPromise);
     447             :     }
     448             :   }
     449           0 :   if (mActive) {
     450             :     // Tell our parent decoder that we have received new data
     451             :     // and send progress event.
     452           0 :     mMediaSource->GetDecoder()->NotifyDataArrived();
     453             :   }
     454             : 
     455           0 :   mCurrentAttributes = aResult.second();
     456             : 
     457           0 :   CheckEndTime();
     458             : 
     459           0 :   if (!mCompletionPromise.Exists()) {
     460           0 :     StopUpdating();
     461             :   }
     462           0 : }
     463             : 
     464             : void
     465           0 : SourceBuffer::AppendDataErrored(const MediaResult& aError)
     466             : {
     467           0 :   MOZ_ASSERT(mUpdating);
     468           0 :   mPendingAppend.Complete();
     469             : 
     470           0 :   switch (aError.Code()) {
     471             :     case NS_ERROR_DOM_MEDIA_CANCELED:
     472             :       // Nothing further to do as the trackbuffer has been shutdown.
     473             :       // or append was aborted and abort() has handled all the events.
     474           0 :       break;
     475             :     default:
     476           0 :       AppendError(aError);
     477           0 :       break;
     478             :   }
     479           0 : }
     480             : 
     481             : void
     482           0 : SourceBuffer::AppendError(const MediaResult& aDecodeError)
     483             : {
     484           0 :   MOZ_ASSERT(NS_IsMainThread());
     485             : 
     486           0 :   ResetParserState();
     487             : 
     488           0 :   mUpdating = false;
     489             : 
     490           0 :   QueueAsyncSimpleEvent("error");
     491           0 :   QueueAsyncSimpleEvent("updateend");
     492             : 
     493           0 :   MOZ_ASSERT(NS_FAILED(aDecodeError));
     494             : 
     495           0 :   mMediaSource->EndOfStream(aDecodeError);
     496           0 : }
     497             : 
     498             : already_AddRefed<MediaByteBuffer>
     499           0 : SourceBuffer::PrepareAppend(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
     500             : {
     501             :   typedef TrackBuffersManager::EvictDataResult Result;
     502             : 
     503           0 :   if (!IsAttached() || mUpdating) {
     504           0 :     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     505           0 :     return nullptr;
     506             :   }
     507             : 
     508             :   // If the HTMLMediaElement.error attribute is not null, then throw an
     509             :   // InvalidStateError exception and abort these steps.
     510           0 :   if (!mMediaSource->GetDecoder() ||
     511           0 :       mMediaSource->GetDecoder()->OwnerHasError()) {
     512           0 :     MSE_DEBUG("HTMLMediaElement.error is not null");
     513           0 :     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     514           0 :     return nullptr;
     515             :   }
     516             : 
     517           0 :   if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
     518           0 :     mMediaSource->SetReadyState(MediaSourceReadyState::Open);
     519             :   }
     520             : 
     521             :   // Eviction uses a byte threshold. If the buffer is greater than the
     522             :   // number of bytes then data is evicted.
     523             :   // TODO: Drive evictions off memory pressure notifications.
     524             :   // TODO: Consider a global eviction threshold  rather than per TrackBuffer.
     525             :   // Give a chance to the TrackBuffersManager to evict some data if needed.
     526             :   Result evicted =
     527           0 :     mTrackBuffersManager->EvictData(TimeUnit::FromSeconds(mMediaSource->GetDecoder()->GetCurrentTime()),
     528           0 :                                     aLength);
     529             : 
     530             :   // See if we have enough free space to append our new data.
     531           0 :   if (evicted == Result::BUFFER_FULL) {
     532           0 :     aRv.Throw(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR);
     533           0 :     return nullptr;
     534             :   }
     535             : 
     536           0 :   RefPtr<MediaByteBuffer> data = new MediaByteBuffer();
     537           0 :   if (!data->AppendElements(aData, aLength, fallible)) {
     538           0 :     aRv.Throw(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR);
     539           0 :     return nullptr;
     540             :   }
     541           0 :   return data.forget();
     542             : }
     543             : 
     544             : double
     545           0 : SourceBuffer::GetBufferedStart()
     546             : {
     547           0 :   MOZ_ASSERT(NS_IsMainThread());
     548           0 :   ErrorResult dummy;
     549           0 :   RefPtr<TimeRanges> ranges = GetBuffered(dummy);
     550           0 :   return ranges->Length() > 0 ? ranges->GetStartTime() : 0;
     551             : }
     552             : 
     553             : double
     554           0 : SourceBuffer::GetBufferedEnd()
     555             : {
     556           0 :   MOZ_ASSERT(NS_IsMainThread());
     557           0 :   ErrorResult dummy;
     558           0 :   RefPtr<TimeRanges> ranges = GetBuffered(dummy);
     559           0 :   return ranges->Length() > 0 ? ranges->GetEndTime() : 0;
     560             : }
     561             : 
     562             : double
     563           0 : SourceBuffer::HighestStartTime()
     564             : {
     565           0 :   MOZ_ASSERT(NS_IsMainThread());
     566             :   return mTrackBuffersManager
     567           0 :          ? mTrackBuffersManager->HighestStartTime().ToSeconds()
     568           0 :          : 0.0;
     569             : }
     570             : 
     571             : double
     572           0 : SourceBuffer::HighestEndTime()
     573             : {
     574           0 :   MOZ_ASSERT(NS_IsMainThread());
     575             :   return mTrackBuffersManager
     576           0 :          ? mTrackBuffersManager->HighestEndTime().ToSeconds()
     577           0 :          : 0.0;
     578             : }
     579             : 
     580             : NS_IMPL_CYCLE_COLLECTION_CLASS(SourceBuffer)
     581             : 
     582           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(SourceBuffer)
     583             :   // Tell the TrackBuffer to end its current SourceBufferResource.
     584           0 :   TrackBuffersManager* manager = tmp->mTrackBuffersManager;
     585           0 :   if (manager) {
     586           0 :     manager->Detach();
     587             :   }
     588           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMediaSource)
     589           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mBuffered)
     590           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(DOMEventTargetHelper)
     591             : 
     592           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SourceBuffer,
     593             :                                                   DOMEventTargetHelper)
     594           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaSource)
     595           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBuffered)
     596           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     597             : 
     598           0 : NS_IMPL_ADDREF_INHERITED(SourceBuffer, DOMEventTargetHelper)
     599           0 : NS_IMPL_RELEASE_INHERITED(SourceBuffer, DOMEventTargetHelper)
     600             : 
     601           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(SourceBuffer)
     602           0 : NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
     603             : 
     604             : #undef MSE_DEBUG
     605             : #undef MSE_DEBUGV
     606             : #undef MSE_API
     607             : 
     608             : } // namespace dom
     609             : 
     610             : } // namespace mozilla

Generated by: LCOV version 1.13