bool
MediaSourceDecoder::CanPlayThrough()
{
  MOZ_ASSERT(NS_IsMainThread());

  if (NextFrameBufferedStatus() == MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE) {
    return false;
  }

  if (IsNaN(mMediaSource->Duration())) {
    // Don't have any data yet.
    return false;
  }
  TimeUnit duration = TimeUnit::FromSeconds(mMediaSource->Duration());
  TimeUnit currentPosition = TimeUnit::FromMicroseconds(CurrentPosition());
  if (duration.IsInfinite()) {
    // We can't make an informed decision and just assume that it's a live stream
    return true;
  } else if (duration <= currentPosition) {
    return true;
  }
  // If we have data up to the mediasource's duration or 30s ahead, we can
  // assume that we can play without interruption.
  TimeUnit timeAhead =
    std::min(duration, currentPosition + TimeUnit::FromSeconds(30));
  TimeInterval interval(currentPosition,
                        timeAhead,
                        MediaSourceDemuxer::EOS_FUZZ);
  return GetBuffered().Contains(ClampIntervalToEnd(interval));
}
media::TimeIntervals
MediaSourceDecoder::GetSeekable()
{
  MOZ_ASSERT(NS_IsMainThread());
  if (!mMediaSource) {
    NS_WARNING("MediaSource element isn't attached");
    return media::TimeIntervals::Invalid();
  }

  media::TimeIntervals seekable;
  double duration = mMediaSource->Duration();
  if (IsNaN(duration)) {
    // Return empty range.
  } else if (duration > 0 && mozilla::IsInfinite(duration)) {
    media::TimeIntervals buffered = GetBuffered();
    if (buffered.Length()) {
      seekable +=
        media::TimeInterval(media::TimeUnit::FromSeconds(0), buffered.GetEnd());
    }
  } else {
    seekable += media::TimeInterval(media::TimeUnit::FromSeconds(0),
                                    media::TimeUnit::FromSeconds(duration));
  }
  MSE_DEBUG("ranges=%s", DumpTimeRanges(seekable).get());
  return seekable;
}
void
MediaDecoderReader::UpdateBuffered()
{
  MOZ_ASSERT(OnTaskQueue());
  NS_ENSURE_TRUE_VOID(!mShutdown);
  mBuffered = GetBuffered();
}
double
SourceBuffer::GetBufferedEnd()
{
  MOZ_ASSERT(NS_IsMainThread());
  ErrorResult dummy;
  nsRefPtr<TimeRanges> ranges = GetBuffered(dummy);
  return ranges->Length() > 0 ? ranges->GetEndTime() : 0;
}
bool
SourceBufferDecoder::ContainsTime(double aTime)
{
  ErrorResult dummy;
  nsRefPtr<dom::TimeRanges> ranges = new dom::TimeRanges();
  nsresult rv = GetBuffered(ranges);
  if (NS_FAILED(rv) || ranges->Length() == 0) {
    return false;
  }
  return ranges->Find(aTime) != dom::TimeRanges::NoIndex;
}
Beispiel #6
0
void
SourceBuffer::GetBufferedStartEndTime(double* aStart, double* aEnd)
{
  ErrorResult dummy;
  nsRefPtr<TimeRanges> ranges = GetBuffered(dummy);
  if (!ranges || ranges->Length() == 0) {
    *aStart = *aEnd = 0.0;
    return;
  }
  *aStart = ranges->Start(0, dummy);
  *aEnd = ranges->End(ranges->Length() - 1, dummy);
}
Beispiel #7
0
bool
SourceBuffer::ContainsTime(double aTime)
{
  ErrorResult dummy;
  nsRefPtr<TimeRanges> ranges = GetBuffered(dummy);
  if (!ranges || ranges->Length() == 0) {
    return false;
  }
  for (uint32_t i = 0; i < ranges->Length(); ++i) {
    if (aTime >= ranges->Start(i, dummy) &&
        aTime <= ranges->End(i, dummy)) {
      return true;
    }
  }
  return false;
}
MediaDecoderOwner::NextFrameStatus
MediaSourceDecoder::NextFrameBufferedStatus()
{
  MOZ_ASSERT(NS_IsMainThread());

  if (!mMediaSource ||
      mMediaSource->ReadyState() == dom::MediaSourceReadyState::Closed) {
    return MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
  }

  // Next frame hasn't been decoded yet.
  // Use the buffered range to consider if we have the next frame available.
  TimeUnit currentPosition = TimeUnit::FromMicroseconds(CurrentPosition());
  TimeInterval interval(currentPosition,
                        currentPosition + media::TimeUnit::FromMicroseconds(DEFAULT_NEXT_FRAME_AVAILABLE_BUFFERED),
                        MediaSourceDemuxer::EOS_FUZZ);
  return GetBuffered().Contains(ClampIntervalToEnd(interval))
    ? MediaDecoderOwner::NEXT_FRAME_AVAILABLE
    : MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
}
media::TimeIntervals
MediaSourceDecoder::GetSeekable()
{
  MOZ_ASSERT(NS_IsMainThread());
  if (!mMediaSource) {
    NS_WARNING("MediaSource element isn't attached");
    return media::TimeIntervals::Invalid();
  }

  media::TimeIntervals seekable;
  double duration = mMediaSource->Duration();
  if (IsNaN(duration)) {
    // Return empty range.
  } else if (duration > 0 && mozilla::IsInfinite(duration)) {
    media::TimeIntervals buffered = GetBuffered();

    // 1. If live seekable range is not empty:
    if (mMediaSource->HasLiveSeekableRange()) {
      // 1. Let union ranges be the union of live seekable range and the
      // HTMLMediaElement.buffered attribute.
      media::TimeIntervals unionRanges =
        buffered + mMediaSource->LiveSeekableRange();
      // 2. Return a single range with a start time equal to the earliest start
      // time in union ranges and an end time equal to the highest end time in
      // union ranges and abort these steps.
      seekable +=
        media::TimeInterval(unionRanges.GetStart(), unionRanges.GetEnd());
      return seekable;
    }

    if (buffered.Length()) {
      seekable +=
        media::TimeInterval(media::TimeUnit::FromSeconds(0), buffered.GetEnd());
    }
  } else {
    seekable += media::TimeInterval(media::TimeUnit::FromSeconds(0),
                                    media::TimeUnit::FromSeconds(duration));
  }
  MSE_DEBUG("ranges=%s", DumpTimeRanges(seekable).get());
  return seekable;
}