зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1362165: P7. Only complete appendBuffer once readyState has changed. r=jwwang
MSE specs require that the readyState be modified during either the Initialization Segment Received or the Coded Frame Processing algorithms. At this stage, we only handle the Initialization Segment part (readyState moving from HAVE_NOTHING to HAVE_METADATA) MozReview-Commit-ID: KBnnWuHJ6Om --HG-- extra : rebase_source : a4450139762d5d033438fbee2ce560fe02ed6ffc
This commit is contained in:
Родитель
5c7678f322
Коммит
a16fab66e4
|
@ -1658,6 +1658,9 @@ void HTMLMediaElement::ShutdownDecoder()
|
|||
RemoveMediaElementFromURITable();
|
||||
NS_ASSERTION(mDecoder, "Must have decoder to shut down");
|
||||
mWaitingForKeyListener.DisconnectIfExists();
|
||||
if (mMediaSource) {
|
||||
mMediaSource->CompletePendingTransactions();
|
||||
}
|
||||
mDecoder->Shutdown();
|
||||
mDecoder = nullptr;
|
||||
}
|
||||
|
@ -5583,6 +5586,12 @@ HTMLMediaElement::UpdateReadyStateInternal()
|
|||
MetadataLoaded(&mediaInfo, nsAutoPtr<const MetadataTags>(nullptr));
|
||||
}
|
||||
|
||||
if (mMediaSource) {
|
||||
// readyState has changed, assuming it's following the pending mediasource
|
||||
// operations. Notify the Mediasource that the operations have completed.
|
||||
mMediaSource->CompletePendingTransactions();
|
||||
}
|
||||
|
||||
enum NextFrameStatus nextFrameStatus = NextFrameStatus();
|
||||
if (nextFrameStatus == NEXT_FRAME_UNAVAILABLE ||
|
||||
(nextFrameStatus == NEXT_FRAME_UNAVAILABLE_BUFFERING &&
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "DecoderDoctorDiagnostics.h"
|
||||
#include "MediaContainerType.h"
|
||||
#include "MediaResult.h"
|
||||
#include "MediaSourceDemuxer.h"
|
||||
#include "MediaSourceUtils.h"
|
||||
#include "SourceBuffer.h"
|
||||
#include "SourceBufferList.h"
|
||||
|
@ -255,11 +256,12 @@ MediaSource::AddSourceBuffer(const nsAString& aType, ErrorResult& aRv)
|
|||
return sourceBuffer.forget();
|
||||
}
|
||||
|
||||
void
|
||||
RefPtr<MediaSource::ActiveCompletionPromise>
|
||||
MediaSource::SourceBufferIsActive(SourceBuffer* aSourceBuffer)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mActiveSourceBuffers->ClearSimple();
|
||||
bool initMissing = false;
|
||||
bool found = false;
|
||||
for (uint32_t i = 0; i < mSourceBuffers->Length(); i++) {
|
||||
SourceBuffer* sourceBuffer = mSourceBuffers->IndexedGetter(i, found);
|
||||
|
@ -268,8 +270,35 @@ MediaSource::SourceBufferIsActive(SourceBuffer* aSourceBuffer)
|
|||
mActiveSourceBuffers->Append(aSourceBuffer);
|
||||
} else if (sourceBuffer->IsActive()) {
|
||||
mActiveSourceBuffers->AppendSimple(sourceBuffer);
|
||||
} else {
|
||||
// Some source buffers haven't yet received an init segment.
|
||||
// There's nothing more we can do at this stage.
|
||||
initMissing = true;
|
||||
}
|
||||
}
|
||||
if (initMissing || !mDecoder) {
|
||||
return ActiveCompletionPromise::CreateAndResolve(true, __func__);
|
||||
}
|
||||
|
||||
mDecoder->NotifyInitDataArrived();
|
||||
|
||||
// Add our promise to the queue.
|
||||
// It will be resolved once the HTMLMediaElement modifies its readyState.
|
||||
MozPromiseHolder<ActiveCompletionPromise> holder;
|
||||
RefPtr<ActiveCompletionPromise> promise = holder.Ensure(__func__);
|
||||
mCompletionPromises.AppendElement(Move(holder));
|
||||
return promise;
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::CompletePendingTransactions()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MSE_DEBUG("Resolving %u promises", unsigned(mCompletionPromises.Length()));
|
||||
for (auto& promise : mCompletionPromises) {
|
||||
promise.Resolve(true, __func__);
|
||||
}
|
||||
mCompletionPromises.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -433,6 +462,7 @@ void
|
|||
MediaSource::Detach()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(mCompletionPromises.IsEmpty());
|
||||
MSE_DEBUG("mDecoder=%p owner=%p",
|
||||
mDecoder.get(), mDecoder ? mDecoder->GetOwner() : nullptr);
|
||||
if (!mDecoder) {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "mozilla/dom/MediaSourceBinding.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionNoteChild.h"
|
||||
|
@ -119,6 +120,9 @@ public:
|
|||
return mAbstractMainThread;
|
||||
}
|
||||
|
||||
// Resolve all CompletionPromise pending.
|
||||
void CompletePendingTransactions();
|
||||
|
||||
private:
|
||||
// SourceBuffer uses SetDuration and SourceBufferIsActive
|
||||
friend class mozilla::dom::SourceBuffer;
|
||||
|
@ -136,8 +140,14 @@ private:
|
|||
// SetDuration with no checks.
|
||||
void SetDuration(double aDuration);
|
||||
|
||||
typedef MozPromise<bool, MediaResult, /* IsExclusive = */ true>
|
||||
ActiveCompletionPromise;
|
||||
// Mark SourceBuffer as active and rebuild ActiveSourceBuffers.
|
||||
void SourceBufferIsActive(SourceBuffer* aSourceBuffer);
|
||||
// Return a MozPromise that will be resolved once all related operations are
|
||||
// completed, or can't progress any further.
|
||||
// Such as, transition of readyState from HAVE_NOTHING to HAVE_METADATA.
|
||||
RefPtr<ActiveCompletionPromise> SourceBufferIsActive(
|
||||
SourceBuffer* aSourceBuffer);
|
||||
|
||||
RefPtr<SourceBufferList> mSourceBuffers;
|
||||
RefPtr<SourceBufferList> mActiveSourceBuffers;
|
||||
|
@ -154,6 +164,7 @@ private:
|
|||
MediaSourceReadyState mReadyState;
|
||||
|
||||
Maybe<media::TimeInterval> mLiveSeekableRange;
|
||||
nsTArray<MozPromiseHolder<ActiveCompletionPromise>> mCompletionPromises;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(MediaSource, MOZILLA_DOM_MEDIASOURCE_IMPLEMENTATION_IID)
|
||||
|
|
|
@ -212,6 +212,7 @@ void
|
|||
SourceBuffer::AbortBufferAppend()
|
||||
{
|
||||
if (mUpdating) {
|
||||
mCompletionPromise.DisconnectIfExists();
|
||||
if (mPendingAppend.Exists()) {
|
||||
mPendingAppend.Disconnect();
|
||||
mTrackBuffersManager->AbortAppendData();
|
||||
|
@ -433,8 +434,16 @@ SourceBuffer::AppendDataCompletedWithSuccess(const SourceBufferTask::AppendBuffe
|
|||
if (aResult.first()) {
|
||||
if (!mActive) {
|
||||
mActive = true;
|
||||
mMediaSource->SourceBufferIsActive(this);
|
||||
mMediaSource->GetDecoder()->NotifyInitDataArrived();
|
||||
MSE_DEBUG("Init segment received");
|
||||
RefPtr<SourceBuffer> self = this;
|
||||
mMediaSource->SourceBufferIsActive(this)
|
||||
->Then(mAbstractMainThread, __func__,
|
||||
[self, this]() {
|
||||
MSE_DEBUG("Complete AppendBuffer operation");
|
||||
mCompletionPromise.Complete();
|
||||
StopUpdating();
|
||||
})
|
||||
->Track(mCompletionPromise);
|
||||
}
|
||||
}
|
||||
if (mActive) {
|
||||
|
@ -448,7 +457,9 @@ SourceBuffer::AppendDataCompletedWithSuccess(const SourceBufferTask::AppendBuffe
|
|||
|
||||
CheckEndTime();
|
||||
|
||||
StopUpdating();
|
||||
if (!mCompletionPromise.Exists()) {
|
||||
StopUpdating();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -182,6 +182,8 @@ private:
|
|||
const MediaContainerType mType;
|
||||
|
||||
RefPtr<TimeRanges> mBuffered;
|
||||
|
||||
MozPromiseRequestHolder<MediaSource::ActiveCompletionPromise> mCompletionPromise;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
Загрузка…
Ссылка в новой задаче