зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1283769
- don't discard audio samples until seek is completed. r=kaku
MozReview-Commit-ID: AirmL0fETNL --HG-- extra : rebase_source : 194659f4eadb21604ce5dc8ee3aa151b16b3d154
This commit is contained in:
Родитель
fedd3f734d
Коммит
9d86d0a443
|
@ -43,13 +43,13 @@ NextFrameSeekTask::NextFrameSeekTask(const void* aDecoderID,
|
|||
SeekJob&& aSeekJob,
|
||||
const MediaInfo& aInfo,
|
||||
const media::TimeUnit& aDuration,
|
||||
int64_t aCurrentMediaTime,
|
||||
int64_t aCurrentTime,
|
||||
MediaQueue<MediaData>& aAudioQueue,
|
||||
MediaQueue<MediaData>& aVideoQueue)
|
||||
: SeekTask(aDecoderID, aThread, aReader, Move(aSeekJob))
|
||||
, mAudioQueue(aAudioQueue)
|
||||
, mVideoQueue(aVideoQueue)
|
||||
, mCurrentTimeBeforeSeek(aCurrentMediaTime)
|
||||
, mCurrentTime(aCurrentTime)
|
||||
, mDuration(aDuration)
|
||||
{
|
||||
AssertOwnerThread();
|
||||
|
@ -89,23 +89,16 @@ NextFrameSeekTask::NeedToResetMDSM() const
|
|||
return false;
|
||||
}
|
||||
|
||||
static int64_t
|
||||
FindNextFrame(MediaQueue<MediaData>& aQueue, int64_t aTime)
|
||||
/*
|
||||
* Remove samples from the queue until aCompare() returns false.
|
||||
* aCompare A function object with the signature bool(int64_t) which returns
|
||||
* true for samples that should be removed.
|
||||
*/
|
||||
template <typename Function> static void
|
||||
DiscardFrames(MediaQueue<MediaData>& aQueue, const Function& aCompare)
|
||||
{
|
||||
AutoTArray<RefPtr<MediaData>, 16> frames;
|
||||
aQueue.GetFirstElements(aQueue.GetSize(), &frames);
|
||||
for (auto&& frame : frames) {
|
||||
if (frame->mTime > aTime) {
|
||||
return frame->mTime;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
DropFramesUntil(MediaQueue<MediaData>& aQueue, int64_t aTime) {
|
||||
while (aQueue.GetSize() > 0) {
|
||||
if (aQueue.PeekFront()->mTime < aTime) {
|
||||
while(aQueue.GetSize() > 0) {
|
||||
if (aCompare(aQueue.PeekFront()->mTime)) {
|
||||
RefPtr<MediaData> releaseMe = aQueue.PopFront();
|
||||
continue;
|
||||
}
|
||||
|
@ -113,53 +106,22 @@ DropFramesUntil(MediaQueue<MediaData>& aQueue, int64_t aTime) {
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DropAllFrames(MediaQueue<MediaData>& aQueue) {
|
||||
while(aQueue.GetSize() > 0) {
|
||||
RefPtr<MediaData> releaseMe = aQueue.PopFront();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DropAllMediaDataBeforeCurrentPosition(MediaQueue<MediaData>& aAudioQueue,
|
||||
MediaQueue<MediaData>& aVideoQueue,
|
||||
int64_t const aCurrentTimeBeforeSeek)
|
||||
{
|
||||
// Drop all audio/video data before GetMediaTime();
|
||||
int64_t newPos = FindNextFrame(aVideoQueue, aCurrentTimeBeforeSeek);
|
||||
if (newPos < 0) {
|
||||
// In this case, we cannot find the next frame in the video queue, so
|
||||
// the NextFrameSeekTask needs to decode video data.
|
||||
DropAllFrames(aVideoQueue);
|
||||
if (aVideoQueue.IsFinished()) {
|
||||
DropAllFrames(aAudioQueue);
|
||||
}
|
||||
} else {
|
||||
DropFramesUntil(aVideoQueue, newPos);
|
||||
DropFramesUntil(aAudioQueue, newPos);
|
||||
// So now, the 1st data in the video queue should be the target of the
|
||||
// NextFrameSeekTask.
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<NextFrameSeekTask::SeekTaskPromise>
|
||||
NextFrameSeekTask::Seek(const media::TimeUnit&)
|
||||
{
|
||||
AssertOwnerThread();
|
||||
|
||||
DropAllMediaDataBeforeCurrentPosition(mAudioQueue, mVideoQueue,
|
||||
mCurrentTimeBeforeSeek);
|
||||
auto currentTime = mCurrentTime;
|
||||
DiscardFrames(mVideoQueue, [currentTime] (int64_t aSampleTime) {
|
||||
return aSampleTime <= currentTime;
|
||||
});
|
||||
|
||||
RefPtr<SeekTaskPromise> promise = mSeekTaskPromise.Ensure(__func__);
|
||||
if (NeedMoreVideo()) {
|
||||
EnsureVideoDecodeTaskQueued();
|
||||
}
|
||||
if (!IsAudioSeekComplete() || !IsVideoSeekComplete()) {
|
||||
return mSeekTaskPromise.Ensure(__func__);
|
||||
}
|
||||
|
||||
UpdateSeekTargetTime();
|
||||
SeekTaskResolveValue val = {}; // Zero-initialize data members.
|
||||
return SeekTask::SeekTaskPromise::CreateAndResolve(val, __func__);
|
||||
MaybeFinishSeek(); // Might resolve mSeekTaskPromise and modify audio queue.
|
||||
return promise;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -249,6 +211,12 @@ NextFrameSeekTask::MaybeFinishSeek()
|
|||
AssertOwnerThread();
|
||||
if (IsAudioSeekComplete() && IsVideoSeekComplete()) {
|
||||
UpdateSeekTargetTime();
|
||||
|
||||
auto time = mSeekJob.mTarget.GetTime().ToMicroseconds();
|
||||
DiscardFrames(mAudioQueue, [time] (int64_t aSampleTime) {
|
||||
return aSampleTime < time;
|
||||
});
|
||||
|
||||
Resolve(__func__); // Call to MDSM::SeekCompleted();
|
||||
}
|
||||
}
|
||||
|
@ -304,7 +272,7 @@ NextFrameSeekTask::OnVideoDecoded(MediaData* aVideoSample)
|
|||
aVideoSample->GetEndTime(),
|
||||
aVideoSample->mDiscontinuity);
|
||||
|
||||
if (aVideoSample->mTime > mCurrentTimeBeforeSeek) {
|
||||
if (aVideoSample->mTime > mCurrentTime) {
|
||||
mSeekedVideoData = aVideoSample;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ public:
|
|||
SeekJob&& aSeekJob,
|
||||
const MediaInfo& aInfo,
|
||||
const media::TimeUnit& aDuration,
|
||||
int64_t aCurrentMediaTime,
|
||||
int64_t aCurrentTime,
|
||||
MediaQueue<MediaData>& aAudioQueue,
|
||||
MediaQueue<MediaData>& aVideoQueue);
|
||||
|
||||
|
@ -86,7 +86,7 @@ private:
|
|||
/*
|
||||
* Internal state.
|
||||
*/
|
||||
const int64_t mCurrentTimeBeforeSeek;
|
||||
const int64_t mCurrentTime;
|
||||
media::TimeUnit mDuration;
|
||||
|
||||
MediaEventListener mAudioCallback;
|
||||
|
|
Загрузка…
Ссылка в новой задаче