Bug 1126465 - Use a MediaPromiseConsumerHolder to track subdecoder seeks. r=mattwoodrow

This commit is contained in:
Bobby Holley 2015-01-28 18:54:11 -08:00
parent 51b0f88fd1
commit 5b1f402fb3
2 changed files with 70 additions and 100 deletions

View File

@ -50,8 +50,6 @@ MediaSourceReader::MediaSourceReader(MediaSourceDecoder* aDecoder)
, mLastVideoTime(0)
, mPendingSeekTime(-1)
, mWaitingForSeekData(false)
, mAudioIsSeeking(false)
, mVideoIsSeeking(false)
, mTimeThreshold(0)
, mDropAudioBeforeThreshold(false)
, mDropVideoBeforeThreshold(false)
@ -124,13 +122,15 @@ MediaSourceReader::RequestAudioData()
mAudioPromise.Reject(CANCELED, __func__);
return p;
}
MOZ_RELEASE_ASSERT(!mSeekRequest.Exists());
SwitchReaderResult ret = SwitchAudioReader(mLastAudioTime);
switch (ret) {
case READER_NEW:
mAudioReader->Seek(mLastAudioTime, 0)
->Then(GetTaskQueue(), __func__, this,
&MediaSourceReader::RequestAudioDataComplete,
&MediaSourceReader::RequestAudioDataFailed);
mSeekRequest.Begin(mAudioReader->Seek(mLastAudioTime, 0)
->RefableThen(GetTaskQueue(), __func__, this,
&MediaSourceReader::CompleteSeekAndDoAudioRequest,
&MediaSourceReader::CompleteSeekAndRejectAudioPromise));
break;
case READER_ERROR:
if (mLastAudioTime) {
@ -145,17 +145,6 @@ MediaSourceReader::RequestAudioData()
return p;
}
void
MediaSourceReader::RequestAudioDataComplete(int64_t aTime)
{
if (IsSeeking()) {
MSE_DEBUG("MediaSourceReader(%p)::RequestAudioDataComplete called mid-seek. Rejecting.", this);
MOZ_RELEASE_ASSERT(mAudioPromise.IsEmpty()); // Already rejected in ::Seek().
return;
}
DoAudioRequest();
}
void MediaSourceReader::DoAudioRequest()
{
mAudioRequest.Begin(mAudioReader->RequestAudioData()
@ -164,12 +153,6 @@ void MediaSourceReader::DoAudioRequest()
&MediaSourceReader::OnAudioNotDecoded));
}
void
MediaSourceReader::RequestAudioDataFailed(nsresult aResult)
{
mAudioPromise.Reject(DECODE_ERROR, __func__);
}
void
MediaSourceReader::OnAudioDecoded(AudioData* aSample)
{
@ -245,10 +228,10 @@ MediaSourceReader::OnAudioNotDecoded(NotDecodedReason aReason)
// EOS_FUZZ_US to allow for the fact that our end time can be inaccurate due to bug
// 1065207.
if (SwitchAudioReader(mLastAudioTime, EOS_FUZZ_US) == READER_NEW) {
mAudioReader->Seek(mLastAudioTime, 0)
->Then(GetTaskQueue(), __func__, this,
&MediaSourceReader::RequestAudioDataComplete,
&MediaSourceReader::RequestAudioDataFailed);
mSeekRequest.Begin(mAudioReader->Seek(mLastAudioTime, 0)
->RefableThen(GetTaskQueue(), __func__, this,
&MediaSourceReader::CompleteSeekAndDoAudioRequest,
&MediaSourceReader::CompleteSeekAndRejectAudioPromise));
return;
}
@ -277,13 +260,15 @@ MediaSourceReader::RequestVideoData(bool aSkipToNextKeyframe, int64_t aTimeThres
mVideoPromise.Reject(CANCELED, __func__);
return p;
}
MOZ_RELEASE_ASSERT(!mSeekRequest.Exists());
SwitchReaderResult ret = SwitchVideoReader(mLastVideoTime);
switch (ret) {
case READER_NEW:
mVideoReader->Seek(mLastVideoTime, 0)
->Then(GetTaskQueue(), __func__, this,
&MediaSourceReader::RequestVideoDataComplete,
&MediaSourceReader::RequestVideoDataFailed);
mSeekRequest.Begin(mVideoReader->Seek(mLastVideoTime, 0)
->RefableThen(GetTaskQueue(), __func__, this,
&MediaSourceReader::CompleteSeekAndDoVideoRequest,
&MediaSourceReader::CompleteSeekAndRejectVideoPromise));
break;
case READER_ERROR:
if (mLastVideoTime) {
@ -299,17 +284,6 @@ MediaSourceReader::RequestVideoData(bool aSkipToNextKeyframe, int64_t aTimeThres
return p;
}
void
MediaSourceReader::RequestVideoDataComplete(int64_t aTime)
{
if (IsSeeking()) {
MSE_DEBUG("MediaSourceReader(%p)::RequestVideoDataComplete called mid-seek. Rejecting.", this);
MOZ_ASSERT(mVideoPromise.IsEmpty()); // Already rejected in ::Seek().
return;
}
DoVideoRequest();
}
void
MediaSourceReader::DoVideoRequest()
{
@ -319,12 +293,6 @@ MediaSourceReader::DoVideoRequest()
&MediaSourceReader::OnVideoNotDecoded));
}
void
MediaSourceReader::RequestVideoDataFailed(nsresult aResult)
{
mVideoPromise.Reject(DECODE_ERROR, __func__);
}
void
MediaSourceReader::OnVideoDecoded(VideoData* aSample)
{
@ -372,10 +340,10 @@ MediaSourceReader::OnVideoNotDecoded(NotDecodedReason aReason)
// EOS_FUZZ_US to allow for the fact that our end time can be inaccurate due to bug
// 1065207.
if (SwitchVideoReader(mLastVideoTime, EOS_FUZZ_US) == READER_NEW) {
mVideoReader->Seek(mLastVideoTime, 0)
->Then(GetTaskQueue(), __func__, this,
&MediaSourceReader::RequestVideoDataComplete,
&MediaSourceReader::RequestVideoDataFailed);
mSeekRequest.Begin(mVideoReader->Seek(mLastVideoTime, 0)
->RefableThen(GetTaskQueue(), __func__, this,
&MediaSourceReader::CompleteSeekAndDoVideoRequest,
&MediaSourceReader::CompleteSeekAndRejectVideoPromise));
return;
}
@ -702,6 +670,10 @@ MediaSourceReader::Seek(int64_t aTime, int64_t aIgnored /* Used only for ogg whi
mAudioPromise.RejectIfExists(CANCELED, __func__);
mVideoPromise.RejectIfExists(CANCELED, __func__);
// Finally, if we were midway seeking a new reader to find a sample, abandon
// that too.
mSeekRequest.DisconnectIfExists();
// Store pending seek target in case the track buffers don't contain
// the desired time and we delay doing the seek.
mPendingSeekTime = aTime;
@ -720,27 +692,22 @@ MediaSourceReader::CancelSeek()
{
MOZ_ASSERT(OnDecodeThread());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
if (mWaitingForSeekData) {
mSeekPromise.Reject(NS_OK, __func__);
mWaitingForSeekData = false;
mPendingSeekTime = -1;
} else if (mVideoIsSeeking) {
// NB: Currently all readers have sync Seeks(), so this is a no-op.
mVideoReader->CancelSeek();
} else if (mAudioIsSeeking) {
// NB: Currently all readers have sync Seeks(), so this is a no-op.
mWaitingForSeekData = false;
mPendingSeekTime = -1;
mSeekRequest.DisconnectIfExists();
if (mAudioReader) {
mAudioReader->CancelSeek();
} else {
MOZ_ASSERT(mSeekPromise.IsEmpty());
}
if (mVideoReader) {
mVideoReader->CancelSeek();
}
mSeekPromise.RejectIfExists(NS_OK, __func__);
}
void
MediaSourceReader::OnVideoSeekCompleted(int64_t aTime)
{
MOZ_ASSERT(mVideoIsSeeking);
MOZ_ASSERT(!mAudioIsSeeking);
mVideoIsSeeking = false;
mSeekRequest.Complete();
if (mAudioTrack) {
mPendingSeekTime = aTime;
@ -754,23 +721,18 @@ MediaSourceReader::OnVideoSeekCompleted(int64_t aTime)
void
MediaSourceReader::DoAudioSeek()
{
mAudioIsSeeking = true;
SwitchAudioReader(mPendingSeekTime);
mAudioReader->Seek(mPendingSeekTime, 0)
->Then(GetTaskQueue(), __func__, this,
&MediaSourceReader::OnAudioSeekCompleted,
&MediaSourceReader::OnSeekFailed);
mSeekRequest.Begin(mAudioReader->Seek(mPendingSeekTime, 0)
->RefableThen(GetTaskQueue(), __func__, this,
&MediaSourceReader::OnAudioSeekCompleted,
&MediaSourceReader::OnSeekFailed));
MSE_DEBUG("MediaSourceReader(%p)::DoAudioSeek reader=%p", this, mAudioReader.get());
}
void
MediaSourceReader::OnAudioSeekCompleted(int64_t aTime)
{
mPendingSeekTime = aTime;
MOZ_ASSERT(mAudioIsSeeking);
MOZ_ASSERT(!mVideoIsSeeking);
mAudioIsSeeking = false;
mSeekRequest.Complete();
mPendingSeekTime = -1;
mSeekPromise.Resolve(aTime, __func__);
}
@ -778,18 +740,7 @@ MediaSourceReader::OnAudioSeekCompleted(int64_t aTime)
void
MediaSourceReader::OnSeekFailed(nsresult aResult)
{
MOZ_ASSERT(mVideoIsSeeking || mAudioIsSeeking);
if (mVideoIsSeeking) {
MOZ_ASSERT(!mAudioIsSeeking);
mVideoIsSeeking = false;
}
if (mAudioIsSeeking) {
MOZ_ASSERT(!mVideoIsSeeking);
mAudioIsSeeking = false;
}
mSeekRequest.Complete();
mPendingSeekTime = -1;
mSeekPromise.Reject(aResult, __func__);
}
@ -828,12 +779,11 @@ MediaSourceReader::AttemptSeek()
void
MediaSourceReader::DoVideoSeek()
{
mVideoIsSeeking = true;
SwitchVideoReader(mPendingSeekTime);
mVideoReader->Seek(mPendingSeekTime, 0)
->Then(GetTaskQueue(), __func__, this,
&MediaSourceReader::OnVideoSeekCompleted,
&MediaSourceReader::OnSeekFailed);
mSeekRequest.Begin(mVideoReader->Seek(mPendingSeekTime, 0)
->RefableThen(GetTaskQueue(), __func__, this,
&MediaSourceReader::OnVideoSeekCompleted,
&MediaSourceReader::OnSeekFailed));
MSE_DEBUG("MediaSourceReader(%p)::DoVideoSeek reader=%p", this, mVideoReader.get());
}

View File

@ -163,10 +163,30 @@ private:
void DoAudioRequest();
void DoVideoRequest();
void RequestAudioDataComplete(int64_t aTime);
void RequestAudioDataFailed(nsresult aResult);
void RequestVideoDataComplete(int64_t aTime);
void RequestVideoDataFailed(nsresult aResult);
void CompleteSeekAndDoAudioRequest()
{
mSeekRequest.Complete();
DoAudioRequest();
}
void CompleteSeekAndDoVideoRequest()
{
mSeekRequest.Complete();
DoVideoRequest();
}
void CompleteSeekAndRejectAudioPromise()
{
mSeekRequest.Complete();
mAudioPromise.Reject(DECODE_ERROR, __func__);
}
void CompleteSeekAndRejectVideoPromise()
{
mSeekRequest.Complete();
mVideoPromise.Reject(DECODE_ERROR, __func__);
}
// Will reject the MediaPromise with END_OF_STREAM if mediasource has ended
// or with WAIT_FOR_DATA otherwise.
void CheckForWaitOrEndOfStream(MediaData::Type aType, int64_t aTime /* microseconds */);
@ -211,13 +231,13 @@ private:
int64_t mLastAudioTime;
int64_t mLastVideoTime;
MediaPromiseConsumerHolder<SeekPromise> mSeekRequest;
MediaPromiseHolder<SeekPromise> mSeekPromise;
// Temporary seek information while we wait for the data
// to be added to the track buffer.
MediaPromiseHolder<SeekPromise> mSeekPromise;
int64_t mPendingSeekTime;
bool mWaitingForSeekData;
bool mAudioIsSeeking;
bool mVideoIsSeeking;
int64_t mTimeThreshold;
bool mDropAudioBeforeThreshold;