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 449533 c04873fad58566b0d346d28837f6dbb91b342b8e
parent 449532 6897558cfa133ae59928f6618910167454b067f4
child 449534 e90141e8315d85415680a6da293056939dbf3c0b
push id88
push userryanvm@gmail.com
push dateWed, 13 Jun 2018 23:43:49 +0000
treeherdermozilla-esr60@89f930216fdb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbryce, cpearce, RyanVM
bugs1454630
milestone60.0.3
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
@@ -792,49 +792,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,
@@ -1417,16 +1420,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
@@ -1519,19 +1523,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();
@@ -1741,18 +1745,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__);
 }
@@ -2395,21 +2399,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 = MediaPrefs::MediaDecoderCheckRecycling() &&
-                        decoder.mDecoder->SupportDecoderRecycling();
+      bool recyclable =
+        MediaPrefs::MediaDecoderCheckRecycling() &&
+        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;