Bug 1376363. P1 - store container type in MediaDecoder. draft
authorJW Wang <jwwang@mozilla.com>
Mon, 26 Jun 2017 17:10:47 +0800
changeset 601701 39aeedda5faf019edb7c8d1e8ee29c0a1bd85fd1
parent 601700 dd6c96258783ebe363a48e821289fc193b40bb74
child 601702 36902fd962f96731738cf889d2e6004c22bd0276
push id66194
push userjwwang@mozilla.com
push dateThu, 29 Jun 2017 01:56:47 +0000
bugs1376363
milestone56.0a1
Bug 1376363. P1 - store container type in MediaDecoder. So we can remove MediaResource::GetContentType() in the future. MozReview-Commit-ID: zWUNF2uGpf
dom/html/HTMLMediaElement.cpp
dom/media/DecoderTraits.cpp
dom/media/DecoderTraits.h
dom/media/MediaDecoder.cpp
dom/media/MediaDecoder.h
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -2502,17 +2502,18 @@ nsresult HTMLMediaElement::LoadResource(
     MediaDecoderInit decoderInit(
       this,
       mAudioChannel,
       mMuted ? 0.0 : mVolume,
       mPreservesPitch,
       mPlaybackRate,
       mPreloadAction == HTMLMediaElement::PRELOAD_METADATA,
       mHasSuspendTaint,
-      HasAttr(kNameSpaceID_None, nsGkAtoms::loop));
+      HasAttr(kNameSpaceID_None, nsGkAtoms::loop),
+      MediaContainerType(MEDIAMIMETYPE("application/x.mediasource")));
 
     RefPtr<MediaSourceDecoder> decoder = new MediaSourceDecoder(decoderInit);
     if (!mMediaSource->Attach(decoder)) {
       // TODO: Handle failure: run "If the media data cannot be fetched at
       // all, due to network errors, causing the user agent to give up
       // trying to fetch the resource" section of resource fetch algorithm.
       decoder->Shutdown();
       return NS_ERROR_FAILURE;
@@ -4645,25 +4646,26 @@ HTMLMediaElement::InitializeDecoderAsClo
 {
   NS_ASSERTION(mLoadingSrc, "mLoadingSrc must already be set");
   NS_ASSERTION(mDecoder == nullptr, "Shouldn't have a decoder");
 
   MediaResource* originalResource = aOriginal->GetResource();
   if (!originalResource)
     return NS_ERROR_FAILURE;
 
-  MediaDecoderInit decoderInit(
-    this,
-    mAudioChannel,
-    mMuted ? 0.0 : mVolume,
-    mPreservesPitch,
-    mPlaybackRate,
-    mPreloadAction == HTMLMediaElement::PRELOAD_METADATA,
-    mHasSuspendTaint,
-    HasAttr(kNameSpaceID_None, nsGkAtoms::loop));
+  MediaDecoderInit decoderInit(this,
+                               mAudioChannel,
+                               mMuted ? 0.0 : mVolume,
+                               mPreservesPitch,
+                               mPlaybackRate,
+                               mPreloadAction ==
+                                 HTMLMediaElement::PRELOAD_METADATA,
+                               mHasSuspendTaint,
+                               HasAttr(kNameSpaceID_None, nsGkAtoms::loop),
+                               aOriginal->ContainerType());
 
   RefPtr<ChannelMediaDecoder> decoder = aOriginal->Clone(decoderInit);
   if (!decoder)
     return NS_ERROR_FAILURE;
 
   LOG(LogLevel::Debug, ("%p Cloned decoder %p from %p", this, decoder.get(), aOriginal));
 
   nsresult rv = decoder->Load(originalResource);
@@ -4678,33 +4680,43 @@ HTMLMediaElement::InitializeDecoderAsClo
 }
 
 nsresult HTMLMediaElement::InitializeDecoderForChannel(nsIChannel* aChannel,
                                                        nsIStreamListener** aListener)
 {
   NS_ASSERTION(mLoadingSrc, "mLoadingSrc must already be set");
 
   nsAutoCString mimeType;
+  DecoderDoctorDiagnostics diagnostics;
 
   aChannel->GetContentType(mimeType);
   NS_ASSERTION(!mimeType.IsEmpty(), "We should have the Content-Type.");
 
-  DecoderDoctorDiagnostics diagnostics;
-  MediaDecoderInit decoderInit(
-    this,
-    mAudioChannel,
-    mMuted ? 0.0 : mVolume,
-    mPreservesPitch,
-    mPlaybackRate,
-    mPreloadAction == HTMLMediaElement::PRELOAD_METADATA,
-    mHasSuspendTaint,
-    HasAttr(kNameSpaceID_None, nsGkAtoms::loop));
+  Maybe<MediaContainerType> containerType = MakeMediaContainerType(mimeType);
+  if (!containerType) {
+    diagnostics.StoreFormatDiagnostics(OwnerDoc(),
+                                       NS_ConvertASCIItoUTF16(mimeType),
+                                       /* aCanPlay = */ false,
+                                       __func__);
+    return NS_ERROR_FAILURE;
+  }
+
+  MediaDecoderInit decoderInit(this,
+                               mAudioChannel,
+                               mMuted ? 0.0 : mVolume,
+                               mPreservesPitch,
+                               mPlaybackRate,
+                               mPreloadAction ==
+                                 HTMLMediaElement::PRELOAD_METADATA,
+                               mHasSuspendTaint,
+                               HasAttr(kNameSpaceID_None, nsGkAtoms::loop),
+                               *containerType);
 
   RefPtr<ChannelMediaDecoder> decoder =
-    DecoderTraits::CreateDecoder(mimeType, decoderInit, &diagnostics);
+    DecoderTraits::CreateDecoder(decoderInit, &diagnostics);
   diagnostics.StoreFormatDiagnostics(OwnerDoc(),
                                      NS_ConvertASCIItoUTF16(mimeType),
                                      decoder != nullptr,
                                      __func__);
   if (!decoder) {
     nsAutoString src;
     GetCurrentSrc(src);
     NS_ConvertUTF8toUTF16 mimeUTF16(mimeType);
--- a/dom/media/DecoderTraits.cpp
+++ b/dom/media/DecoderTraits.cpp
@@ -261,88 +261,84 @@ bool DecoderTraits::ShouldHandleMediaTyp
     }
   }
 
   return CanHandleMediaType(*containerType, aDiagnostics) != CANPLAY_NO;
 }
 
 // Instantiates but does not initialize decoder.
 static already_AddRefed<ChannelMediaDecoder>
