Bug 1119757: Allow seeking on media with infinite duration. r=cpearce

MSE defines content to have infinite duration when no duration is defined.
And MSE is always seekable within the buffered range, regardless of the duration

--HG--
extra : rebase_source : 369cce10504b125716af0a60e07d1d1144117f59
This commit is contained in:
Jean-Yves Avenard 2015-01-16 23:49:01 +11:00
Родитель 9e51efea6e
Коммит b0638f45f3
2 изменённых файлов: 38 добавлений и 11 удалений

Просмотреть файл

@ -188,6 +188,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mPlayDuration(0),
mStartTime(-1),
mEndTime(-1),
mDurationSet(false),
mFragmentEndTime(-1),
mReader(aReader),
mCurrentFrameTime(0),
@ -1408,6 +1409,14 @@ int64_t MediaDecoderStateMachine::GetDuration()
return mEndTime - mStartTime;
}
int64_t MediaDecoderStateMachine::GetEndTime()
{
if (mEndTime == -1 && mDurationSet) {
return INT64_MAX;
}
return mEndTime;
}
void MediaDecoderStateMachine::SetDuration(int64_t aDuration)
{
NS_ASSERTION(NS_IsMainThread() || OnDecodeThread(),
@ -1415,13 +1424,21 @@ void MediaDecoderStateMachine::SetDuration(int64_t aDuration)
AssertCurrentThreadInMonitor();
if (aDuration == -1) {
mDurationSet = false;
return;
}
mDurationSet = true;
if (mStartTime == -1) {
SetStartTime(0);
}
if (aDuration == INT64_MAX) {
mEndTime = -1;
return;
}
mEndTime = mStartTime + aDuration;
}
@ -1735,12 +1752,13 @@ MediaDecoderStateMachine::StartSeek(const SeekTarget& aTarget)
}
// Bound the seek time to be inside the media range.
int64_t end = GetEndTime();
NS_ASSERTION(mStartTime != -1, "Should know start time by now");
NS_ASSERTION(mEndTime != -1, "Should know end time by now");
NS_ASSERTION(end != -1, "Should know end time by now");
int64_t seekTime = aTarget.mTime + mStartTime;
seekTime = std::min(seekTime, mEndTime);
seekTime = std::min(seekTime, end);
seekTime = std::max(mStartTime, seekTime);
NS_ASSERTION(seekTime >= mStartTime && seekTime <= mEndTime,
NS_ASSERTION(seekTime >= mStartTime && seekTime <= end,
"Can only seek in range [0,duration]");
mSeekTarget = SeekTarget(seekTime, aTarget.mType);
@ -2188,7 +2206,7 @@ nsresult MediaDecoderStateMachine::DecodeMetadata()
return NS_ERROR_FAILURE;
}
mDecoder->StartProgressUpdates();
mGotDurationFromMetaData = (GetDuration() != -1);
mGotDurationFromMetaData = (GetDuration() != -1) || mDurationSet;
if (mGotDurationFromMetaData) {
// We have all the information required: duration and size
@ -2300,12 +2318,8 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame()
}
NS_ASSERTION(mStartTime != -1, "Must have start time");
MOZ_ASSERT((!HasVideo() && !HasAudio()) ||
!(mDecoder->IsMediaSeekable() && mDecoder->IsTransportSeekable()) ||
mEndTime != -1,
"Active seekable media should have end time");
MOZ_ASSERT(!(mDecoder->IsMediaSeekable() && mDecoder->IsTransportSeekable()) ||
GetDuration() != -1,
(GetDuration() != -1) || mDurationSet,
"Seekable media should have duration");
DECODER_LOG("Media goes from %lld to %lld (duration %lld) "
"transportSeekable=%d, mediaSeekable=%d",
@ -2429,7 +2443,7 @@ void MediaDecoderStateMachine::DecodeSeek()
// the reader, since it could do I/O or deadlock some other way.
res = mReader->ResetDecode();
if (NS_SUCCEEDED(res)) {
mReader->Seek(seekTime, mStartTime, mEndTime, mCurrentTimeBeforeSeek)
mReader->Seek(seekTime, mStartTime, GetEndTime(), mCurrentTimeBeforeSeek)
->Then(DecodeTaskQueue(), __func__, this,
&MediaDecoderStateMachine::OnSeekCompleted,
&MediaDecoderStateMachine::OnSeekFailed);
@ -3244,7 +3258,7 @@ void MediaDecoderStateMachine::SetStartTime(int64_t aStartTimeUsecs)
mStartTime = 0;
if (aStartTimeUsecs != 0) {
mStartTime = aStartTimeUsecs;
if (mGotDurationFromMetaData) {
if (mGotDurationFromMetaData && GetEndTime() != INT64_MAX) {
NS_ASSERTION(mEndTime != -1,
"We should have mEndTime as supplied duration here");
// We were specified a duration from a Content-Duration HTTP header.

Просмотреть файл

@ -171,11 +171,18 @@ public:
// must be obtained before calling this. It is in units of microseconds.
int64_t GetDuration();
// Time of the last frame in the media, in microseconds or INT64_MAX if
// media has an infinite duration.
// Accessed on state machine, decode, and main threads.
// Access controlled by decoder monitor.
int64_t GetEndTime();
// Called from the main thread to set the duration of the media resource
// if it is able to be obtained via HTTP headers. Called from the
// state machine thread to set the duration if it is obtained from the
// media metadata. The decoder monitor must be obtained before calling this.
// aDuration is in microseconds.
// A value of INT64_MAX will be treated as infinity.
void SetDuration(int64_t aDuration);
// Called while decoding metadata to set the end time of the media
@ -832,8 +839,14 @@ protected:
// Time of the last frame in the media, in microseconds. This is the
// end time of the last frame in the media. Accessed on state
// machine, decode, and main threads. Access controlled by decoder monitor.
// It will be set to -1 if the duration is infinite
int64_t mEndTime;
// Will be set when SetDuration has been called with a value != -1
// mDurationSet false doesn't indicate that we do not have a valid duration
// as mStartTime and mEndTime could have been set separately.
bool mDurationSet;
// Position to seek to in microseconds when the seek state transition occurs.
// The decoder monitor lock must be obtained before reading or writing
// this value. Accessed on main and decode thread.