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); }
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); }
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); }
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(); }
void SourceBuffer::RangeRemoval(double aStart, double aEnd) { StartUpdating(); DoRangeRemoval(aStart, aEnd); nsCOMPtr<nsIRunnable> task = NS_NewRunnableMethod(this, &SourceBuffer::StopUpdating); NS_DispatchToMainThread(task); }
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); }); }
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)); }
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); }
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); }
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(); }
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); }
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(); }
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(); }
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(); }
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); }