Commit d4f88926 authored by cajbir's avatar cajbir
Browse files

Bug 976037 - Implement an eviction algorithm for media source extensions - r=kinetik

--HG--
extra : rebase_source : 9727384f364f88957db822905436c19c4943c019
parent 6dc4d165
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -371,6 +371,14 @@ MediaSource::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
  return MediaSourceBinding::Wrap(aCx, aScope, this);
}

void
MediaSource::NotifyEvicted(double aStart, double aEnd)
{
  // Cycle through all SourceBuffers and tell them to evict data in
  // the given range.
  mSourceBuffers->Evict(aStart, aEnd);
}

NS_IMPL_CYCLE_COLLECTION_INHERITED_2(MediaSource, nsDOMEventTargetHelper,
                                     mSourceBuffers, mActiveSourceBuffers)

+5 −0
Original line number Diff line number Diff line
@@ -85,6 +85,11 @@ public:
    return mDecoder;
  }

  // Called by SourceBuffers to notify this MediaSource that data has
  // been evicted from the buffered data. The start and end times
  // that were evicted are provided.
  void NotifyEvicted(double aStart, double aEnd);

private:
  explicit MediaSource(nsPIDOMWindow* aWindow);

+9 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include "MediaSource.h"
#include "SubBufferDecoder.h"
#include "SourceBufferResource.h"
#include "VideoUtils.h"

#ifdef PR_LOGGING
extern PRLogModuleInfo* gMediaSourceLog;
@@ -238,4 +239,12 @@ MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
  return NS_OK;
}

double
MediaSourceDecoder::GetMediaSourceDuration()
{
  return mMediaSource ?
           mMediaSource->Duration() :
           mDuration / static_cast<double>(USECS_PER_S);
}

} // namespace mozilla
+4 −0
Original line number Diff line number Diff line
@@ -79,6 +79,10 @@ public:
    return mAudioReader;
  }

  // Returns the duration in seconds as provided by the attached MediaSource.
  // If no MediaSource is attached, returns the duration tracked by the decoder.
  double GetMediaSourceDuration();

private:
  dom::MediaSource* mMediaSource;

+66 −0
Original line number Diff line number Diff line
@@ -96,6 +96,23 @@ SubBufferDecoder::GetImageContainer()
  return mParentDecoder->GetImageContainer();
}

int64_t
SubBufferDecoder::ConvertToByteOffset(double aTime)
{
  // Uses a conversion based on (aTime/duration) * length.  For the
  // purposes of eviction this should be adequate since we have the
  // byte threshold as well to ensure data actually gets evicted and
  // we ensure we don't evict before the current playable point.
  double duration = mParentDecoder->GetMediaSourceDuration();
  if (duration <= 0.0 || IsNaN(duration)) {
    return -1;
  }
  int64_t length = GetResource()->GetLength();
  MOZ_ASSERT(length > 0);
  int64_t offset = (aTime / duration) * length;
  return offset;
}

namespace dom {

void
@@ -330,7 +347,56 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
                              mDecoder->GetResource()->GetLength());
  // TODO: Run buffer append algorithm asynchronously (would call StopUpdating()).
  mDecoder->GetResource()->AppendData(aData, aLength);

  // Eviction uses a byte threshold. If the buffer is greater than the
  // number of bytes then data is evicted. The time range for this
  // eviction is reported back to the media source. It will then
  // evict data before that range across all SourceBuffer's it knows
  // about.
  const int evict_threshold = 1000000;
  bool evicted = mDecoder->GetResource()->EvictData(evict_threshold);
  if (evicted) {
    double start = 0.0;
    double end = 0.0;
    GetBufferedStartEndTime(&start, &end);

    // We notify that we've evicted from the time range 0 through to
    // the current start point.
    mMediaSource->NotifyEvicted(0.0, start);
  }
  StopUpdating();

  // Schedule the state machine thread to ensure playback starts
  // if required when data is appended.
  mMediaSource->GetDecoder()->ScheduleStateMachineThread();
}

void
SourceBuffer::GetBufferedStartEndTime(double* aStart, double* aEnd)
{
  nsRefPtr<TimeRanges> ranges = new TimeRanges();
  mDecoder->GetBuffered(ranges);
  ranges->Normalize();
  int length = ranges->Length();
  ErrorResult rv;

  if (aStart) {
    *aStart = length > 0 ? ranges->Start(0, rv) : 0.0;
  }

  if (aEnd) {
    *aEnd = length > 0 ? ranges->End(length - 1, rv) : 0.0;
  }
}

void
SourceBuffer::Evict(double aStart, double aEnd)
{
  // Need to map time to byte offset then evict
  int64_t end = mDecoder->ConvertToByteOffset(aEnd);
  if (end > 0) {
    mDecoder->GetResource()->EvictBefore(end);
  }
}

NS_IMPL_CYCLE_COLLECTION_INHERITED_1(SourceBuffer, nsDOMEventTargetHelper, mMediaSource)
Loading