diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:13:27 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:13:27 +0000 |
commit | 40a355a42d4a9444dc753c04c6608dade2f06a23 (patch) | |
tree | 871fc667d2de662f171103ce5ec067014ef85e61 /dom/media/platforms/wmf/MFMediaEngineVideoStream.cpp | |
parent | Adding upstream version 124.0.1. (diff) | |
download | firefox-upstream/125.0.1.tar.xz firefox-upstream/125.0.1.zip |
Adding upstream version 125.0.1.upstream/125.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/media/platforms/wmf/MFMediaEngineVideoStream.cpp')
-rw-r--r-- | dom/media/platforms/wmf/MFMediaEngineVideoStream.cpp | 108 |
1 files changed, 93 insertions, 15 deletions
diff --git a/dom/media/platforms/wmf/MFMediaEngineVideoStream.cpp b/dom/media/platforms/wmf/MFMediaEngineVideoStream.cpp index ca043478f0..0fedcd31b9 100644 --- a/dom/media/platforms/wmf/MFMediaEngineVideoStream.cpp +++ b/dom/media/platforms/wmf/MFMediaEngineVideoStream.cpp @@ -49,7 +49,7 @@ void MFMediaEngineVideoStream::SetKnowsCompositor( this]() { mKnowsCompositor = knowCompositor; LOG("Set SetKnowsCompositor=%p", mKnowsCompositor.get()); - ResolvePendingDrainPromiseIfNeeded(); + ResolvePendingPromisesIfNeeded(); })); } @@ -74,7 +74,7 @@ void MFMediaEngineVideoStream::SetDCompSurfaceHandle(HANDLE aDCompSurfaceHandle, } } LOG("Set DCompSurfaceHandle, handle=%p", mDCompSurfaceHandle); - ResolvePendingDrainPromiseIfNeeded(); + ResolvePendingPromisesIfNeeded(); })); } @@ -209,7 +209,7 @@ HRESULT MFMediaEngineVideoStream::CreateMediaType(const TrackInfo& aInfo, bool MFMediaEngineVideoStream::HasEnoughRawData() const { // If more than this much raw video is queued, we'll hold off request more // video. - return mRawDataQueueForFeedingEngine.Duration() >= + return mRawDataQueueForFeedingEngine.PreciseDuration() >= StaticPrefs::media_wmf_media_engine_raw_data_threshold_video(); } @@ -240,6 +240,32 @@ bool MFMediaEngineVideoStream::IsDCompImageReady() { return true; } +RefPtr<MediaDataDecoder::DecodePromise> MFMediaEngineVideoStream::OutputData( + RefPtr<MediaRawData> aSample) { + if (IsShutdown()) { + return MediaDataDecoder::DecodePromise::CreateAndReject( + MediaResult(NS_ERROR_FAILURE, + RESULT_DETAIL("MFMediaEngineStream is shutdown")), + __func__); + } + AssertOnTaskQueue(); + NotifyNewData(aSample); + MediaDataDecoder::DecodedData outputs; + if (RefPtr<MediaData> outputData = OutputDataInternal()) { + outputs.AppendElement(outputData); + LOGV("Output data [%" PRId64 ",%" PRId64 "]", + outputData->mTime.ToMicroseconds(), + outputData->GetEndTime().ToMicroseconds()); + } + if (ShouldDelayVideoDecodeBeforeDcompReady()) { + LOG("Dcomp isn't ready and we already have enough video data. We will send " + "them back together at one when Dcomp is ready"); + return mVideoDecodeBeforeDcompPromise.Ensure(__func__); + } + return MediaDataDecoder::DecodePromise::CreateAndResolve(std::move(outputs), + __func__); +} + already_AddRefed<MediaData> MFMediaEngineVideoStream::OutputDataInternal() { AssertOnTaskQueue(); if (mRawDataQueueForGeneratingOutput.GetSize() == 0 || !IsDCompImageReady()) { @@ -261,28 +287,62 @@ RefPtr<MediaDataDecoder::DecodePromise> MFMediaEngineVideoStream::Drain() { MediaDataDecoder::DecodedData outputs; if (!IsDCompImageReady()) { LOGV("Waiting for dcomp image for draining"); + // A workaround for a special case where we have sent all input data to the + // media engine, and waiting for an output. Sometime media engine would + // never return the first frame to us, unless we notify it the end event, + // which happens on the case where the video only contains one frame. If we + // don't send end event to the media engine, the drain promise would be + // pending forever. + if (!mSampleRequestTokens.empty() && + mRawDataQueueForFeedingEngine.GetSize() == 0) { + NotifyEndEvent(); + } return mPendingDrainPromise.Ensure(__func__); } return MFMediaEngineStream::Drain(); } -void MFMediaEngineVideoStream::ResolvePendingDrainPromiseIfNeeded() { +RefPtr<MediaDataDecoder::FlushPromise> MFMediaEngineVideoStream::Flush() { + AssertOnTaskQueue(); + auto promise = MFMediaEngineStream::Flush(); + mPendingDrainPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__); + mVideoDecodeBeforeDcompPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, + __func__); + return promise; +} + +void MFMediaEngineVideoStream::ResolvePendingPromisesIfNeeded() { AssertOnTaskQueue(); - if (mPendingDrainPromise.IsEmpty()) { - return; - } if (!IsDCompImageReady()) { return; } - MediaDataDecoder::DecodedData outputs; - while (RefPtr<MediaData> outputData = OutputDataInternal()) { - outputs.AppendElement(outputData); - LOGV("Output data [%" PRId64 ",%" PRId64 "]", - outputData->mTime.ToMicroseconds(), - outputData->GetEndTime().ToMicroseconds()); + + // Resolve decoding promise first, then drain promise + if (!mVideoDecodeBeforeDcompPromise.IsEmpty()) { + MediaDataDecoder::DecodedData outputs; + while (RefPtr<MediaData> outputData = OutputDataInternal()) { + outputs.AppendElement(outputData); + LOGV("Output data [%" PRId64 ",%" PRId64 "]", + outputData->mTime.ToMicroseconds(), + outputData->GetEndTime().ToMicroseconds()); + } + mVideoDecodeBeforeDcompPromise.Resolve(std::move(outputs), __func__); + LOG("Resolved video decode before Dcomp promise"); + } + + // This drain promise could return no data, if all data has been processed in + // the decoding promise. + if (!mPendingDrainPromise.IsEmpty()) { + MediaDataDecoder::DecodedData outputs; + while (RefPtr<MediaData> outputData = OutputDataInternal()) { + outputs.AppendElement(outputData); + LOGV("Output data [%" PRId64 ",%" PRId64 "]", + outputData->mTime.ToMicroseconds(), + outputData->GetEndTime().ToMicroseconds()); + } + mPendingDrainPromise.Resolve(std::move(outputs), __func__); + LOG("Resolved pending drain promise"); } - mPendingDrainPromise.Resolve(std::move(outputs), __func__); - LOG("Resolved pending drain promise"); } MediaDataDecoder::ConversionRequired MFMediaEngineVideoStream::NeedsConversion() @@ -336,6 +396,20 @@ void MFMediaEngineVideoStream::UpdateConfig(const VideoInfo& aInfo) { void MFMediaEngineVideoStream::ShutdownCleanUpOnTaskQueue() { AssertOnTaskQueue(); mPendingDrainPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__); + mVideoDecodeBeforeDcompPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, + __func__); +} + +void MFMediaEngineVideoStream::SendRequestSampleEvent(bool aIsEnough) { + AssertOnTaskQueue(); + MFMediaEngineStream::SendRequestSampleEvent(aIsEnough); + // We need more data to be sent in, we should resolve the promise to allow + // more input data to be sent. + if (!aIsEnough && !mVideoDecodeBeforeDcompPromise.IsEmpty()) { + LOG("Resolved pending input promise to allow more input be sent in"); + mVideoDecodeBeforeDcompPromise.Resolve(MediaDataDecoder::DecodedData{}, + __func__); + } } bool MFMediaEngineVideoStream::IsEnded() const { @@ -352,6 +426,10 @@ bool MFMediaEngineVideoStream::IsEnded() const { bool MFMediaEngineVideoStream::IsEncrypted() const { return mIsEncrypted; } +bool MFMediaEngineVideoStream::ShouldDelayVideoDecodeBeforeDcompReady() { + return HasEnoughRawData() && !IsDCompImageReady(); +} + nsCString MFMediaEngineVideoStream::GetCodecName() const { switch (mStreamType) { case WMFStreamType::H264: |