Bug 1454630 - P2. Use new PDMFactory whenever encryption type change. r=bryce, r=cpearce, a=RyanVM
authorJean-Yves Avenard <jyavenard@mozilla.com>
Sun, 27 May 2018 18:42:25 +0200
changeset 473586 ed4aa0f2e4e3d0dc6e42be601db945310526d6ec
parent 473585 66ccbab3ef0f2b4042d2a89ebf89d5e96e4fbc20
child 473587 5326f573aaec25b0842d2f2695cce82757fd52e6
push id1728
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:12:27 +0000
treeherdermozilla-release@c296fde26f5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbryce, cpearce, RyanVM
bugs1454630
milestone61.0
Bug 1454630 - P2. Use new PDMFactory whenever encryption type change. r=bryce, r=cpearce, a=RyanVM If the content being played was first non-encrypted, the PDMFactory would have been set without a CDMProxy. As such, it is necessary to use a new PDMFactory when the encryption type changes (from clear to encrypted). Rather than attempting to detect if the encryption status has changed, simply use two PDMFactory, one with CDMProxy set and one without (for clear content) Also, never attempt to recycle a decoder if the encryption type changed (used only on Android) The TrackBuffersManager would have already handle the dispatching of the encrypted event when parsing the new init segment. As such, nothing more is necessary. MozReview-Commit-ID: Jn14P2F6N5V
dom/media/MediaFormatReader.cpp
dom/media/MediaFormatReader.h
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -796,49 +796,52 @@ MediaFormatReader::DecoderFactory::RunSt
     }
   }
 }
 
 MediaResult
 MediaFormatReader::DecoderFactory::DoCreateDecoder(Data& aData)
 {
   auto& ownerData = aData.mOwnerData;
-
-  if (!mOwner->mPlatform) {
-    mOwner->mPlatform = new PDMFactory();
-    if (mOwner->IsEncrypted()) {
+  auto& decoder = mOwner->GetDecoderData(aData.mTrack);
+  auto& platform =
+    decoder.IsEncrypted() ? mOwner->mEncryptedPlatform : mOwner->mPlatform;
+
+  if (!platform) {
+    platform = new PDMFactory();
+    if (decoder.IsEncrypted()) {
       MOZ_ASSERT(mOwner->mCDMProxy);
-      mOwner->mPlatform->SetCDMProxy(mOwner->mCDMProxy);
+      platform->SetCDMProxy(mOwner->mCDMProxy);
     }
   }
 
   // result may not be updated by PDMFactory::CreateDecoder, as such it must be
   // initialized to a fatal error by default.
   MediaResult result = MediaResult(
     NS_ERROR_DOM_MEDIA_FATAL_ERR,
     nsPrintfCString("error creating %s decoder", TrackTypeToStr(aData.mTrack)));
 
   switch (aData.mTrack) {
     case TrackInfo::kAudioTrack: {
-      aData.mDecoder = mOwner->mPlatform->CreateDecoder({
+      aData.mDecoder = platform->CreateDecoder({
         *ownerData.GetCurrentInfo()->GetAsAudioInfo(),
         ownerData.mTaskQueue,
         mOwner->mCrashHelper,
         CreateDecoderParams::UseNullDecoder(ownerData.mIsNullDecode),
         &result,
         TrackInfo::kAudioTrack,
         &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.
-      aData.mDecoder = mOwner->mPlatform->CreateDecoder(
+      aData.mDecoder = platform->CreateDecoder(
         { *ownerData.GetCurrentInfo()->GetAsVideoInfo(),
           ownerData.mTaskQueue,
           mOwner->mKnowsCompositor,
           mOwner->GetImageContainer(),
           mOwner->mCrashHelper,
           CreateDecoderParams::UseNullDecoder(ownerData.mIsNullDecode),
           &result,
           TrackType::kVideoTrack,
@@ -1423,16 +1426,17 @@ MediaFormatReader::TearDownDecoders()
   if (mVideo.mTaskQueue) {
     mVideo.mTaskQueue->BeginShutdown();
     mVideo.mTaskQueue->AwaitShutdownAndIdle();
     mVideo.mTaskQueue = nullptr;
   }
 
   mDecoderFactory = nullptr;
   mPlatform = nullptr;
+  mEncryptedPlatform = nullptr;
   mVideoFrameContainer = nullptr;
 
   ReleaseResources();
   mBuffered.DisconnectAll();
   return mTaskQueue->BeginShutdown();
 }
 
 nsresult
@@ -1525,19 +1529,19 @@ MediaFormatReader::SetCDMProxy(CDMProxy*
     PrepareToSetCDMForTrack(TrackInfo::kAudioTrack);
   }
   if (HasVideo()) {
     PrepareToSetCDMForTrack(TrackInfo::kVideoTrack);
   }
 
   mCDMProxy = aProxy;
 
-  if (IsEncrypted() && !mCDMProxy) {
+  if (!mCDMProxy) {
     // Release old PDMFactory which contains an EMEDecoderModule.
-    mPlatform = nullptr;
+    mEncryptedPlatform = nullptr;
   }
 
   if (!mInitDone || mSetCDMForTracks.isEmpty() || !mCDMProxy) {
     // 1) MFR is not initialized yet or
     // 2) Demuxer is initialized without active audio and video or
     // 3) A null cdm proxy is set
     // the promise can be resolved directly.
     mSetCDMForTracks.clear();
@@ -1747,18 +1751,18 @@ MediaFormatReader::MaybeResolveMetadataP
   UpdateBuffered();
 
   mMetadataPromise.Resolve(Move(metadata), __func__);
 }
 
 bool
 MediaFormatReader::IsEncrypted() const
 {
-  return (HasAudio() && mInfo.mAudio.mCrypto.mValid) ||
-         (HasVideo() && mInfo.mVideo.mCrypto.mValid);
+  return (HasAudio() && mAudio.GetCurrentInfo()->mCrypto.mValid) ||
+         (HasVideo() && mVideo.GetCurrentInfo()->mCrypto.mValid);
 }
 
 void
 MediaFormatReader::OnDemuxerInitFailed(const MediaResult& aError)
 {
   mDemuxerInitRequest.Complete();
   mMetadataPromise.Reject(aError, __func__);
 }
@@ -2401,21 +2405,23 @@ MediaFormatReader::HandleDemuxedSamples(
   }
 
   RefPtr<MediaRawData> sample = decoder.mQueuedSamples[0];
   const RefPtr<TrackInfoSharedPtr> info = sample->mTrackInfo;
 
   if (info && decoder.mLastStreamSourceID != info->GetID()) {
     nsTArray<RefPtr<MediaRawData>> samples;
     if (decoder.mDecoder) {
-      bool recyclable = StaticPrefs::MediaDecoderRecycleEnabled() &&
-                        decoder.mDecoder->SupportDecoderRecycling();
+      bool recyclable =
+        StaticPrefs::MediaDecoderRecycleEnabled() &&
+        decoder.mDecoder->SupportDecoderRecycling() &&
+        (*info)->mCrypto.mValid == decoder.GetCurrentInfo()->mCrypto.mValid;
       if (!recyclable && decoder.mTimeThreshold.isNothing() &&
           (decoder.mNextStreamSourceID.isNothing() ||
-            decoder.mNextStreamSourceID.ref() != info->GetID())) {
+           decoder.mNextStreamSourceID.ref() != info->GetID())) {
         LOG("%s stream id has changed from:%d to:%d, draining decoder.",
             TrackTypeToStr(aTrack),
             decoder.mLastStreamSourceID,
             info->GetID());
         decoder.RequestDrain();
         decoder.mNextStreamSourceID = Some(info->GetID());
         ScheduleUpdate(aTrack);
         return;
--- a/dom/media/MediaFormatReader.h
+++ b/dom/media/MediaFormatReader.h
@@ -334,16 +334,17 @@ private:
 
   bool ShouldSkip(media::TimeUnit aTimeThreshold);
 
   void SetVideoDecodeThreshold();
 
   size_t SizeOfQueue(TrackType aTrack);
 
   RefPtr<PDMFactory> mPlatform;
+  RefPtr<PDMFactory> mEncryptedPlatform;
 
   enum class DrainState
   {
     None,
     DrainRequested,
     Draining,
     PartialDrainPending,
     DrainCompleted,
@@ -582,16 +583,20 @@ private:
     // with MSE or the WebMDemuxer.
     const TrackInfo* GetCurrentInfo() const
     {
       if (mInfo) {
         return *mInfo;
       }
       return mOriginalInfo.get();
     }
+    bool IsEncrypted() const
+    {
+      return GetCurrentInfo()->mCrypto.mValid;
+    }
 
     // Used by the MDSM for logging purposes.
     Atomic<size_t> mSizeOfQueue;
     // Used by the MDSM to determine if video decoding is hardware accelerated.
     // This value is updated after a frame is successfully decoded.
     Atomic<bool> mIsHardwareAccelerated;
     // Sample format monitoring.
     uint32_t mLastStreamSourceID;