Bug 1322234 - P2. When first frame decoding failed with hardware decoder, fall back to software decoding r=bryce
authorJean-Yves Avenard <jyavenard@mozilla.com>
Thu, 04 Oct 2018 09:43:24 +0000
changeset 495286 ad7f2511596c2992ad1185ac96c985f17fb36f93
parent 495285 49dc3475d6f34392b1177870a8cf5f135934ff80
child 495287 d0b359a2a15a4bf17f6263fe456d6dc72e5da09b
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbryce
bugs1322234, 1363668
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1322234 - P2. When first frame decoding failed with hardware decoder, fall back to software decoding r=bryce Continuing on the infrastructure provided by bug 1363668 we will now forcibly disable hardware decoding if the first frame failed to decode with a hardware accelerated decoder. Depends on D7615 Differential Revision: https://phabricator.services.mozilla.com/D7616
dom/media/MediaFormatReader.cpp
dom/media/MediaFormatReader.h
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -606,27 +606,33 @@ MediaFormatReader::DecoderFactory::DoCre
         &mOwner->OnTrackWaitingForKeyProducer()
       });
       break;
     }
 
     case TrackType::kVideoTrack: {
       // Decoders use the layers backend to decide if they can use hardware decoding,
       // so specify LAYERS_NONE if we want to forcibly disable it.
+      using Option = CreateDecoderParams::Option;
+      using OptionSet = CreateDecoderParams::OptionSet;
+
       aData.mDecoder = platform->CreateDecoder(
         { *ownerData.GetCurrentInfo()->GetAsVideoInfo(),
           ownerData.mTaskQueue,
           mOwner->mKnowsCompositor,
           mOwner->GetImageContainer(),
           mOwner->mCrashHelper,
           CreateDecoderParams::UseNullDecoder(ownerData.mIsNullDecode),
           &result,
           TrackType::kVideoTrack,
           &mOwner->OnTrackWaitingForKeyProducer(),
-          CreateDecoderParams::VideoFrameRate(ownerData.mMeanRate.Mean()) });
+          CreateDecoderParams::VideoFrameRate(ownerData.mMeanRate.Mean()),
+          OptionSet(ownerData.mHardwareDecodingDisabled
+                      ? Option::HardwareDecoderNotAllowed
+                      : Option::Default) });
       break;
     }
 
     default:
       break;
   }
 
   if (aData.mDecoder) {
@@ -2226,16 +2232,19 @@ MediaFormatReader::HandleDemuxedSamples(
       }
 
       // If flushing is required, it will clear our array of queued samples.
       // So we may need to make a copy.
       samples = decoder.mQueuedSamples;
       if (!recyclable) {
         LOG("Decoder does not support recycling, recreate decoder.");
         ShutdownDecoder(aTrack);
+        // We're going to be using a new decoder following the change of content
+        // We can attempt to use hardware decoding again.
+        decoder.mHardwareDecodingDisabled = false;
       } else if (decoder.HasWaitingPromise()) {
         decoder.Flush();
       }
     }
 
     LOG("%s stream id has changed from:%d to:%d.",
         TrackTypeToStr(aTrack),
         decoder.mLastStreamSourceID,
@@ -2578,24 +2587,35 @@ MediaFormatReader::Update(TrackType aTra
       DrainDecoder(aTrack);
     }
     return;
   }
 
   if (decoder.mError && !decoder.HasFatalError()) {
     MOZ_RELEASE_ASSERT(!decoder.HasInternalSeekPending(),
                        "No error can occur while an internal seek is pending");
+
+    nsCString error;
+    bool firstFrameDecodingFailedWithHardware =
+      decoder.mFirstFrameTime &&
+      decoder.mError.ref() == NS_ERROR_DOM_MEDIA_DECODE_ERR &&
+      decoder.mDecoder && decoder.mDecoder->IsHardwareAccelerated(error) &&
+      !decoder.mHardwareDecodingDisabled;
     bool needsNewDecoder =
-      decoder.mError.ref() == NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER;
+      decoder.mError.ref() == NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER ||
+      firstFrameDecodingFailedWithHardware;
     if (!needsNewDecoder &&
         ++decoder.mNumOfConsecutiveError > decoder.mMaxConsecutiveError) {
       DDLOG(DDLogCategory::Log, "too_many_decode_errors", decoder.mError.ref());
       NotifyError(aTrack, decoder.mError.ref());
       return;
     }
+    if (firstFrameDecodingFailedWithHardware) {
+      decoder.mHardwareDecodingDisabled = true;
+    }
     decoder.mError.reset();
 
     LOG("%s decoded error count %d", TrackTypeToStr(aTrack),
         decoder.mNumOfConsecutiveError);
 
     if (needsNewDecoder) {
       LOG("Error: Need new decoder");
       ShutdownDecoder(aTrack);
--- a/dom/media/MediaFormatReader.h
+++ b/dom/media/MediaFormatReader.h
@@ -381,16 +381,17 @@ private:
       , mNumSamplesInput(0)
       , mNumSamplesOutput(0)
       , mNumSamplesOutputTotal(0)
       , mNumSamplesSkippedTotal(0)
       , mSizeOfQueue(0)
       , mIsHardwareAccelerated(false)
       , mLastStreamSourceID(UINT32_MAX)
       , mIsNullDecode(false)
+      , mHardwareDecodingDisabled(false)
     {
       DecoderDoctorLogger::LogConstruction("MediaFormatReader::DecoderData",
                                            this);
     }
 
     ~DecoderData()
     {
       DecoderDoctorLogger::LogDestruction("MediaFormatReader::DecoderData",
@@ -617,16 +618,17 @@ private:
     UniquePtr<TrackInfo> mOriginalInfo;
     // Written exclusively on the TaskQueue, can be read on MDSM's TaskQueue.
     // Must be read with parent's mutex held.
     UniquePtr<TrackInfo> mWorkingInfo;
     RefPtr<TrackInfoSharedPtr> mInfo;
     Maybe<media::TimeUnit> mFirstDemuxedSampleTime;
     // Use NullDecoderModule or not.
     bool mIsNullDecode;
+    bool mHardwareDecodingDisabled;
 
     class
     {
     public:
       float Mean() const { return mMean; }
 
       void Update(const media::TimeUnit& aValue)
       {