nsRefPtr<MediaDecoderReader::SeekPromise> MediaSourceReader::Seek(int64_t aTime, int64_t aIgnored /* Used only for ogg which is non-MSE */) { MSE_DEBUG("Seek(aTime=%lld, aEnd=%lld, aCurrent=%lld)", aTime); MOZ_DIAGNOSTIC_ASSERT(mSeekPromise.IsEmpty()); MOZ_DIAGNOSTIC_ASSERT(mAudioPromise.IsEmpty()); MOZ_DIAGNOSTIC_ASSERT(mVideoPromise.IsEmpty()); nsRefPtr<SeekPromise> p = mSeekPromise.Ensure(__func__); if (IsShutdown()) { mSeekPromise.Reject(NS_ERROR_FAILURE, __func__); return p; } // Store pending seek target in case the track buffers don't contain // the desired time and we delay doing the seek. mPendingSeekTime = aTime; { ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); mWaitingForSeekData = true; mDropAudioBeforeThreshold = false; mDropVideoBeforeThreshold = false; mTimeThreshold = 0; } AttemptSeek(); return p; }
nsRefPtr<MediaDecoderReader::SeekPromise> MediaSourceReader::Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime) { MSE_DEBUG("MediaSourceReader(%p)::Seek(aTime=%lld, aStart=%lld, aEnd=%lld, aCurrent=%lld)", this, aTime, aStartTime, aEndTime, aCurrentTime); mSeekPromise.RejectIfExists(NS_OK, __func__); nsRefPtr<SeekPromise> p = mSeekPromise.Ensure(__func__); if (IsShutdown()) { mSeekPromise.Reject(NS_ERROR_FAILURE, __func__); return p; } // Store pending seek target in case the track buffers don't contain // the desired time and we delay doing the seek. mPendingSeekTime = aTime; mPendingStartTime = aStartTime; mPendingEndTime = aEndTime; mPendingCurrentTime = aCurrentTime; // Only increment the number of expected OnSeekCompleted // notifications if we weren't already waiting for AttemptSeek // to complete (and they would have been accounted for already). { ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); if (!mWaitingForSeekData) { mWaitingForSeekData = true; if (mAudioTrack) { mPendingSeeks++; } if (mVideoTrack) { mPendingSeeks++; } } } AttemptSeek(); return p; }
void ProgramData::Parse(const std::string& Source) { auto MovePointerLambda = [&](Instruction::value_type x) { if (Text.back() == Instruction::Type::MovePointer) { Text.back().Value += x; // Remove instructions that have no effect if (!Text.back().Value) Text.pop_back(); } else { Text.emplace_back(Instruction::Type::MovePointer, x); } }; auto AdditionLambda = [&](Instruction::value_type x) { if (Text.back() == Instruction::Type::Addition) { Text.back().Value += x; // Remove instructions that have no effect if (!Text.back().Value) Text.pop_back(); } else if (Text.back() == Instruction::Type::Reset && Text.back().Value == 1 && Text.back().Offset == 0) { Text.pop_back(); Text.emplace_back(Instruction::Type::Set, x); } else if (Text.back() == Instruction::Type::Set) { Text.back().Value += x; } else { Text.emplace_back(Instruction::Type::Addition, x); } }; for (auto Char : Source) { switch (Char) { case '>': MovePointerLambda(1); break; case '<': MovePointerLambda(-1); break; case '+': AdditionLambda(1); break; case '-': AdditionLambda(-1); break; case '.': Text.emplace_back(Instruction::Type::Output); break; case ',': Text.emplace_back(Instruction::Type::Input); break; case '[': Text.emplace_back(Instruction::Type::LoopStart); break; case ']': Instruction* const BeginPointer = [&] { auto Iterator = std::find(std::rbegin(Text), std::rend(Text), Instruction::Type::LoopStart); if (Iterator == std::rend(Text)) throw bf::exception::UnmatchedClose(); return &*Iterator; }(); Instruction* const EndPointer = std::data(Text) + std::size(Text); if (DropEmptyLoop(BeginPointer, EndPointer)) break; if (AttemptReset(BeginPointer, EndPointer)) break; if (AttemptSeek(BeginPointer, EndPointer)) break; if (AttemptMultiplication(BeginPointer, EndPointer)) break; Text.emplace_back(Instruction::Type::LoopEnd); break; } } }