Beispiel #1
0
nsresult WaveReader::ReadMetadata(VideoInfo* aInfo,
                                    MetadataTags** aTags)
{
  NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");

  bool loaded = LoadRIFFChunk();
  if (!loaded) {
    return NS_ERROR_FAILURE;
  }

  nsAutoPtr<nsHTMLMediaElement::MetadataTags> tags;

  bool loadAllChunks = LoadAllChunks(tags);
  if (!loadAllChunks) {
    return NS_ERROR_FAILURE;
  }

  mInfo.mHasAudio = true;
  mInfo.mHasVideo = false;
  mInfo.mAudioRate = mSampleRate;
  mInfo.mAudioChannels = mChannels;

  *aInfo = mInfo;

  *aTags = tags.forget();

  ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());

  mDecoder->SetMediaDuration(
    static_cast<int64_t>(BytesToTime(GetDataLength()) * USECS_PER_S));

  return NS_OK;
}
Beispiel #2
0
nsresult
WaveReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
{
  MOZ_ASSERT(OnTaskQueue());

  bool loaded = LoadRIFFChunk();
  if (!loaded) {
    return NS_ERROR_FAILURE;
  }

  nsAutoPtr<dom::HTMLMediaElement::MetadataTags> tags;

  bool loadAllChunks = LoadAllChunks(tags);
  if (!loadAllChunks) {
    return NS_ERROR_FAILURE;
  }

  mInfo.mAudio.mRate = mSampleRate;
  mInfo.mAudio.mChannels = mChannels;
  mInfo.mMetadataDuration.emplace(TimeUnit::FromSeconds(BytesToTime(GetDataLength())));

  *aInfo = mInfo;

  *aTags = tags.forget();


  return NS_OK;
}
Beispiel #3
0
nsresult MediaOmxReader::GetBuffered(mozilla::dom::TimeRanges* aBuffered, int64_t aStartTime)
{
  if (!mOmxDecoder.get())
    return NS_OK;

  MediaResource* stream = mOmxDecoder->GetResource();

  int64_t durationUs = 0;
  mOmxDecoder->GetDuration(&durationUs);

  // Nothing to cache if the media takes 0us to play.
  if (!durationUs)
    return NS_OK;

  // Special case completely cached files.  This also handles local files.
  if (stream->IsDataCachedToEndOfResource(0)) {
    aBuffered->Add(0, durationUs);
    return NS_OK;
  }

  int64_t totalBytes = stream->GetLength();

  // If we can't determine the total size, pretend that we have nothing
  // buffered. This will put us in a state of eternally-low-on-undecoded-data
  // which is not get, but about the best we can do.
  if (totalBytes == -1)
    return NS_OK;

  int64_t startOffset = stream->GetNextCachedData(0);
  while (startOffset >= 0) {
    int64_t endOffset = stream->GetCachedDataEnd(startOffset);
    // Bytes [startOffset..endOffset] are cached.
    NS_ASSERTION(startOffset >= 0, "Integer underflow in GetBuffered");
    NS_ASSERTION(endOffset >= 0, "Integer underflow in GetBuffered");

    uint64_t startUs = BytesToTime(startOffset, totalBytes, durationUs);
    uint64_t endUs = BytesToTime(endOffset, totalBytes, durationUs);
    if (startUs != endUs) {
      aBuffered->Add((double)startUs / USECS_PER_S, (double)endUs / USECS_PER_S);
    }
    startOffset = stream->GetNextCachedData(endOffset);
  }
  return NS_OK;
}
Beispiel #4
0
media::TimeIntervals GetEstimatedBufferedTimeRanges(mozilla::MediaResource* aStream,
                                                    int64_t aDurationUsecs)
{
  media::TimeIntervals buffered;
  // Nothing to cache if the media takes 0us to play.
  if (aDurationUsecs <= 0 || !aStream)
    return buffered;

  // Special case completely cached files.  This also handles local files.
  if (aStream->IsDataCachedToEndOfResource(0)) {
    buffered +=
      media::TimeInterval(media::TimeUnit::FromMicroseconds(0),
                          media::TimeUnit::FromMicroseconds(aDurationUsecs));
    return buffered;
  }

  int64_t totalBytes = aStream->GetLength();

  // If we can't determine the total size, pretend that we have nothing
  // buffered. This will put us in a state of eternally-low-on-undecoded-data
  // which is not great, but about the best we can do.
  if (totalBytes <= 0)
    return buffered;

  int64_t startOffset = aStream->GetNextCachedData(0);
  while (startOffset >= 0) {
    int64_t endOffset = aStream->GetCachedDataEnd(startOffset);
    // Bytes [startOffset..endOffset] are cached.
    NS_ASSERTION(startOffset >= 0, "Integer underflow in GetBuffered");
    NS_ASSERTION(endOffset >= 0, "Integer underflow in GetBuffered");

    int64_t startUs = BytesToTime(startOffset, totalBytes, aDurationUsecs);
    int64_t endUs = BytesToTime(endOffset, totalBytes, aDurationUsecs);
    if (startUs != endUs) {
      buffered +=
        media::TimeInterval(media::TimeUnit::FromMicroseconds(startUs),

                              media::TimeUnit::FromMicroseconds(endUs));
    }
    startOffset = aStream->GetNextCachedData(endOffset);
  }
  return buffered;
}
nsresult WaveReader::GetBuffered(nsTimeRanges* aBuffered, int64_t aStartTime)
{
  if (!mInfo.mHasAudio) {
    return NS_OK;
  }
  int64_t startOffset = mDecoder->GetResource()->GetNextCachedData(mWavePCMOffset);
  while (startOffset >= 0) {
    int64_t endOffset = mDecoder->GetResource()->GetCachedDataEnd(startOffset);
    // Bytes [startOffset..endOffset] are cached.
    NS_ASSERTION(startOffset >= mWavePCMOffset, "Integer underflow in GetBuffered");
    NS_ASSERTION(endOffset >= mWavePCMOffset, "Integer underflow in GetBuffered");

    // We need to round the buffered ranges' times to microseconds so that they
    // have the same precision as the currentTime and duration attribute on 
    // the media element.
    aBuffered->Add(RoundToUsecs(BytesToTime(startOffset - mWavePCMOffset)),
                   RoundToUsecs(BytesToTime(endOffset - mWavePCMOffset)));
    startOffset = mDecoder->GetResource()->GetNextCachedData(endOffset);
  }
  return NS_OK;
}
Beispiel #6
0
media::TimeIntervals WaveReader::GetBuffered()
{
  if (!mInfo.HasAudio()) {
    return media::TimeIntervals();
  }
  media::TimeIntervals buffered;
  AutoPinned<MediaResource> resource(mDecoder->GetResource());
  int64_t startOffset = resource->GetNextCachedData(mWavePCMOffset);
  while (startOffset >= 0) {
    int64_t endOffset = resource->GetCachedDataEnd(startOffset);
    // Bytes [startOffset..endOffset] are cached.
    NS_ASSERTION(startOffset >= mWavePCMOffset, "Integer underflow in GetBuffered");
    NS_ASSERTION(endOffset >= mWavePCMOffset, "Integer underflow in GetBuffered");

    // We need to round the buffered ranges' times to microseconds so that they
    // have the same precision as the currentTime and duration attribute on
    // the media element.
    buffered += media::TimeInterval(
      media::TimeUnit::FromSeconds(BytesToTime(startOffset - mWavePCMOffset)),
      media::TimeUnit::FromSeconds(BytesToTime(endOffset - mWavePCMOffset)));
    startOffset = resource->GetNextCachedData(endOffset);
  }
  return buffered;
}
nsresult WaveReader::Seek(int64_t aTarget, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime)
{
  NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
  LOG(PR_LOG_DEBUG, ("%p About to seek to %lld", mDecoder, aTarget));
  if (NS_FAILED(ResetDecode())) {
    return NS_ERROR_FAILURE;
  }
  double d = BytesToTime(GetDataLength());
  NS_ASSERTION(d < INT64_MAX / USECS_PER_S, "Duration overflow"); 
  int64_t duration = static_cast<int64_t>(d * USECS_PER_S);
  double seekTime = NS_MIN(aTarget, duration) / static_cast<double>(USECS_PER_S);
  int64_t position = RoundDownToFrame(static_cast<int64_t>(TimeToBytes(seekTime)));
  NS_ASSERTION(INT64_MAX - mWavePCMOffset > position, "Integer overflow during wave seek");
  position += mWavePCMOffset;
  return mDecoder->GetResource()->Seek(nsISeekableStream::NS_SEEK_SET, position);
}
Beispiel #8
0
nsRefPtr<MediaDecoderReader::SeekPromise>
WaveReader::Seek(int64_t aTarget, int64_t aEndTime)
{
  MOZ_ASSERT(OnTaskQueue());
  LOG(LogLevel::Debug, ("%p About to seek to %lld", mDecoder, aTarget));

  if (NS_FAILED(ResetDecode())) {
    return SeekPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
  }
  double d = BytesToTime(GetDataLength());
  NS_ASSERTION(d < INT64_MAX / USECS_PER_S, "Duration overflow");
  int64_t duration = static_cast<int64_t>(d * USECS_PER_S);
  double seekTime = std::min(aTarget, duration) / static_cast<double>(USECS_PER_S);
  int64_t position = RoundDownToFrame(static_cast<int64_t>(TimeToBytes(seekTime)));
  NS_ASSERTION(INT64_MAX - mWavePCMOffset > position, "Integer overflow during wave seek");
  position += mWavePCMOffset;
  nsresult res = mDecoder->GetResource()->Seek(nsISeekableStream::NS_SEEK_SET, position);
  if (NS_FAILED(res)) {
    return SeekPromise::CreateAndReject(res, __func__);
  } else {
    return SeekPromise::CreateAndResolve(aTarget, __func__);
  }
}