void MediaSourceReader::OnAudioNotDecoded(NotDecodedReason aReason) { MOZ_DIAGNOSTIC_ASSERT(!IsSeeking()); mAudioRequest.Complete(); MSE_DEBUG("aReason=%u IsEnded: %d", aReason, IsEnded()); if (aReason == CANCELED) { mAudioPromise.Reject(CANCELED, __func__); return; } // If End of stream. Force switching past this stream to another reader by // switching to the end of the buffered range. int64_t lastAudioTime = mLastAudioTime; if (aReason == END_OF_STREAM && mAudioSourceDecoder) { AdjustEndTime(&mLastAudioTime, mAudioSourceDecoder); } SwitchSourceResult result = SwitchAudioSource(&mLastAudioTime); // See if we can find a different source that can pick up where we left off. if (result == SOURCE_NEW) { GetAudioReader()->ResetDecode(); mAudioSeekRequest.Begin(GetAudioReader()->Seek(GetReaderAudioTime(mLastAudioTime), 0) ->RefableThen(GetTaskQueue(), __func__, this, &MediaSourceReader::CompleteAudioSeekAndDoRequest, &MediaSourceReader::CompleteAudioSeekAndRejectPromise)); return; } // If we got a DECODE_ERROR and we have buffered data in the requested range // then it must be a genuine decoding error. // Otherwise we can assume that the data was either evicted or explicitely // removed from the source buffer and we should wait for new data. if (aReason == DECODE_ERROR && result != SOURCE_NONE) { mAudioPromise.Reject(DECODE_ERROR, __func__); return; } CheckForWaitOrEndOfStream(MediaData::AUDIO_DATA, mLastAudioTime); if (mLastAudioTime - lastAudioTime >= EOS_FUZZ_US) { // No decoders are available to switch to. We will re-attempt from the last // failing position. mLastAudioTime = lastAudioTime; } }
nsRefPtr<MediaDecoderReader::AudioDataPromise> MediaSourceReader::RequestAudioData() { MOZ_ASSERT(OnTaskQueue()); MOZ_DIAGNOSTIC_ASSERT(mSeekPromise.IsEmpty(), "No sample requests allowed while seeking"); MOZ_DIAGNOSTIC_ASSERT(mAudioPromise.IsEmpty(), "No duplicate sample requests"); nsRefPtr<AudioDataPromise> p = mAudioPromise.Ensure(__func__); MSE_DEBUGV("mLastAudioTime=%lld", mLastAudioTime); if (!mAudioTrack) { MSE_DEBUG("called with no audio track"); mAudioPromise.Reject(DECODE_ERROR, __func__); return p; } if (IsSeeking()) { MSE_DEBUG("called mid-seek. Rejecting."); mAudioPromise.Reject(CANCELED, __func__); return p; } MOZ_DIAGNOSTIC_ASSERT(!mAudioSeekRequest.Exists()); SwitchSourceResult ret = SwitchAudioSource(&mLastAudioTime); switch (ret) { case SOURCE_NEW: GetAudioReader()->ResetDecode(); mAudioSeekRequest.Begin(GetAudioReader()->Seek(GetReaderAudioTime(mLastAudioTime), 0) ->Then(OwnerThread(), __func__, this, &MediaSourceReader::CompleteAudioSeekAndDoRequest, &MediaSourceReader::CompleteAudioSeekAndRejectPromise)); break; case SOURCE_NONE: if (!mLastAudioTime) { // This is the first call to RequestAudioData. // Fallback to using decoder with earliest data. mAudioSourceDecoder = FirstDecoder(MediaData::AUDIO_DATA); } if (mLastAudioTime || !mAudioSourceDecoder) { CheckForWaitOrEndOfStream(MediaData::AUDIO_DATA, mLastAudioTime); break; } // Fallback to getting first frame from first decoder. default: DoAudioRequest(); break; } return p; }
void MediaSourceReader::DoAudioSeek() { int64_t seekTime = mPendingSeekTime; if (mSeekToEnd) { seekTime = LastSampleTime(MediaData::AUDIO_DATA); } if (SwitchAudioSource(&seekTime) == SOURCE_NONE) { // Data we need got evicted since the last time we checked for data // availability. Abort current seek attempt. mWaitingForSeekData = true; return; } GetAudioReader()->ResetDecode(); mAudioSeekRequest.Begin(GetAudioReader()->Seek(GetReaderAudioTime(seekTime), 0) ->RefableThen(GetTaskQueue(), __func__, this, &MediaSourceReader::OnAudioSeekCompleted, &MediaSourceReader::OnAudioSeekFailed)); MSE_DEBUG("reader=%p", GetAudioReader()); }