-InstantiateDecoder(const MediaContainerType& aType,
-                   MediaDecoderInit& aInit,
+InstantiateDecoder(MediaDecoderInit& aInit,
                    DecoderDoctorDiagnostics* aDiagnostics)
 {
   MOZ_ASSERT(NS_IsMainThread());
   RefPtr<ChannelMediaDecoder> decoder;
 
+  const MediaContainerType& type = aInit.mContainerType;
+
 #ifdef MOZ_ANDROID_HLS_SUPPORT
-  if (HLSDecoder::IsSupportedType(aType)) {
+  if (HLSDecoder::IsSupportedType(type)) {
     decoder = new HLSDecoder(aInit);
     return decoder.forget();
   }
 #endif
 #ifdef MOZ_FMP4
-  if (MP4Decoder::IsSupportedType(aType, aDiagnostics)) {
+  if (MP4Decoder::IsSupportedType(type, aDiagnostics)) {
     decoder = new MP4Decoder(aInit);
     return decoder.forget();
   }
 #endif
-  if (MP3Decoder::IsSupportedType(aType)) {
+  if (MP3Decoder::IsSupportedType(type)) {
     decoder = new MP3Decoder(aInit);
     return decoder.forget();
   }
-  if (ADTSDecoder::IsSupportedType(aType)) {
+  if (ADTSDecoder::IsSupportedType(type)) {
     decoder = new ADTSDecoder(aInit);
     return decoder.forget();
   }
-  if (OggDecoder::IsSupportedType(aType)) {
+  if (OggDecoder::IsSupportedType(type)) {
     decoder = new OggDecoder(aInit);
     return decoder.forget();
   }
-  if (WaveDecoder::IsSupportedType(aType)) {
+  if (WaveDecoder::IsSupportedType(type)) {
     decoder = new WaveDecoder(aInit);
     return decoder.forget();
   }
-  if (FlacDecoder::IsSupportedType(aType)) {
+  if (FlacDecoder::IsSupportedType(type)) {
     decoder = new FlacDecoder(aInit);
     return decoder.forget();
   }
 #ifdef MOZ_ANDROID_OMX
   if (MediaDecoder::IsAndroidMediaPluginEnabled() &&
-      EnsureAndroidMediaPluginHost()->FindDecoder(aType, nullptr)) {
-    decoder = new AndroidMediaDecoder(aInit, aType);
+      EnsureAndroidMediaPluginHost()->FindDecoder(type, nullptr)) {
+    decoder = new AndroidMediaDecoder(aInit, type);
     return decoder.forget();
   }
 #endif
 
-  if (WebMDecoder::IsSupportedType(aType)) {
+  if (WebMDecoder::IsSupportedType(type)) {
     decoder = new WebMDecoder(aInit);
     return decoder.forget();
   }
 
-  if (DecoderTraits::IsHttpLiveStreamingType(aType)) {
+  if (DecoderTraits::IsHttpLiveStreamingType(type)) {
     // We don't have an HLS decoder.
     Telemetry::Accumulate(Telemetry::MEDIA_HLS_DECODER_SUCCESS, false);
   }
 
   return nullptr;
 }
 
 /* static */
 already_AddRefed<ChannelMediaDecoder>
-DecoderTraits::CreateDecoder(const nsACString& aType,
-                             MediaDecoderInit& aInit,
+DecoderTraits::CreateDecoder(MediaDecoderInit& aInit,
                              DecoderDoctorDiagnostics* aDiagnostics)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  Maybe<MediaContainerType> type = MakeMediaContainerType(aType);
-  if (!type) {
-    return nullptr;
-  }
-  return InstantiateDecoder(*type, aInit, aDiagnostics);
+  return InstantiateDecoder(aInit, aDiagnostics);
 }
 
 /* static */
 MediaDecoderReader*
 DecoderTraits::CreateReader(const MediaContainerType& aType,
                             AbstractMediaDecoder* aDecoder)
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/dom/media/DecoderTraits.h
+++ b/dom/media/DecoderTraits.h
@@ -39,17 +39,16 @@ public:
   // for the type is more limited than appears in the wild, we should return
   // false here even if CanHandleMediaType would return true.
   static bool ShouldHandleMediaType(const char* aMIMEType,
                                     DecoderDoctorDiagnostics* aDiagnostics);
 
   // Create a decoder for the given aType. Returns null if we
   // were unable to create the decoder.
   static already_AddRefed<ChannelMediaDecoder> CreateDecoder(
-    const nsACString& aType,
     MediaDecoderInit& aInit,
     DecoderDoctorDiagnostics* aDiagnostics);
 
   // Create a reader for thew given MIME type aType. Returns null
   // if we were unable to create the reader.
   static MediaDecoderReader* CreateReader(const MediaContainerType& aType,
                                           AbstractMediaDecoder* aDecoder);
 
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -262,16 +262,17 @@ MediaDecoder::MediaDecoder(MediaDecoderI
   , INIT_CANONICAL(mSameOriginMedia, false)
   , INIT_CANONICAL(mMediaPrincipalHandle, PRINCIPAL_HANDLE_NONE)
   , INIT_CANONICAL(mPlaybackBytesPerSecond, 0.0)
   , INIT_CANONICAL(mPlaybackRateReliable, true)
   , INIT_CANONICAL(mDecoderPosition, 0)
   , mTelemetryReported(false)
   , mIsMediaElement(!!mOwner->GetMediaElement())
   , mElement(mOwner->GetMediaElement())
+  , mContainerType(aInit.mContainerType)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mAbstractMainThread);
   MediaMemoryTracker::AddMediaDecoder(this);
 
   //
   // Initialize watchers.
   //
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -47,43 +47,46 @@ enum class MediaEventType : int8_t;
 enum class Visibility : uint8_t;
 
 // GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
 // GetTickCount() and conflicts with MediaDecoder::GetCurrentTime implementation.
 #ifdef GetCurrentTime
 #undef GetCurrentTime
 #endif
 
-struct MediaDecoderInit
+struct MOZ_STACK_CLASS MediaDecoderInit
 {
   MediaDecoderOwner* const mOwner;
   const dom::AudioChannel mAudioChannel;
   const double mVolume;
   const bool mPreservesPitch;
   const double mPlaybackRate;
   const bool mMinimizePreroll;
   const bool mHasSuspendTaint;
   const bool mLooping;
+  const MediaContainerType mContainerType;
 
   MediaDecoderInit(MediaDecoderOwner* aOwner,
                    dom::AudioChannel aAudioChannel,
                    double aVolume,
                    bool aPreservesPitch,
                    double aPlaybackRate,
                    bool aMinimizePreroll,
                    bool aHasSuspendTaint,
-                   bool aLooping)
+                   bool aLooping,
+                   const MediaContainerType& aContainerType)
     : mOwner(aOwner)
     , mAudioChannel(aAudioChannel)
     , mVolume(aVolume)
     , mPreservesPitch(aPreservesPitch)
     , mPlaybackRate(aPlaybackRate)
     , mMinimizePreroll(aMinimizePreroll)
     , mHasSuspendTaint(aHasSuspendTaint)
     , mLooping(aLooping)
+    , mContainerType(aContainerType)
   {
   }
 };
 
 class MediaDecoder : public AbstractMediaDecoder
 {
 public:
   typedef MozPromise<bool /* aIgnored */, bool /* aIgnored */,
@@ -103,16 +106,20 @@ public:
     PLAY_STATE_SHUTDOWN
   };
 
   // Must be called exactly once, on the main thread, during startup.
   static void InitStatics();
 
   explicit MediaDecoder(MediaDecoderInit& aInit);
 
+  // Returns the container content type of the resource.
+  // Safe to call from any thread.
+  const MediaContainerType& ContainerType() const { return mContainerType; }
+
   // Create a new state machine to run this decoder.
   // Subclasses must implement this.
   virtual MediaDecoderStateMachine* CreateStateMachine() = 0;
 
   // Cleanup internal data structures. Must be called on the main
   // thread by the owning object before that object disposes of this object.
   virtual void Shutdown();
 
@@ -823,13 +830,14 @@ private:
   // Notify owner when the audible state changed
   void NotifyAudibleStateChanged();
 
   bool mTelemetryReported;
 
   // Used to debug how mOwner becomes a dangling pointer in bug 1326294.
   bool mIsMediaElement;
   WeakPtr<dom::HTMLMediaElement> mElement;
+  const MediaContainerType mContainerType;
 };
 
 } // namespace mozilla
 
 #endif