Bug 1276272 - part 3 - implement promise-based HTMLMediaElement::seekToNextFrame(); r=jwwang

MozReview-Commit-ID: JaUQe5GK6bF
This commit is contained in:
Kaku Kuo
2016-06-09 20:27:39 +01:00
parent ea955d482e
commit ae2ee4a539
4 changed files with 110 additions and 30 deletions

View File

@@ -1466,19 +1466,19 @@ HTMLMediaElement::FastSeek(double aTime, ErrorResult& aRv)
{
LOG(LogLevel::Debug, ("Reporting telemetry VIDEO_FASTSEEK_USED"));
Telemetry::Accumulate(Telemetry::VIDEO_FASTSEEK_USED, 1);
Seek(aTime, SeekTarget::PrevSyncPoint, aRv);
RefPtr<Promise> tobeDropped = Seek(aTime, SeekTarget::PrevSyncPoint, aRv);
}
void
already_AddRefed<Promise>
HTMLMediaElement::SeekToNextFrame(ErrorResult& aRv)
{
Seek(CurrentTime(), SeekTarget::NextFrame, aRv);
return Seek(CurrentTime(), SeekTarget::NextFrame, aRv);
}
void
HTMLMediaElement::SetCurrentTime(double aCurrentTime, ErrorResult& aRv)
{
Seek(aCurrentTime, SeekTarget::Accurate, aRv);
RefPtr<Promise> tobeDropped = Seek(aCurrentTime, SeekTarget::Accurate, aRv);
}
/**
@@ -1519,7 +1519,7 @@ IsInRanges(dom::TimeRanges& aRanges,
return NS_OK;
}
void
already_AddRefed<Promise>
HTMLMediaElement::Seek(double aTime,
SeekTarget::Type aSeekType,
ErrorResult& aRv)
@@ -1527,6 +1527,19 @@ HTMLMediaElement::Seek(double aTime,
// aTime should be non-NaN.
MOZ_ASSERT(!mozilla::IsNaN(aTime));
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(OwnerDoc()->GetInnerWindow());
if (!global) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
RefPtr<Promise> promise = Promise::Create(global, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
// Detect if user has interacted with element by seeking so that
// play will not be blocked when initiated by a script.
if (EventStateManager::IsHandlingUserInput() || nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
@@ -1537,7 +1550,8 @@ HTMLMediaElement::Seek(double aTime,
if (mSrcStream) {
// do nothing since media streams have an empty Seekable range.
return;
promise->MaybeRejectWithUndefined();
return promise.forget();
}
if (mPlayed && mCurrentPlayRangeStart != -1.0) {
@@ -1554,27 +1568,30 @@ HTMLMediaElement::Seek(double aTime,
if (mReadyState == nsIDOMHTMLMediaElement::HAVE_NOTHING) {
mDefaultPlaybackStartPosition = aTime;
return;
promise->MaybeRejectWithUndefined();
return promise.forget();
}
if (!mDecoder) {
// mDecoder must always be set in order to reach this point.
NS_ASSERTION(mDecoder, "SetCurrentTime failed: no decoder");
return;
promise->MaybeRejectWithUndefined();
return promise.forget();
}
// Clamp the seek target to inside the seekable ranges.
RefPtr<dom::TimeRanges> seekable = new dom::TimeRanges(ToSupports(OwnerDoc()));
media::TimeIntervals seekableIntervals = mDecoder->GetSeekable();
if (seekableIntervals.IsInvalid()) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); // This will reject the promise.
return promise.forget();
}
seekableIntervals.ToTimeRanges(seekable);
uint32_t length = 0;
seekable->GetLength(&length);
if (!length) {
return;
promise->MaybeRejectWithUndefined();
return promise.forget();
}
// If the position we want to seek to is not in a seekable range, we seek
@@ -1585,8 +1602,8 @@ HTMLMediaElement::Seek(double aTime,
int32_t range = 0;
bool isInRange = false;
if (NS_FAILED(IsInRanges(*seekable, aTime, isInRange, range))) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); // This will reject the promise.
return promise.forget();
}
if (!isInRange) {
if (range != -1) {
@@ -1596,11 +1613,11 @@ HTMLMediaElement::Seek(double aTime,
double leftBound, rightBound;
if (NS_FAILED(seekable->End(range, &leftBound))) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
return promise.forget();
}
if (NS_FAILED(seekable->Start(range + 1, &rightBound))) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
return promise.forget();
}
double distanceLeft = Abs(leftBound - aTime);
double distanceRight = Abs(rightBound - aTime);
@@ -1615,7 +1632,7 @@ HTMLMediaElement::Seek(double aTime,
// Clamp the seek target to the end of the last seekable range.
if (NS_FAILED(seekable->End(length - 1, &aTime))) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
return promise.forget();
}
}
} else {
@@ -1641,13 +1658,15 @@ HTMLMediaElement::Seek(double aTime,
// The media backend is responsible for dispatching the timeupdate
// event if it changes the playback position as a result of the seek.
LOG(LogLevel::Debug, ("%p SetCurrentTime(%f) starting seek", this, aTime));
nsresult rv = mDecoder->Seek(aTime, aSeekType);
nsresult rv = mDecoder->Seek(aTime, aSeekType, promise);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
}
// We changed whether we're seeking so we need to AddRemoveSelfReference.
AddRemoveSelfReference();
return promise.forget();
}
NS_IMETHODIMP HTMLMediaElement::SetCurrentTime(double aCurrentTime)