Bug 1280036: don't create video frame before seek target. r?jya
MozReview-Commit-ID: 5idJj2r2d6E
--- a/dom/media/platforms/wmf/WMFMediaDataDecoder.cpp
+++ b/dom/media/platforms/wmf/WMFMediaDataDecoder.cpp
@@ -231,9 +231,24 @@ WMFMediaDataDecoder::ConfigurationChange
void
WMFMediaDataDecoder::ProcessConfigurationChanged(UniquePtr<TrackInfo>&& aConfig)
{
if (mMFTManager) {
mMFTManager->ConfigurationChanged(*aConfig);
}
}
+void
+WMFMediaDataDecoder::SetSeekThreshold(const media::TimeUnit& aTime)
+{
+ MOZ_ASSERT(mCallback->OnReaderTaskQueue());
+ MOZ_DIAGNOSTIC_ASSERT(!mIsShutDown);
+
+ RefPtr<WMFMediaDataDecoder> self = this;
+ nsCOMPtr<nsIRunnable> runnable =
+ NS_NewRunnableFunction([self, aTime]() {
+ media::TimeUnit threshold = aTime;
+ self->mMFTManager->SetSeekThreshold(threshold);
+ });
+ mTaskQueue->Dispatch(runnable.forget());
+}
+
} // namespace mozilla
--- a/dom/media/platforms/wmf/WMFMediaDataDecoder.h
+++ b/dom/media/platforms/wmf/WMFMediaDataDecoder.h
@@ -32,17 +32,20 @@ public:
// or until no more is able to be produced.
// Returns S_OK on success, or MF_E_TRANSFORM_NEED_MORE_INPUT if there's not
// enough data to produce more output. If this returns a failure code other
// than MF_E_TRANSFORM_NEED_MORE_INPUT, an error will be reported to the
// MP4Reader.
virtual HRESULT Output(int64_t aStreamOffset,
RefPtr<MediaData>& aOutput) = 0;
- void Flush() { mDecoder->Flush(); }
+ void Flush() {
+ mDecoder->Flush();
+ mSeekTargetThreshold.reset();
+ }
void Drain()
{
if (FAILED(mDecoder->SendMFTMessage(MFT_MESSAGE_COMMAND_DRAIN, 0))) {
NS_WARNING("Failed to send DRAIN command to MFT");
}
}
@@ -52,19 +55,25 @@ public:
virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const { return false; }
virtual TrackInfo::TrackType GetType() = 0;
virtual void ConfigurationChanged(const TrackInfo& aConfig) {}
virtual const char* GetDescriptionName() const = 0;
+ virtual void SetSeekThreshold(const media::TimeUnit& aTime) {
+ mSeekTargetThreshold = Some(aTime);
+ }
+
protected:
// IMFTransform wrapper that performs the decoding.
RefPtr<MFTDecoder> mDecoder;
+
+ Maybe<media::TimeUnit> mSeekTargetThreshold;
};
// Decodes audio and video using Windows Media Foundation. Samples are decoded
// using the MFTDecoder created by the MFTManager. This class implements
// the higher-level logic that drives mapping the MFT to the async
// MediaDataDecoder interface. The specifics of decoding the exact stream
// type are handled by MFTManager and the MFTDecoder it creates.
class WMFMediaDataDecoder : public MediaDataDecoder {
@@ -88,16 +97,18 @@ public:
nsresult ConfigurationChanged(const TrackInfo& aConfig) override;
const char* GetDescriptionName() const override
{
return mMFTManager ? mMFTManager->GetDescriptionName() : "";
}
+ virtual void SetSeekThreshold(const media::TimeUnit& aTime) override;
+
private:
// Called on the task queue. Inserts the sample into the decoder, and
// extracts output if available.
void ProcessDecode(MediaRawData* aSample);
// Called on the task queue. Extracts output if available, and delivers
// it to the reader. Called after ProcessDecode() and ProcessDrain().
--- a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
+++ b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
@@ -784,16 +784,30 @@ WMFVideoMFTManager::Output(int64_t aStre
++mNullOutputCount;
if (mNullOutputCount > 250) {
LOG("Excessive Video MFTDecoder returning success but no output; giving up");
mGotExcessiveNullOutput = true;
return E_FAIL;
}
continue;
}
+ if (mSeekTargetThreshold.isSome()) {
+ media::TimeUnit pts = GetSampleTime(sample);
+ if (!pts.IsValid()) {
+ return E_FAIL;
+ }
+ if (pts < mSeekTargetThreshold.ref()) {
+ LOG("Dropping video frame which pts is smaller than seek target.");
+ // It is necessary to clear the pointer to release the previous output
+ // buffer.
+ sample = nullptr;
+ continue;
+ }
+ mSeekTargetThreshold.reset();
+ }
break;
}
// Else unexpected error, assert, and bail.
NS_WARNING("WMFVideoMFTManager::Output() unexpected error");
return hr;
}
RefPtr<VideoData> frame;
@@ -833,9 +847,14 @@ WMFVideoMFTManager::IsHardwareAccelerate
void
WMFVideoMFTManager::ConfigurationChanged(const TrackInfo& aConfig)
{
MOZ_ASSERT(aConfig.GetAsVideoInfo());
mVideoInfo = *aConfig.GetAsVideoInfo();
mImageSize = mVideoInfo.mImage;
}
+void
+WMFVideoMFTManager::SetSeekThreshold(const media::TimeUnit& aTime)
+{
+}
+
} // namespace mozilla
--- a/dom/media/platforms/wmf/WMFVideoMFTManager.h
+++ b/dom/media/platforms/wmf/WMFVideoMFTManager.h
@@ -44,16 +44,18 @@ public:
const char* GetDescriptionName() const override
{
nsCString failureReason;
return IsHardwareAccelerated(failureReason)
? "wmf hardware video decoder" : "wmf software video decoder";
}
+ void SetSeekThreshold(const media::TimeUnit& aTime) override;
+
private:
bool InitializeDXVA(bool aForceD3D9);
bool InitInternal(bool aForceD3D9);
HRESULT ConfigureVideoFrameGeometry();