Пример #1
0
void
SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
{
    MSE_DEBUG("SourceBuffer(%p)::AppendData(aLength=%u)", this, aLength);
    if (!PrepareAppend(aRv)) {
        return;
    }
    StartUpdating();

    if (!mTrackBuffer->AppendData(aData, aLength)) {
        Optional<MediaSourceEndOfStreamError> decodeError(MediaSourceEndOfStreamError::Decode);
        ErrorResult dummy;
        mMediaSource->EndOfStream(decodeError, dummy);
        aRv.Throw(NS_ERROR_FAILURE);
        return;
    }

    if (mTrackBuffer->HasInitSegment()) {
        mMediaSource->QueueInitializationEvent();
    }

    // Run the final step of the buffer append algorithm asynchronously to
    // ensure the SourceBuffer's updating flag transition behaves as required
    // by the spec.
    nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &SourceBuffer::StopUpdating);
    NS_DispatchToMainThread(event);
}
Пример #2
0
void
SourceBuffer::Remove(double aStart, double aEnd, ErrorResult& aRv)
{
  MOZ_ASSERT(NS_IsMainThread());
  MSE_API("Remove(aStart=%f, aEnd=%f)", aStart, aEnd);
  if (!IsAttached()) {
    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
    return;
  }
  if (mUpdating) {
    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
    return;
  }
  if (IsNaN(mMediaSource->Duration()) ||
      aStart < 0 || aStart > mMediaSource->Duration() ||
      aEnd <= aStart || IsNaN(aEnd)) {
    aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
    return;
  }
  if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
    mMediaSource->SetReadyState(MediaSourceReadyState::Open);
  }

  StartUpdating();
  nsCOMPtr<nsIRunnable> task = new RangeRemovalRunnable(this, aStart, aEnd);
  NS_DispatchToMainThread(task);
}
Пример #3
0
void
SourceBuffer::Remove(double aStart, double aEnd, ErrorResult& aRv)
{
    MOZ_ASSERT(NS_IsMainThread());
    MSE_API("SourceBuffer(%p)::Remove(aStart=%f, aEnd=%f)", this, aStart, aEnd);
    if (!IsAttached()) {
        aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
        return;
    }
    if (IsNaN(mMediaSource->Duration()) ||
            aStart < 0 || aStart > mMediaSource->Duration() ||
            aEnd <= aStart || IsNaN(aEnd)) {
        aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
        return;
    }
    if (mUpdating || mMediaSource->ReadyState() != MediaSourceReadyState::Open) {
        aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
        return;
    }
    StartUpdating();
    /// TODO: Run coded frame removal algorithm.

    // Run the final step of the coded frame removal algorithm asynchronously
    // to ensure the SourceBuffer's updating flag transition behaves as
    // required by the spec.
    nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &SourceBuffer::StopUpdating);
    NS_DispatchToMainThread(event);
}
Пример #4
0
SelfUpdater::SelfUpdater(const QString & arcUrl, QWidget *parent) :
    QDialog(parent, Qt::WindowTitleHint | Qt::CustomizeWindowHint),
    ui(new Ui::SelfUpdater),
    archiveUrl(arcUrl),
    currentDownload(0),
    unpacker(0),
    lastErrorCode(0)
{
    ui->setupUi(this);

    networkManager = new QNetworkAccessManager();
    unpacker = new ZipUnpacker();

    connect(this, SIGNAL(StartUpdating()), this, SLOT(OnStartUpdating()));

    emit StartUpdating();
}
Пример #5
0
void
SourceBuffer::RangeRemoval(double aStart, double aEnd)
{
  StartUpdating();
  DoRangeRemoval(aStart, aEnd);
  nsCOMPtr<nsIRunnable> task =
    NS_NewRunnableMethod(this, &SourceBuffer::StopUpdating);
  NS_DispatchToMainThread(task);
}
Пример #6
0
void
SourceBuffer::RangeRemoval(double aStart, double aEnd)
{
  StartUpdating();

  RefPtr<SourceBuffer> self = this;
  mTrackBuffersManager->RangeRemoval(TimeUnit::FromSeconds(aStart),
                                     TimeUnit::FromSeconds(aEnd))
    ->Then(AbstractThread::MainThread(), __func__,
           [self] (bool) { self->StopUpdating(); },
           []() { MOZ_ASSERT(false); });
}
Пример #7
0
void
SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
{
  MSE_DEBUG("AppendData(aLength=%u)", aLength);

  RefPtr<MediaByteBuffer> data = PrepareAppend(aData, aLength, aRv);
  if (!data) {
    return;
  }
  StartUpdating();

  mPendingAppend.Begin(mTrackBuffersManager->AppendData(data, mCurrentAttributes)
                       ->Then(AbstractThread::MainThread(), __func__, this,
                              &SourceBuffer::AppendDataCompletedWithSuccess,
                              &SourceBuffer::AppendDataErrored));
}
Пример #8
0
void
SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
{
  MSE_DEBUG("AppendData(aLength=%u)", aLength);

  RefPtr<MediaByteBuffer> data = PrepareAppend(aData, aLength, aRv);
  if (!data) {
    return;
  }
  mContentManager->AppendData(data, mAttributes->GetTimestampOffset());

  StartUpdating();

  nsCOMPtr<nsIRunnable> task = new BufferAppendRunnable(this, mUpdateID);
  NS_DispatchToMainThread(task);
}
Пример #9
0
void
SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
{
  MSE_DEBUG("AppendData(aLength=%u)", aLength);

  nsRefPtr<LargeDataBuffer> data = PrepareAppend(aData, aLength, aRv);
  if (!data) {
    return;
  }
  StartUpdating();

  MOZ_ASSERT(mAppendMode == SourceBufferAppendMode::Segments,
             "We don't handle timestampOffset for sequence mode yet");
  nsCOMPtr<nsIRunnable> task =
    new AppendDataRunnable(this, data, mTimestampOffset, mUpdateID);
  NS_DispatchToMainThread(task);
}
Пример #10
0
void
SourceBuffer::Remove(double aStart, double aEnd, ErrorResult& aRv)
{
  if (!IsAttached() || mUpdating ||
      mMediaSource->ReadyState() != MediaSourceReadyState::Open) {
    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
    return;
  }
  if (aStart < 0 || aStart > mMediaSource->Duration() ||
      aEnd <= aStart) {
    aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
    return;
  }
  StartUpdating();
  /// TODO: Run coded frame removal algorithm asynchronously (would call StopUpdating()).
  StopUpdating();
}
Пример #11
0
void
SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
{
    MSE_DEBUG("AppendData(aLength=%u)", aLength);

    nsRefPtr<MediaByteBuffer> data = PrepareAppend(aData, aLength, aRv);
    if (!data) {
        return;
    }
    mContentManager->AppendData(data, mTimestampOffset);

    StartUpdating();

    MOZ_ASSERT(mIsUsingFormatReader || mAppendMode == SourceBufferAppendMode::Segments,
               "We don't handle timestampOffset for sequence mode yet");
    nsCOMPtr<nsIRunnable> task = new BufferAppendRunnable(this, mUpdateID);
    NS_DispatchToMainThread(task);
}
Пример #12
0
void
SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
{
  if (!IsAttached() || mUpdating) {
    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
    return;
  }
  if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
    mMediaSource->SetReadyState(MediaSourceReadyState::Open);
  }
  // TODO: Run coded frame eviction algorithm.
  // TODO: Test buffer full flag.
  MSE_DEBUG("%p Append(ArrayBuffer=%u)", this, aLength);
  StartUpdating();
  // XXX: For future reference: NDA call must run on the main thread.
  mDecoder->NotifyDataArrived(reinterpret_cast<const char*>(aData),
                              aLength,
                              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();
}
Пример #13
0
void
SourceBuffer::Remove(double aStart, double aEnd, ErrorResult& aRv)
{
  MOZ_ASSERT(NS_IsMainThread());
  MSE_API("SourceBuffer(%p)::Remove(aStart=%f, aEnd=%f)", this, aStart, aEnd);
  if (IsNaN(mMediaSource->Duration()) ||
      aStart < 0 || aStart > mMediaSource->Duration() ||
      aEnd <= aStart || IsNaN(aEnd)) {
    aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
    return;
  }
  if (!IsAttached() || mUpdating ||
      mMediaSource->ReadyState() != MediaSourceReadyState::Open) {
    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
    return;
  }
  StartUpdating();
  /// TODO: Run coded frame removal algorithm asynchronously (would call StopUpdating()).
  StopUpdating();
}
Пример #14
0
void
SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
{
  MSE_DEBUG("SourceBuffer(%p)::AppendData(aLength=%u)", this, aLength);
  if (!IsAttached() || mUpdating) {
    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
    return;
  }
  if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
    mMediaSource->SetReadyState(MediaSourceReadyState::Open);
  }
  // TODO: Run coded frame eviction algorithm.
  // TODO: Test buffer full flag.
  StartUpdating();
  // TODO: Run buffer append algorithm asynchronously (would call StopUpdating()).
  if (mParser->IsInitSegmentPresent(aData, aLength)) {
    MSE_DEBUG("SourceBuffer(%p)::AppendData: New initialization segment.", this);
    if (mDecoderInitialized) {
      // Existing decoder has been used, time for a new one.
      DiscardDecoder();
    }

    // If we've got a decoder here, it's not initialized, so we can use it
    // rather than creating a new one.
    if (!mDecoder && !InitNewDecoder()) {
      aRv.Throw(NS_ERROR_FAILURE); // XXX: Review error handling.
      return;
    }
    MSE_DEBUG("SourceBuffer(%p)::AppendData: Decoder marked as initialized.", this);
    mDecoderInitialized = true;
  } else if (!mDecoderInitialized) {
    MSE_DEBUG("SourceBuffer(%p)::AppendData: Non-init segment appended during initialization.");
    Optional<MediaSourceEndOfStreamError> decodeError(MediaSourceEndOfStreamError::Decode);
    ErrorResult dummy;
    mMediaSource->EndOfStream(decodeError, dummy);
    aRv.Throw(NS_ERROR_FAILURE);
    return;
  }
  // XXX: For future reference: NDA call must run on the main thread.
  mDecoder->NotifyDataArrived(reinterpret_cast<const char*>(aData),
                              aLength,
                              mDecoder->GetResource()->GetLength());
  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 SourceBuffers it knows
  // about.
  // TODO: Make the eviction threshold smaller for audio-only streams.
  // TODO: Drive evictions off memory pressure notifications.
  const uint32_t evict_threshold = 75 * (1 << 20);
  bool evicted = mDecoder->GetResource()->EvictData(evict_threshold);
  if (evicted) {
    MSE_DEBUG("SourceBuffer(%p)::AppendBuffer Evict; current buffered start=%f",
              this, GetBufferedStart());

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

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

  mMediaSource->NotifyGotData();
}
Пример #15
0
void
SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
{
  MSE_DEBUG("SourceBuffer(%p)::AppendData(aLength=%u)", this, aLength);
  if (!PrepareAppend(aRv)) {
    return;
  }
  StartUpdating();
  // TODO: Run more of the buffer append algorithm asynchronously.
  if (mParser->IsInitSegmentPresent(aData, aLength)) {
    MSE_DEBUG("SourceBuffer(%p)::AppendData: New initialization segment.", this);
    mMediaSource->QueueInitializationEvent();
    mTrackBuffer->DiscardDecoder();
    if (!mTrackBuffer->NewDecoder()) {
      aRv.Throw(NS_ERROR_FAILURE); // XXX: Review error handling.
      return;
    }
    MSE_DEBUG("SourceBuffer(%p)::AppendData: Decoder marked as initialized.", this);
  } else if (!mTrackBuffer->HasInitSegment()) {
    MSE_DEBUG("SourceBuffer(%p)::AppendData: Non-init segment appended during initialization.", this);
    Optional<MediaSourceEndOfStreamError> decodeError(MediaSourceEndOfStreamError::Decode);
    ErrorResult dummy;
    mMediaSource->EndOfStream(decodeError, dummy);
    aRv.Throw(NS_ERROR_FAILURE);
    return;
  }
  int64_t start, end;
  if (mParser->ParseStartAndEndTimestamps(aData, aLength, start, end)) {
    int64_t lastStart, lastEnd;
    mTrackBuffer->LastTimestamp(lastStart, lastEnd);
    if (mParser->IsMediaSegmentPresent(aData, aLength) &&
        !mParser->TimestampsFuzzyEqual(start, lastEnd)) {
      MSE_DEBUG("SourceBuffer(%p)::AppendData: Data last=[%lld, %lld] overlaps [%lld, %lld]",
                this, lastStart, lastEnd, start, end);

      // This data is earlier in the timeline than data we have already
      // processed, so we must create a new decoder to handle the decoding.
      mTrackBuffer->DiscardDecoder();

      // If we've got a decoder here, it's not initialized, so we can use it
      // rather than creating a new one.
      if (!mTrackBuffer->NewDecoder()) {
        aRv.Throw(NS_ERROR_FAILURE); // XXX: Review error handling.
        return;
      }
      MSE_DEBUG("SourceBuffer(%p)::AppendData: Decoder marked as initialized.", this);
      const nsTArray<uint8_t>& initData = mParser->InitData();
      mTrackBuffer->AppendData(initData.Elements(), initData.Length());
      mTrackBuffer->SetLastStartTimestamp(start);
    }
    mTrackBuffer->SetLastEndTimestamp(end);
    MSE_DEBUG("SourceBuffer(%p)::AppendData: Segment last=[%lld, %lld] [%lld, %lld]",
              this, lastStart, lastEnd, start, end);
  }
  if (!mTrackBuffer->AppendData(aData, aLength)) {
    Optional<MediaSourceEndOfStreamError> decodeError(MediaSourceEndOfStreamError::Decode);
    ErrorResult dummy;
    mMediaSource->EndOfStream(decodeError, dummy);
    aRv.Throw(NS_ERROR_FAILURE);
    return;
  }

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

  // Run the final step of the buffer append algorithm asynchronously to
  // ensure the SourceBuffer's updating flag transition behaves as required
  // by the spec.
  nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &SourceBuffer::StopUpdating);
  NS_DispatchToMainThread(event);
}