From 20853d0607ed90f23e744a1297500d8750060eef Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Wed, 30 Nov 2016 01:42:50 +1100 Subject: [PATCH] Bug 1319992: P3. Remove no longer used seeking argument. r=jwwang MozReview-Commit-ID: 9Oc0SHX0Rw2 --HG-- extra : rebase_source : 845ab6daa4414e57d5ce02dee1424df29d3b962d --- dom/media/MediaDecoderReader.h | 6 +- dom/media/MediaDecoderReaderWrapper.cpp | 7 +- dom/media/MediaDecoderReaderWrapper.h | 3 +- dom/media/MediaDecoderStateMachine.cpp | 2 +- dom/media/MediaFormatReader.cpp | 2 +- dom/media/MediaFormatReader.h | 3 +- dom/media/NextFrameSeekTask.cpp | 327 ++++++++++++++++++++++ dom/media/NextFrameSeekTask.h | 89 ++++++ dom/media/SeekTask.h | 117 ++++++++ dom/media/android/AndroidMediaReader.cpp | 2 +- dom/media/android/AndroidMediaReader.h | 2 +- dom/media/directshow/DirectShowReader.cpp | 2 +- dom/media/directshow/DirectShowReader.h | 3 +- 13 files changed, 546 insertions(+), 19 deletions(-) create mode 100644 dom/media/NextFrameSeekTask.cpp create mode 100644 dom/media/NextFrameSeekTask.h create mode 100644 dom/media/SeekTask.h diff --git a/dom/media/MediaDecoderReader.h b/dom/media/MediaDecoderReader.h index 05f62a54db73..55240e653def 100644 --- a/dom/media/MediaDecoderReader.h +++ b/dom/media/MediaDecoderReader.h @@ -151,10 +151,8 @@ public: // ReadUpdatedMetadata will always be called once ReadMetadata has succeeded. virtual void ReadUpdatedMetadata(MediaInfo* aInfo) {} - // Moves the decode head to aTime microseconds. aEndTime denotes the end - // time of the media in usecs. This is only needed for OggReader, and should - // probably be removed somehow. - virtual RefPtr Seek(const SeekTarget& aTarget, int64_t aEndTime) = 0; + // Moves the decode head to aTime microseconds. + virtual RefPtr Seek(const SeekTarget& aTarget) = 0; virtual void SetCDMProxy(CDMProxy* aProxy) {} diff --git a/dom/media/MediaDecoderReaderWrapper.cpp b/dom/media/MediaDecoderReaderWrapper.cpp index c73ea018e6e1..a0ab6d35181d 100644 --- a/dom/media/MediaDecoderReaderWrapper.cpp +++ b/dom/media/MediaDecoderReaderWrapper.cpp @@ -121,16 +121,15 @@ MediaDecoderReaderWrapper::IsWaitingVideoData() const } RefPtr -MediaDecoderReaderWrapper::Seek(const SeekTarget& aTarget, - const media::TimeUnit& aEndTime) +MediaDecoderReaderWrapper::Seek(const SeekTarget& aTarget) { MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); SeekTarget adjustedTarget = aTarget; adjustedTarget.SetTime(adjustedTarget.GetTime() + StartTime()); - return InvokeAsync( + return InvokeAsync( mReader->OwnerThread(), mReader.get(), __func__, &MediaDecoderReader::Seek, - Move(adjustedTarget), aEndTime.ToMicroseconds()); + Move(adjustedTarget)); } void diff --git a/dom/media/MediaDecoderReaderWrapper.h b/dom/media/MediaDecoderReaderWrapper.h index 92741d06da73..e046b6516660 100644 --- a/dom/media/MediaDecoderReaderWrapper.h +++ b/dom/media/MediaDecoderReaderWrapper.h @@ -67,8 +67,7 @@ public: bool IsWaitingAudioData() const; bool IsWaitingVideoData() const; - RefPtr Seek(const SeekTarget& aTarget, - const media::TimeUnit& aEndTime); + RefPtr Seek(const SeekTarget& aTarget); RefPtr Shutdown(); void ReleaseResources(); diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index 1e426c428fd2..c0e5e7dbbc33 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -1013,7 +1013,7 @@ private: void DoSeek() override { // Request the demuxer to perform seek. - mSeekRequest.Begin(Reader()->Seek(mSeekJob.mTarget.ref(), mMaster->Duration()) + mSeekRequest.Begin(Reader()->Seek(mSeekJob.mTarget.ref()) ->Then(OwnerThread(), __func__, [this] (media::TimeUnit aUnit) { OnSeekResolved(aUnit); diff --git a/dom/media/MediaFormatReader.cpp b/dom/media/MediaFormatReader.cpp index c9e8d023bf96..f11c028bca1c 100644 --- a/dom/media/MediaFormatReader.cpp +++ b/dom/media/MediaFormatReader.cpp @@ -2270,7 +2270,7 @@ MediaFormatReader::OnVideoSkipFailed(MediaTrackDemuxer::SkipFailureHolder aFailu } RefPtr -MediaFormatReader::Seek(const SeekTarget& aTarget, int64_t aUnused) +MediaFormatReader::Seek(const SeekTarget& aTarget) { MOZ_ASSERT(OnTaskQueue()); diff --git a/dom/media/MediaFormatReader.h b/dom/media/MediaFormatReader.h index 199cd1220897..e297016cfb98 100644 --- a/dom/media/MediaFormatReader.h +++ b/dom/media/MediaFormatReader.h @@ -46,8 +46,7 @@ public: void ReadUpdatedMetadata(MediaInfo* aInfo) override; - RefPtr - Seek(const SeekTarget& aTarget, int64_t aUnused) override; + RefPtr Seek(const SeekTarget& aTarget) override; protected: void NotifyDataArrived() override; diff --git a/dom/media/NextFrameSeekTask.cpp b/dom/media/NextFrameSeekTask.cpp new file mode 100644 index 000000000000..6a1ad3cea912 --- /dev/null +++ b/dom/media/NextFrameSeekTask.cpp @@ -0,0 +1,327 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "NextFrameSeekTask.h" +#include "MediaDecoderReaderWrapper.h" +#include "mozilla/AbstractThread.h" +#include "mozilla/Assertions.h" +#include "nsPrintfCString.h" + +namespace mozilla { + +extern LazyLogModule gMediaSampleLog; + +#define SAMPLE_LOG(x, ...) MOZ_LOG(gMediaSampleLog, LogLevel::Debug, \ + ("[NextFrameSeekTask] Decoder=%p " x, mDecoderID, ##__VA_ARGS__)) + +namespace media { + +NextFrameSeekTask::NextFrameSeekTask(const void* aDecoderID, + AbstractThread* aThread, + MediaDecoderReaderWrapper* aReader, + const SeekTarget& aTarget, + const MediaInfo& aInfo, + const media::TimeUnit& aDuration, + int64_t aCurrentTime, + MediaQueue& aAudioQueue, + MediaQueue& aVideoQueue) + : SeekTask(aDecoderID, aThread, aReader, aTarget) + , mAudioQueue(aAudioQueue) + , mVideoQueue(aVideoQueue) + , mCurrentTime(aCurrentTime) + , mDuration(aDuration) +{ + AssertOwnerThread(); + MOZ_ASSERT(aInfo.HasVideo()); +} + +NextFrameSeekTask::~NextFrameSeekTask() +{ + AssertOwnerThread(); + MOZ_ASSERT(mIsDiscarded); +} + +void +NextFrameSeekTask::Discard() +{ + AssertOwnerThread(); + + // Disconnect MDSM. + RejectIfExist(NS_ERROR_DOM_MEDIA_CANCELED, __func__); + + mIsDiscarded = true; +} + +int64_t +NextFrameSeekTask::CalculateNewCurrentTime() const +{ + AssertOwnerThread(); + + // The HTMLMediaElement.currentTime should be updated to the seek target + // which has been updated to the next frame's time. + return mTarget.GetTime().ToMicroseconds(); +} + +void +NextFrameSeekTask::HandleAudioDecoded(MediaData* aAudio) +{ + AssertOwnerThread(); + MOZ_ASSERT(aAudio); + MOZ_ASSERT(!mSeekTaskPromise.IsEmpty(), "Seek shouldn't be finished"); + + // The MDSM::mDecodedAudioEndTime will be updated once the whole SeekTask is + // resolved. + + SAMPLE_LOG("OnAudioDecoded [%lld,%lld]", aAudio->mTime, aAudio->GetEndTime()); + + // We accept any audio data here. + mSeekedAudioData = aAudio; + + MaybeFinishSeek(); +} + +void +NextFrameSeekTask::HandleVideoDecoded(MediaData* aVideo, TimeStamp aDecodeStart) +{ + AssertOwnerThread(); + MOZ_ASSERT(aVideo); + MOZ_ASSERT(!mSeekTaskPromise.IsEmpty(), "Seek shouldn't be finished"); + + // The MDSM::mDecodedVideoEndTime will be updated once the whole SeekTask is + // resolved. + + SAMPLE_LOG("OnVideoDecoded [%lld,%lld]", aVideo->mTime, aVideo->GetEndTime()); + + if (aVideo->mTime > mCurrentTime) { + mSeekedVideoData = aVideo; + } + + if (NeedMoreVideo()) { + RequestVideoData(); + return; + } + + MaybeFinishSeek(); +} + +void +NextFrameSeekTask::HandleNotDecoded(MediaData::Type aType, const MediaResult& aError) +{ + AssertOwnerThread(); + switch (aType) { + case MediaData::AUDIO_DATA: + { + MOZ_ASSERT(!mSeekTaskPromise.IsEmpty(), "Seek shouldn't be finished"); + + SAMPLE_LOG("OnAudioNotDecoded (aError=%u)", aError.Code()); + + // We don't really handle audio deocde error here. Let MDSM to trigger further + // audio decoding tasks if it needs to play audio, and MDSM will then receive + // the decoding state from MediaDecoderReader. + + MaybeFinishSeek(); + break; + } + case MediaData::VIDEO_DATA: + { + MOZ_ASSERT(!mSeekTaskPromise.IsEmpty(), "Seek shouldn't be finished"); + + SAMPLE_LOG("OnVideoNotDecoded (aError=%u)", aError.Code()); + + if (aError == NS_ERROR_DOM_MEDIA_END_OF_STREAM) { + mIsVideoQueueFinished = true; + } + + // Video seek not finished. + if (NeedMoreVideo()) { + switch (aError.Code()) { + case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA: + mReader->WaitForData(MediaData::VIDEO_DATA); + break; + case NS_ERROR_DOM_MEDIA_CANCELED: + RequestVideoData(); + break; + case NS_ERROR_DOM_MEDIA_END_OF_STREAM: + MOZ_ASSERT(false, "Shouldn't want more data for ended video."); + break; + default: + // Reject the promise since we can't finish video seek anyway. + RejectIfExist(aError, __func__); + break; + } + return; + } + + MaybeFinishSeek(); + break; + } + default: + MOZ_ASSERT_UNREACHABLE("We cannot handle RAW_DATA or NULL_DATA here."); + } +} + +void +NextFrameSeekTask::HandleAudioWaited(MediaData::Type aType) +{ + AssertOwnerThread(); + + // We don't make an audio decode request here, instead, let MDSM to + // trigger further audio decode tasks if MDSM itself needs to play audio. + MaybeFinishSeek(); +} + +void +NextFrameSeekTask::HandleVideoWaited(MediaData::Type aType) +{ + AssertOwnerThread(); + + if (NeedMoreVideo()) { + RequestVideoData(); + return; + } + MaybeFinishSeek(); +} + +void +NextFrameSeekTask::HandleNotWaited(const WaitForDataRejectValue& aRejection) +{ + AssertOwnerThread(); + + switch(aRejection.mType) { + case MediaData::AUDIO_DATA: + { + // We don't make an audio decode request here, instead, let MDSM to + // trigger further audio decode tasks if MDSM itself needs to play audio. + MaybeFinishSeek(); + break; + } + case MediaData::VIDEO_DATA: + { + if (NeedMoreVideo()) { + // Reject if we can't finish video seeking. + RejectIfExist(NS_ERROR_DOM_MEDIA_CANCELED, __func__); + return; + } + MaybeFinishSeek(); + break; + } + default: + MOZ_ASSERT_UNREACHABLE("We cannot handle RAW_DATA or NULL_DATA here."); + } +} + +/* + * 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 static void +DiscardFrames(MediaQueue& aQueue, const Function& aCompare) +{ + while(aQueue.GetSize() > 0) { + if (aCompare(aQueue.PeekFront()->mTime)) { + RefPtr releaseMe = aQueue.PopFront(); + continue; + } + break; + } +} + +RefPtr +NextFrameSeekTask::Seek() +{ + AssertOwnerThread(); + + auto currentTime = mCurrentTime; + DiscardFrames(mVideoQueue, [currentTime] (int64_t aSampleTime) { + return aSampleTime <= currentTime; + }); + + RefPtr promise = mSeekTaskPromise.Ensure(__func__); + if (!IsVideoRequestPending() && NeedMoreVideo()) { + RequestVideoData(); + } + MaybeFinishSeek(); // Might resolve mSeekTaskPromise and modify audio queue. + return promise; +} + +void +NextFrameSeekTask::RequestVideoData() +{ + AssertOwnerThread(); + mReader->RequestVideoData(false, media::TimeUnit()); +} + +bool +NextFrameSeekTask::NeedMoreVideo() const +{ + AssertOwnerThread(); + // Need to request video when we have none and video queue is not finished. + return mVideoQueue.GetSize() == 0 && + !mSeekedVideoData && + !mVideoQueue.IsFinished() && + !mIsVideoQueueFinished; +} + +bool +NextFrameSeekTask::IsVideoRequestPending() const +{ + AssertOwnerThread(); + return mReader->IsRequestingVideoData() || mReader->IsWaitingVideoData(); +} + +bool +NextFrameSeekTask::IsAudioSeekComplete() const +{ + AssertOwnerThread(); + // Don't finish seek until there are no pending requests. Otherwise, we might + // lose audio samples for the promise is resolved asynchronously. + return !mReader->IsRequestingAudioData() && !mReader->IsWaitingAudioData(); +} + +bool +NextFrameSeekTask::IsVideoSeekComplete() const +{ + AssertOwnerThread(); + // Don't finish seek until there are no pending requests. Otherwise, we might + // lose video samples for the promise is resolved asynchronously. + return !IsVideoRequestPending() && !NeedMoreVideo(); +} + +void +NextFrameSeekTask::MaybeFinishSeek() +{ + AssertOwnerThread(); + if (IsAudioSeekComplete() && IsVideoSeekComplete()) { + UpdateSeekTargetTime(); + + auto time = mTarget.GetTime().ToMicroseconds(); + DiscardFrames(mAudioQueue, [time] (int64_t aSampleTime) { + return aSampleTime < time; + }); + + Resolve(__func__); // Call to MDSM::SeekCompleted(); + } +} + +void +NextFrameSeekTask::UpdateSeekTargetTime() +{ + AssertOwnerThread(); + + RefPtr data = mVideoQueue.PeekFront(); + if (data) { + mTarget.SetTime(TimeUnit::FromMicroseconds(data->mTime)); + } else if (mSeekedVideoData) { + mTarget.SetTime(TimeUnit::FromMicroseconds(mSeekedVideoData->mTime)); + } else if (mIsVideoQueueFinished || mVideoQueue.AtEndOfStream()) { + mTarget.SetTime(mDuration); + } else { + MOZ_ASSERT(false, "No data!"); + } +} +} // namespace media +} // namespace mozilla diff --git a/dom/media/NextFrameSeekTask.h b/dom/media/NextFrameSeekTask.h new file mode 100644 index 000000000000..3b22bf221351 --- /dev/null +++ b/dom/media/NextFrameSeekTask.h @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef NEXTFRAME_SEEK_TASK_H +#define NEXTFRAME_SEEK_TASK_H + +#include "SeekTask.h" +#include "MediaDecoderReader.h" + +namespace mozilla { +namespace media { + +/* + * While invoking a NextFrameSeekTask, we don't know the seek target time, what + * we know is the media's currant position. We use the media's currant position + * to find out what the next frame is, by traversing through the video queue or + * asking the decoder to decode more video frames. Once we confirm the next + * frame, we then know the target time of the NextFrameSeekTask and we update it + * so that the MDSM will be able to update the media element's position. + */ + +class NextFrameSeekTask final : public SeekTask { +public: + NextFrameSeekTask(const void* aDecoderID, + AbstractThread* aThread, + MediaDecoderReaderWrapper* aReader, + const SeekTarget& aTarget, + const MediaInfo& aInfo, + const media::TimeUnit& aDuration, + int64_t aCurrentTime, + MediaQueue& aAudioQueue, + MediaQueue& aVideoQueue); + + void Discard() override; + + RefPtr Seek() override; + + int64_t CalculateNewCurrentTime() const override; + + void HandleAudioDecoded(MediaData* aAudio) override; + + void HandleVideoDecoded(MediaData* aVideo, TimeStamp aDecodeStart) override; + + void HandleNotDecoded(MediaData::Type aType, const MediaResult& aError) override; + + void HandleAudioWaited(MediaData::Type aType) override; + + void HandleVideoWaited(MediaData::Type aType) override; + + void HandleNotWaited(const WaitForDataRejectValue& aRejection) override; + + ~NextFrameSeekTask(); + + void RequestVideoData(); + + bool NeedMoreVideo() const; + + bool IsVideoRequestPending() const; + + bool IsAudioSeekComplete() const; + + bool IsVideoSeekComplete() const; + + void MaybeFinishSeek(); + + // Update the seek target's time before resolving this seek task, the updated + // time will be used in the MDSM::SeekCompleted() to update the MDSM's position. + void UpdateSeekTargetTime(); + + /* + * Data shared with MDSM. + */ + MediaQueue& mAudioQueue; + MediaQueue& mVideoQueue; + + /* + * Internal state. + */ + const int64_t mCurrentTime; + media::TimeUnit mDuration; +}; + +} // namespace media +} // namespace mozilla + +#endif /* NEXTFRAME_SEEK_TASK_H */ diff --git a/dom/media/SeekTask.h b/dom/media/SeekTask.h new file mode 100644 index 000000000000..f33cb956e977 --- /dev/null +++ b/dom/media/SeekTask.h @@ -0,0 +1,117 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef SEEK_TASK_H +#define SEEK_TASK_H + +#include "mozilla/MozPromise.h" +#include "MediaData.h" // For MediaData::Type. +#include "MediaDecoderReader.h" // For WaitForDataRejectValue. +#include "MediaResult.h" +#include "SeekTarget.h" + +namespace mozilla { + +class AbstractThread; +class MediaData; +class MediaDecoderReaderWrapper; + +namespace media { +class TimeUnit; +} + +struct SeekTaskResolveValue +{ + RefPtr mSeekedAudioData; + RefPtr mSeekedVideoData; + bool mIsAudioQueueFinished; + bool mIsVideoQueueFinished; +}; + +struct SeekTaskRejectValue +{ + SeekTaskRejectValue() + : mIsAudioQueueFinished(false) + , mIsVideoQueueFinished(false) + , mError(NS_ERROR_DOM_MEDIA_FATAL_ERR) + { + } + bool mIsAudioQueueFinished; + bool mIsVideoQueueFinished; + MediaResult mError; +}; + +class SeekTask { + + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SeekTask) + +public: + static const bool IsExclusive = true; + + using SeekTaskPromise = + MozPromise; + + virtual void Discard() = 0; + + virtual RefPtr Seek() = 0; + + virtual int64_t CalculateNewCurrentTime() const = 0; + + virtual void HandleAudioDecoded(MediaData* aAudio) = 0; + + virtual void HandleVideoDecoded(MediaData* aVideo, TimeStamp aDecodeStart) = 0; + + virtual void HandleNotDecoded(MediaData::Type aType, const MediaResult& aError) = 0; + + virtual void HandleAudioWaited(MediaData::Type aType) = 0; + + virtual void HandleVideoWaited(MediaData::Type aType) = 0; + + virtual void HandleNotWaited(const WaitForDataRejectValue& aRejection) = 0; + +protected: + SeekTask(const void* aDecoderID, + AbstractThread* aThread, + MediaDecoderReaderWrapper* aReader, + const SeekTarget& aTarget); + + virtual ~SeekTask(); + +public: + void Resolve(const char* aCallSite); + + void RejectIfExist(const MediaResult& aError, const char* aCallSite); + + void AssertOwnerThread() const; + + AbstractThread* OwnerThread() const; + + /* + * Data shared with MDSM. + */ + const void* mDecoderID; // For logging. + const RefPtr mOwnerThread; + const RefPtr mReader; + + /* + * Internal state. + */ + SeekTarget mTarget; + MozPromiseHolder mSeekTaskPromise; + bool mIsDiscarded; + + /* + * Information which are going to be returned to MDSM. + */ + RefPtr mSeekedAudioData; + RefPtr mSeekedVideoData; + bool mIsAudioQueueFinished; + bool mIsVideoQueueFinished; +}; + +} // namespace mozilla + +#endif /* SEEK_TASK_H */ diff --git a/dom/media/android/AndroidMediaReader.cpp b/dom/media/android/AndroidMediaReader.cpp index c98f741b6c98..cf21a6aab735 100644 --- a/dom/media/android/AndroidMediaReader.cpp +++ b/dom/media/android/AndroidMediaReader.cpp @@ -313,7 +313,7 @@ bool AndroidMediaReader::DecodeAudioData() } RefPtr -AndroidMediaReader::Seek(const SeekTarget& aTarget, int64_t aEndTime) +AndroidMediaReader::Seek(const SeekTarget& aTarget) { MOZ_ASSERT(OnTaskQueue()); diff --git a/dom/media/android/AndroidMediaReader.h b/dom/media/android/AndroidMediaReader.h index acf34bd675d8..d65b5089ce98 100644 --- a/dom/media/android/AndroidMediaReader.h +++ b/dom/media/android/AndroidMediaReader.h @@ -48,7 +48,7 @@ public: bool DecodeVideoFrame(bool &aKeyframeSkip, int64_t aTimeThreshold) override; nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) override; - RefPtr Seek(const SeekTarget& aTarget, int64_t aEndTime) override; + RefPtr Seek(const SeekTarget& aTarget) override; RefPtr Shutdown() override; diff --git a/dom/media/directshow/DirectShowReader.cpp b/dom/media/directshow/DirectShowReader.cpp index ba27548b60f8..04033739ea1c 100644 --- a/dom/media/directshow/DirectShowReader.cpp +++ b/dom/media/directshow/DirectShowReader.cpp @@ -320,7 +320,7 @@ DirectShowReader::DecodeVideoFrame(bool &aKeyframeSkip, } RefPtr -DirectShowReader::Seek(const SeekTarget& aTarget, int64_t aEndTime) +DirectShowReader::Seek(const SeekTarget& aTarget) { nsresult res = SeekInternal(aTarget.GetTime().ToMicroseconds()); if (NS_FAILED(res)) { diff --git a/dom/media/directshow/DirectShowReader.h b/dom/media/directshow/DirectShowReader.h index b165f0939190..4e314a819d84 100644 --- a/dom/media/directshow/DirectShowReader.h +++ b/dom/media/directshow/DirectShowReader.h @@ -57,8 +57,7 @@ public: nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) override; - RefPtr - Seek(const SeekTarget& aTarget, int64_t aEndTime) override; + RefPtr Seek(const SeekTarget& aTarget) override; static const GUID CLSID_MPEG_LAYER_3_DECODER_FILTER;