Bug 814284 - Part 1: Refactor the code necessary for detection of codec support out of nsHTMLMediaElement; r=cpearce
authorEhsan Akhgari <ehsan@mozilla.com>
Wed, 21 Nov 2012 22:10:41 -0500
changeset 123134 abfcf6bd97a40a5ada5d3779b9b99b8929599ddf
parent 123133 78ed9104dadd36e50eb578de48e2b864975ecdfb
child 123135 2020b35ea3b4884496b75b755b5c64f07fdda9e9
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs814284
milestone20.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 814284 - Part 1: Refactor the code necessary for detection of codec support out of nsHTMLMediaElement; r=cpearce
content/base/src/nsContentUtils.cpp
content/html/content/public/nsHTMLMediaElement.h
content/html/content/src/nsHTMLMediaElement.cpp
content/media/DecoderTraits.cpp
content/media/DecoderTraits.h
content/media/Makefile.in
layout/build/nsContentDLF.cpp
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -164,16 +164,17 @@
 #include "nsIEditor.h"
 #include "nsIEditorDocShell.h"
 #include "mozilla/Attributes.h"
 #include "nsIParserService.h"
 #include "nsIDOMScriptObjectFactory.h"
 #include "nsSandboxFlags.h"
 #include "nsSVGFeatures.h"
 #include "MediaDecoder.h"
+#include "DecoderTraits.h"
 
 #include "nsWrapperCacheInlines.h"
 
 extern "C" int MOZ_XMLTranslateEntity(const char* ptr, const char* end,
                                       const char** next, PRUnichar* result);
 extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end,
                                  int ns_aware, const char** colon);
 
@@ -6586,48 +6587,48 @@ nsContentUtils::FindInternalContentViewe
       else
       *aLoaderType = TYPE_UNKNOWN;
     }
     return docFactory.forget();
   }
 
 #ifdef MOZ_MEDIA
 #ifdef MOZ_OGG
-  if (nsHTMLMediaElement::IsOggType(nsDependentCString(aType))) {
+  if (DecoderTraits::IsOggType(nsDependentCString(aType))) {
     docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
     if (docFactory && aLoaderType) {
       *aLoaderType = TYPE_CONTENT;
     }
     return docFactory.forget();
   }
 #endif
 
 #ifdef MOZ_WEBM
-  if (nsHTMLMediaElement::IsWebMType(nsDependentCString(aType))) {
+  if (DecoderTraits::IsWebMType(nsDependentCString(aType))) {
     docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
     if (docFactory && aLoaderType) {
       *aLoaderType = TYPE_CONTENT;
     }
     return docFactory.forget();
   }
 #endif
 
 #ifdef MOZ_GSTREAMER
-  if (nsHTMLMediaElement::IsGStreamerSupportedType(nsDependentCString(aType))) {
+  if (DecoderTraits::IsGStreamerSupportedType(nsDependentCString(aType))) {
     docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
     if (docFactory && aLoaderType) {
       *aLoaderType = TYPE_CONTENT;
     }
     return docFactory.forget();
   }
 #endif
 
 #ifdef MOZ_MEDIA_PLUGINS
   if (mozilla::MediaDecoder::IsMediaPluginsEnabled() &&
-      nsHTMLMediaElement::IsMediaPluginsType(nsDependentCString(aType))) {
+      DecoderTraits::IsMediaPluginsType(nsDependentCString(aType))) {
     docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
     if (docFactory && aLoaderType) {
       *aLoaderType = TYPE_CONTENT;
     }
     return docFactory.forget();
   }
 #endif // MOZ_MEDIA_PLUGINS
 #endif // MOZ_MEDIA
--- a/content/html/content/public/nsHTMLMediaElement.h
+++ b/content/html/content/public/nsHTMLMediaElement.h
@@ -19,16 +19,17 @@
 #include "AudioStream.h"
 #include "VideoFrameContainer.h"
 #include "mozilla/CORSMode.h"
 #include "nsDOMMediaStream.h"
 #include "mozilla/Mutex.h"
 #include "nsTimeRanges.h"
 #include "nsIDOMWakeLock.h"
 #include "AudioChannelCommon.h"
+#include "DecoderTraits.h"
 
 // Define to output information on decoding and painting framerate
 /* #define DEBUG_FRAME_RATE 1 */
 
 typedef uint16_t nsMediaNetworkState;
 typedef uint16_t nsMediaReadyState;
 
 namespace mozilla {
@@ -53,22 +54,16 @@ public:
   typedef mozilla::MetadataTags MetadataTags;
   typedef mozilla::AudioStream AudioStream;
   typedef mozilla::MediaDecoder MediaDecoder;
 
 #ifdef MOZ_DASH
   friend class DASHDecoder;
 #endif
 
-  enum CanPlayStatus {
-    CANPLAY_NO,
-    CANPLAY_MAYBE,
-    CANPLAY_YES
-  };
-
   mozilla::CORSMode GetCORSMode() {
     return mCORSMode;
   }
 
   nsHTMLMediaElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLMediaElement();
 
   /**
@@ -249,76 +244,19 @@ public:
 
   // called to notify that the principal of the decoder's media resource has changed.
   virtual void NotifyDecoderPrincipalChanged() MOZ_FINAL MOZ_OVERRIDE;
 
   // Update the visual size of the media. Called from the decoder on the
   // main thread when/if the size changes.
   void UpdateMediaSize(nsIntSize size);
 
-  // Returns the CanPlayStatus indicating if we can handle this
-  // MIME type. The MIME type should not include the codecs parameter.
-  // If it returns anything other than CANPLAY_NO then it also
-  // returns a null-terminated list of supported codecs
-  // in *aSupportedCodecs. This list should not be freed, it is static data.
-  static CanPlayStatus CanHandleMediaType(const char* aMIMEType,
-                                          char const *const ** aSupportedCodecs);
-
   // Returns the CanPlayStatus indicating if we can handle the
   // full MIME type including the optional codecs parameter.
-  static CanPlayStatus GetCanPlay(const nsAString& aType);
-
-  // Returns true if we should handle this MIME type when it appears
-  // as an <object> or as a toplevel page. If, in practice, our support
-  // 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);
-
-#ifdef MOZ_OGG
-  static bool IsOggType(const nsACString& aType);
-  static const char gOggTypes[3][16];
-  static char const *const gOggCodecs[3];
-  static char const *const gOggCodecsWithOpus[4];
-#endif
-
-#ifdef MOZ_WAVE
-  static bool IsWaveType(const nsACString& aType);
-  static const char gWaveTypes[4][15];
-  static char const *const gWaveCodecs[2];
-#endif
-
-#ifdef MOZ_WEBM
-  static bool IsWebMType(const nsACString& aType);
-  static const char gWebMTypes[2][11];
-  static char const *const gWebMCodecs[4];
-#endif
-
-#ifdef MOZ_GSTREAMER
-  static bool IsGStreamerSupportedType(const nsACString& aType);
-  static bool IsH264Type(const nsACString& aType);
-  static const char gH264Types[3][16];
-#endif
-
-#ifdef MOZ_WIDGET_GONK
-  static bool IsOmxSupportedType(const nsACString& aType);
-  static const char gOmxTypes[5][16];
-#endif
-
-#if defined(MOZ_GSTREAMER) || defined(MOZ_WIDGET_GONK)
-  static char const *const gH264Codecs[9];
-#endif
-
-#ifdef MOZ_MEDIA_PLUGINS
-  static bool IsMediaPluginsType(const nsACString& aType);
-#endif
-
-#ifdef MOZ_DASH
-  static bool IsDASHMPDType(const nsACString& aType);
-  static const char gDASHMPDTypes[1][21];
-#endif
+  static mozilla::CanPlayStatus GetCanPlay(const nsAString& aType);
 
   /**
    * Get the mime type for this element.
    */
   void GetMimeType(nsCString& aMimeType);
 
   /**
    * Called when a child source element is added to this media element. This
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -2044,362 +2044,40 @@ nsresult nsHTMLMediaElement::BindToTree(
 void nsHTMLMediaElement::UnbindFromTree(bool aDeep,
                                         bool aNullParent)
 {
   if (!mPaused && mNetworkState != nsIDOMHTMLMediaElement::NETWORK_EMPTY)
     Pause();
   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
 }
 
-#ifdef MOZ_RAW
-static const char gRawTypes[2][16] = {
-  "video/x-raw",
-  "video/x-raw-yuv"
-};
-
-static const char* gRawCodecs[1] = {
-  nullptr
-};
-
-static bool IsRawType(const nsACString& aType)
-{
-  if (!MediaDecoder::IsRawEnabled()) {
-    return false;
-  }
-
-  for (uint32_t i = 0; i < ArrayLength(gRawTypes); ++i) {
-    if (aType.EqualsASCII(gRawTypes[i])) {
-      return true;
-    }
-  }
-
-  return false;
-}
-#endif
-#ifdef MOZ_OGG
-// See http://www.rfc-editor.org/rfc/rfc5334.txt for the definitions
-// of Ogg media types and codec types
-const char nsHTMLMediaElement::gOggTypes[3][16] = {
-  "video/ogg",
-  "audio/ogg",
-  "application/ogg"
-};
-
-char const *const nsHTMLMediaElement::gOggCodecs[3] = {
-  "vorbis",
-  "theora",
-  nullptr
-};
-
-char const *const nsHTMLMediaElement::gOggCodecsWithOpus[4] = {
-  "vorbis",
-  "opus",
-  "theora",
-  nullptr
-};
-
-bool
-nsHTMLMediaElement::IsOggType(const nsACString& aType)
-{
-  if (!MediaDecoder::IsOggEnabled()) {
-    return false;
-  }
-
-  for (uint32_t i = 0; i < ArrayLength(gOggTypes); ++i) {
-    if (aType.EqualsASCII(gOggTypes[i])) {
-      return true;
-    }
-  }
-
-  return false;
-}
-#endif
-
-#ifdef MOZ_WAVE
-// See http://www.rfc-editor.org/rfc/rfc2361.txt for the definitions
-// of WAVE media types and codec types. However, the audio/vnd.wave
-// MIME type described there is not used.
-const char nsHTMLMediaElement::gWaveTypes[4][15] = {
-  "audio/x-wav",
-  "audio/wav",
-  "audio/wave",
-  "audio/x-pn-wav"
-};
-
-char const *const nsHTMLMediaElement::gWaveCodecs[2] = {
-  "1", // Microsoft PCM Format
-  nullptr
-};
-
-bool
-nsHTMLMediaElement::IsWaveType(const nsACString& aType)
-{
-  if (!MediaDecoder::IsWaveEnabled()) {
-    return false;
-  }
-
-  for (uint32_t i = 0; i < ArrayLength(gWaveTypes); ++i) {
-    if (aType.EqualsASCII(gWaveTypes[i])) {
-      return true;
-    }
-  }
-
-  return false;
-}
-#endif
-
-#ifdef MOZ_WEBM
-const char nsHTMLMediaElement::gWebMTypes[2][11] = {
-  "video/webm",
-  "audio/webm"
-};
-
-char const *const nsHTMLMediaElement::gWebMCodecs[4] = {
-  "vp8",
-  "vp8.0",
-  "vorbis",
-  nullptr
-};
-
-bool
-nsHTMLMediaElement::IsWebMType(const nsACString& aType)
-{
-  if (!MediaDecoder::IsWebMEnabled()) {
-    return false;
-  }
-
-  for (uint32_t i = 0; i < ArrayLength(gWebMTypes); ++i) {
-    if (aType.EqualsASCII(gWebMTypes[i])) {
-      return true;
-    }
-  }
-
-  return false;
-}
-#endif
-
-#if defined(MOZ_GSTREAMER) || defined(MOZ_WIDGET_GONK)
-char const *const nsHTMLMediaElement::gH264Codecs[9] = {
-  "avc1.42E01E",  // H.264 Constrained Baseline Profile Level 3.0
-  "avc1.42001E",  // H.264 Baseline Profile Level 3.0
-  "avc1.58A01E",  // H.264 Extended Profile Level 3.0
-  "avc1.4D401E",  // H.264 Main Profile Level 3.0
-  "avc1.64001E",  // H.264 High Profile Level 3.0
-  "avc1.64001F",  // H.264 High Profile Level 3.1
-  "mp4v.20.3",    // 3GPP
-  "mp4a.40.2",    // AAC-LC
-  nullptr
-};
-#endif
-
-#ifdef MOZ_GSTREAMER
-const char nsHTMLMediaElement::gH264Types[3][16] = {
-  "video/mp4",
-  "video/3gpp",
-  "video/quicktime",
-};
-
-bool
-nsHTMLMediaElement::IsH264Type(const nsACString& aType)
-{
-  for (uint32_t i = 0; i < ArrayLength(gH264Types); ++i) {
-    if (aType.EqualsASCII(gH264Types[i])) {
-      return true;
-    }
-  }
-  return false;
-}
-#endif
-
-#ifdef MOZ_WIDGET_GONK
-const char nsHTMLMediaElement::gOmxTypes[5][16] = {
-  "audio/mpeg",
-  "audio/mp4",
-  "video/mp4",
-  "video/3gpp",
-  "video/quicktime",
-};
-
-bool
-nsHTMLMediaElement::IsOmxSupportedType(const nsACString& aType)
-{
-  if (!MediaDecoder::IsOmxEnabled()) {
-    return false;
-  }
-
-  for (uint32_t i = 0; i < ArrayLength(gOmxTypes); ++i) {
-    if (aType.EqualsASCII(gOmxTypes[i])) {
-      return true;
-    }
-  }
-
-  return false;
-}
-#endif
-
-#ifdef MOZ_MEDIA_PLUGINS
-bool
-nsHTMLMediaElement::IsMediaPluginsType(const nsACString& aType)
-{
-  if (!MediaDecoder::IsMediaPluginsEnabled()) {
-    return false;
-  }
-
-  static const char* supportedTypes[] = {
-    "audio/mpeg", "audio/mp4", "video/mp4"
-  };
-  for (uint32_t i = 0; i < ArrayLength(supportedTypes); ++i) {
-    if (aType.EqualsASCII(supportedTypes[i])) {
-      return true;
-    }
-  }
-  return false;
-}
-#endif
-
-#ifdef MOZ_DASH
-/* static */
-const char nsHTMLMediaElement::gDASHMPDTypes[1][21] = {
-  "application/dash+xml"
-};
-
-/* static */
-bool
-nsHTMLMediaElement::IsDASHMPDType(const nsACString& aType)
-{
-  if (!MediaDecoder::IsDASHEnabled()) {
-    return false;
-  }
-
-  for (uint32_t i = 0; i < ArrayLength(gDASHMPDTypes); ++i) {
-    if (aType.EqualsASCII(gDASHMPDTypes[i])) {
-      return true;
-    }
-  }
-
-  return false;
-}
-#endif
-
-/* static */
-nsHTMLMediaElement::CanPlayStatus
-nsHTMLMediaElement::CanHandleMediaType(const char* aMIMEType,
-                                       char const *const ** aCodecList)
-{
-#ifdef MOZ_RAW
-  if (IsRawType(nsDependentCString(aMIMEType))) {
-    *aCodecList = gRawCodecs;
-    return CANPLAY_MAYBE;
-  }
-#endif
-#ifdef MOZ_OGG
-  if (IsOggType(nsDependentCString(aMIMEType))) {
-    *aCodecList = MediaDecoder::IsOpusEnabled() ? gOggCodecsWithOpus : gOggCodecs;
-    return CANPLAY_MAYBE;
-  }
-#endif
-#ifdef MOZ_WAVE
-  if (IsWaveType(nsDependentCString(aMIMEType))) {
-    *aCodecList = gWaveCodecs;
-    return CANPLAY_MAYBE;
-  }
-#endif
-#ifdef MOZ_WEBM
-  if (IsWebMType(nsDependentCString(aMIMEType))) {
-    *aCodecList = gWebMCodecs;
-    return CANPLAY_YES;
-  }
-#endif
-#ifdef MOZ_DASH
-  if (IsDASHMPDType(nsDependentCString(aMIMEType))) {
-    // DASH manifest uses WebM codecs only.
-    *aCodecList = gWebMCodecs;
-    return CANPLAY_YES;
-  }
-#endif
-
-#ifdef MOZ_GSTREAMER
-  if (IsH264Type(nsDependentCString(aMIMEType))) {
-    *aCodecList = gH264Codecs;
-    return CANPLAY_MAYBE;
-  }
-#endif
-#ifdef MOZ_WIDGET_GONK
-  if (IsOmxSupportedType(nsDependentCString(aMIMEType))) {
-    *aCodecList = gH264Codecs;
-    return CANPLAY_MAYBE;
-  }
-#endif
-#ifdef MOZ_MEDIA_PLUGINS
-  if (MediaDecoder::IsMediaPluginsEnabled() && GetMediaPluginHost()->FindDecoder(nsDependentCString(aMIMEType), aCodecList))
-    return CANPLAY_MAYBE;
-#endif
-  return CANPLAY_NO;
-}
-
-/* static */
-bool nsHTMLMediaElement::ShouldHandleMediaType(const char* aMIMEType)
-{
-#ifdef MOZ_RAW
-  if (IsRawType(nsDependentCString(aMIMEType)))
-    return true;
-#endif
-#ifdef MOZ_OGG
-  if (IsOggType(nsDependentCString(aMIMEType)))
-    return true;
-#endif
-#ifdef MOZ_WEBM
-  if (IsWebMType(nsDependentCString(aMIMEType)))
-    return true;
-#endif
-#ifdef MOZ_GSTREAMER
-  if (IsH264Type(nsDependentCString(aMIMEType)))
-    return true;
-#endif
-#ifdef MOZ_WIDGET_GONK
-  if (IsOmxSupportedType(nsDependentCString(aMIMEType))) {
-    return true;
-  }
-#endif
-#ifdef MOZ_MEDIA_PLUGINS
-  if (MediaDecoder::IsMediaPluginsEnabled() && GetMediaPluginHost()->FindDecoder(nsDependentCString(aMIMEType), NULL))
-    return true;
-#endif
-  // We should not return true for Wave types, since there are some
-  // Wave codecs actually in use in the wild that we don't support, and
-  // we should allow those to be handled by plugins or helper apps.
-  // Furthermore people can play Wave files on most platforms by other
-  // means.
-  return false;
-}
-
 static bool
 CodecListContains(char const *const * aCodecs, const nsAString& aCodec)
 {
   for (int32_t i = 0; aCodecs[i]; ++i) {
     if (aCodec.EqualsASCII(aCodecs[i]))
       return true;
   }
   return false;
 }
 
 /* static */
-nsHTMLMediaElement::CanPlayStatus
+CanPlayStatus
 nsHTMLMediaElement::GetCanPlay(const nsAString& aType)
 {
   nsContentTypeParser parser(aType);
   nsAutoString mimeType;
   nsresult rv = parser.GetType(mimeType);
   if (NS_FAILED(rv))
     return CANPLAY_NO;
 
   NS_ConvertUTF16toUTF8 mimeTypeUTF8(mimeType);
   char const *const * supportedCodecs;
-  CanPlayStatus status = CanHandleMediaType(mimeTypeUTF8.get(),
-                                            &supportedCodecs);
+  CanPlayStatus status = DecoderTraits::CanHandleMediaType(mimeTypeUTF8.get(),
+                                                           &supportedCodecs);
   if (status == CANPLAY_NO)
     return CANPLAY_NO;
 
   nsAutoString codecs;
   rv = parser.GetParameter("codecs", codecs);
   if (NS_FAILED(rv)) {
     // Parameter not found or whatever
     return status;
@@ -2439,104 +2117,82 @@ nsHTMLMediaElement::CanPlayType(const ns
   default:
   case CANPLAY_MAYBE:
     aResult.AssignLiteral("maybe");
     break;
   }
   return NS_OK;
 }
 
-#ifdef MOZ_GSTREAMER
-bool
-nsHTMLMediaElement::IsGStreamerSupportedType(const nsACString& aMimeType)
-{
-  if (!MediaDecoder::IsGStreamerEnabled())
-    return false;
-  if (IsH264Type(aMimeType))
-    return true;
-  if (!Preferences::GetBool("media.prefer-gstreamer", false))
-    return false;
-#ifdef MOZ_WEBM
-  if (IsWebMType(aMimeType))
-    return true;
-#endif
-#ifdef MOZ_OGG
-  if (IsOggType(aMimeType))
-    return true;
-#endif
-  return false;
-}
-#endif
-
 already_AddRefed<MediaDecoder>
 nsHTMLMediaElement::CreateDecoder(const nsACString& aType)
 {
 
 #ifdef MOZ_GSTREAMER
   // When enabled, use GStreamer for H.264, but not for codecs handled by our
   // bundled decoders, unless the "media.prefer-gstreamer" pref is set.
-  if (IsGStreamerSupportedType(aType)) {
+  if (DecoderTraits::IsGStreamerSupportedType(aType)) {
     nsRefPtr<GStreamerDecoder> decoder = new GStreamerDecoder();
     if (decoder->Init(this)) {
       return decoder.forget();
     }
   }
 #endif
 
 #ifdef MOZ_RAW
-  if (IsRawType(aType)) {
+  if (DecoderTraits::IsRawType(aType)) {
     nsRefPtr<RawDecoder> decoder = new RawDecoder();
     if (decoder->Init(this)) {
       return decoder.forget();
     }
   }
 #endif
 #ifdef MOZ_OGG
-  if (IsOggType(aType)) {
+  if (DecoderTraits::IsOggType(aType)) {
     nsRefPtr<OggDecoder> decoder = new OggDecoder();
     if (decoder->Init(this)) {
       return decoder.forget();
     }
   }
 #endif
 #ifdef MOZ_WAVE
-  if (IsWaveType(aType)) {
+  if (DecoderTraits::IsWaveType(aType)) {
     nsRefPtr<WaveDecoder> decoder = new WaveDecoder();
     if (decoder->Init(this)) {
       return decoder.forget();
     }
   }
 #endif
 #ifdef MOZ_WIDGET_GONK
-  if (IsOmxSupportedType(aType)) {
+  if (DecoderTraits::IsOmxSupportedType(aType)) {
     nsRefPtr<MediaOmxDecoder> decoder = new MediaOmxDecoder();
     if (decoder->Init(this)) {
       return decoder.forget();
     }
   }
 #endif
 #ifdef MOZ_MEDIA_PLUGINS
   if (MediaDecoder::IsMediaPluginsEnabled() && GetMediaPluginHost()->FindDecoder(aType, NULL)) {
     nsRefPtr<MediaPluginDecoder> decoder = new MediaPluginDecoder(aType);
     if (decoder->Init(this)) {
       return decoder.forget();
     }
   }
 #endif
 #ifdef MOZ_WEBM
-  if (IsWebMType(aType)) {
+  if (DecoderTraits::IsWebMType(aType)) {
     nsRefPtr<WebMDecoder> decoder = new WebMDecoder();
     if (decoder->Init(this)) {
       return decoder.forget();
     }
   }
 #endif
 
 #ifdef MOZ_DASH
-  if (IsDASHMPDType(aType)) {
+  if (DecoderTraits::IsDASHMPDType(aType)) {
     nsRefPtr<DASHDecoder> decoder = new DASHDecoder();
     if (decoder->Init(this)) {
       return decoder.forget();
     }
   }
 #endif
 
   return nullptr;
new file mode 100644
--- /dev/null
+++ b/content/media/DecoderTraits.cpp
@@ -0,0 +1,362 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "DecoderTraits.h"
+#include "MediaDecoder.h"
+#ifdef MOZ_MEDIA_PLUGINS
+#include "MediaPluginHost.h"
+#endif
+
+namespace mozilla
+{
+
+#ifdef MOZ_RAW
+static const char gRawTypes[2][16] = {
+  "video/x-raw",
+  "video/x-raw-yuv"
+};
+
+static const char* gRawCodecs[1] = {
+  nullptr
+};
+
+/* static */
+bool
+DecoderTraits::IsRawType(const nsACString& aType)
+{
+  if (!MediaDecoder::IsRawEnabled()) {
+    return false;
+  }
+
+  for (uint32_t i = 0; i < ArrayLength(gRawTypes); ++i) {
+    if (aType.EqualsASCII(gRawTypes[i])) {
+      return true;
+    }
+  }
+
+  return false;
+}
+#endif
+
+#ifdef MOZ_OGG
+// See http://www.rfc-editor.org/rfc/rfc5334.txt for the definitions
+// of Ogg media types and codec types
+static const char gOggTypes[3][16] = {
+  "video/ogg",
+  "audio/ogg",
+  "application/ogg"
+};
+
+static char const *const gOggCodecs[3] = {
+  "vorbis",
+  "theora",
+  nullptr
+};
+
+static char const *const gOggCodecsWithOpus[4] = {
+  "vorbis",
+  "opus",
+  "theora",
+  nullptr
+};
+
+bool
+DecoderTraits::IsOggType(const nsACString& aType)
+{
+  if (!MediaDecoder::IsOggEnabled()) {
+    return false;
+  }
+
+  for (uint32_t i = 0; i < ArrayLength(gOggTypes); ++i) {
+    if (aType.EqualsASCII(gOggTypes[i])) {
+      return true;
+    }
+  }
+
+  return false;
+}
+#endif
+
+#ifdef MOZ_WAVE
+// See http://www.rfc-editor.org/rfc/rfc2361.txt for the definitions
+// of WAVE media types and codec types. However, the audio/vnd.wave
+// MIME type described there is not used.
+static const char gWaveTypes[4][15] = {
+  "audio/x-wav",
+  "audio/wav",
+  "audio/wave",
+  "audio/x-pn-wav"
+};
+
+static char const *const gWaveCodecs[2] = {
+  "1", // Microsoft PCM Format
+  nullptr
+};
+
+bool
+DecoderTraits::IsWaveType(const nsACString& aType)
+{
+  if (!MediaDecoder::IsWaveEnabled()) {
+    return false;
+  }
+
+  for (uint32_t i = 0; i < ArrayLength(gWaveTypes); ++i) {
+    if (aType.EqualsASCII(gWaveTypes[i])) {
+      return true;
+    }
+  }
+
+  return false;
+}
+#endif
+
+#ifdef MOZ_WEBM
+static const char gWebMTypes[2][11] = {
+  "video/webm",
+  "audio/webm"
+};
+
+static char const *const gWebMCodecs[4] = {
+  "vp8",
+  "vp8.0",
+  "vorbis",
+  nullptr
+};
+
+bool
+DecoderTraits::IsWebMType(const nsACString& aType)
+{
+  if (!MediaDecoder::IsWebMEnabled()) {
+    return false;
+  }
+
+  for (uint32_t i = 0; i < ArrayLength(gWebMTypes); ++i) {
+    if (aType.EqualsASCII(gWebMTypes[i])) {
+      return true;
+    }
+  }
+
+  return false;
+}
+#endif
+
+#ifdef MOZ_GSTREAMER
+static const char gH264Types[3][16] = {
+  "video/mp4",
+  "video/3gpp",
+  "video/quicktime",
+};
+
+bool
+DecoderTraits::IsGStreamerSupportedType(const nsACString& aMimeType)
+{
+  if (!MediaDecoder::IsGStreamerEnabled())
+    return false;
+  if (IsH264Type(aMimeType))
+    return true;
+  if (!Preferences::GetBool("media.prefer-gstreamer", false))
+    return false;
+#ifdef MOZ_WEBM
+  if (IsWebMType(aMimeType))
+    return true;
+#endif
+#ifdef MOZ_OGG
+  if (IsOggType(aMimeType))
+    return true;
+#endif
+  return false;
+}
+
+bool
+DecoderTraits::IsH264Type(const nsACString& aType)
+{
+  for (uint32_t i = 0; i < ArrayLength(gH264Types); ++i) {
+    if (aType.EqualsASCII(gH264Types[i])) {
+      return true;
+    }
+  }
+  return false;
+}
+#endif
+
+#ifdef MOZ_WIDGET_GONK
+static const char gOmxTypes[5][16] = {
+  "audio/mpeg",
+  "audio/mp4",
+  "video/mp4",
+  "video/3gpp",
+  "video/quicktime",
+};
+
+bool
+DecoderTraits::IsOmxSupportedType(const nsACString& aType)
+{
+  if (!MediaDecoder::IsOmxEnabled()) {
+    return false;
+  }
+
+  for (uint32_t i = 0; i < ArrayLength(gOmxTypes); ++i) {
+    if (aType.EqualsASCII(gOmxTypes[i])) {
+      return true;
+    }
+  }
+
+  return false;
+}
+#endif
+
+#if defined(MOZ_GSTREAMER) || defined(MOZ_WIDGET_GONK)
+static char const *const gH264Codecs[9] = {
+  "avc1.42E01E",  // H.264 Constrained Baseline Profile Level 3.0
+  "avc1.42001E",  // H.264 Baseline Profile Level 3.0
+  "avc1.58A01E",  // H.264 Extended Profile Level 3.0
+  "avc1.4D401E",  // H.264 Main Profile Level 3.0
+  "avc1.64001E",  // H.264 High Profile Level 3.0
+  "avc1.64001F",  // H.264 High Profile Level 3.1
+  "mp4v.20.3",    // 3GPP
+  "mp4a.40.2",    // AAC-LC
+  nullptr
+};
+#endif
+
+#ifdef MOZ_MEDIA_PLUGINS
+bool
+DecoderTraits::IsMediaPluginsType(const nsACString& aType)
+{
+  if (!MediaDecoder::IsMediaPluginsEnabled()) {
+    return false;
+  }
+
+  static const char* supportedTypes[] = {
+    "audio/mpeg", "audio/mp4", "video/mp4"
+  };
+  for (uint32_t i = 0; i < ArrayLength(supportedTypes); ++i) {
+    if (aType.EqualsASCII(supportedTypes[i])) {
+      return true;
+    }
+  }
+  return false;
+}
+#endif
+
+#ifdef MOZ_DASH
+/* static */
+static const char gDASHMPDTypes[1][21] = {
+  "application/dash+xml"
+};
+
+/* static */
+bool
+DecoderTraits::IsDASHMPDType(const nsACString& aType)
+{
+  if (!MediaDecoder::IsDASHEnabled()) {
+    return false;
+  }
+
+  for (uint32_t i = 0; i < ArrayLength(gDASHMPDTypes); ++i) {
+    if (aType.EqualsASCII(gDASHMPDTypes[i])) {
+      return true;
+    }
+  }
+
+  return false;
+}
+#endif
+
+/* static */
+bool DecoderTraits::ShouldHandleMediaType(const char* aMIMEType)
+{
+#ifdef MOZ_RAW
+  if (IsRawType(nsDependentCString(aMIMEType)))
+    return true;
+#endif
+#ifdef MOZ_OGG
+  if (IsOggType(nsDependentCString(aMIMEType)))
+    return true;
+#endif
+#ifdef MOZ_WEBM
+  if (IsWebMType(nsDependentCString(aMIMEType)))
+    return true;
+#endif
+#ifdef MOZ_GSTREAMER
+  if (IsH264Type(nsDependentCString(aMIMEType)))
+    return true;
+#endif
+#ifdef MOZ_WIDGET_GONK
+  if (IsOmxSupportedType(nsDependentCString(aMIMEType))) {
+    return true;
+  }
+#endif
+#ifdef MOZ_MEDIA_PLUGINS
+  if (MediaDecoder::IsMediaPluginsEnabled() && GetMediaPluginHost()->FindDecoder(nsDependentCString(aMIMEType), NULL))
+    return true;
+#endif
+  // We should not return true for Wave types, since there are some
+  // Wave codecs actually in use in the wild that we don't support, and
+  // we should allow those to be handled by plugins or helper apps.
+  // Furthermore people can play Wave files on most platforms by other
+  // means.
+  return false;
+}
+
+/* static */
+CanPlayStatus
+DecoderTraits::CanHandleMediaType(const char* aMIMEType,
+                                       char const *const ** aCodecList)
+{
+#ifdef MOZ_RAW
+  if (IsRawType(nsDependentCString(aMIMEType))) {
+    *aCodecList = gRawCodecs;
+    return CANPLAY_MAYBE;
+  }
+#endif
+#ifdef MOZ_OGG
+  if (IsOggType(nsDependentCString(aMIMEType))) {
+    *aCodecList = MediaDecoder::IsOpusEnabled() ? gOggCodecsWithOpus : gOggCodecs;
+    return CANPLAY_MAYBE;
+  }
+#endif
+#ifdef MOZ_WAVE
+  if (IsWaveType(nsDependentCString(aMIMEType))) {
+    *aCodecList = gWaveCodecs;
+    return CANPLAY_MAYBE;
+  }
+#endif
+#ifdef MOZ_WEBM
+  if (IsWebMType(nsDependentCString(aMIMEType))) {
+    *aCodecList = gWebMCodecs;
+    return CANPLAY_YES;
+  }
+#endif
+#ifdef MOZ_DASH
+  if (IsDASHMPDType(nsDependentCString(aMIMEType))) {
+    // DASH manifest uses WebM codecs only.
+    *aCodecList = gWebMCodecs;
+    return CANPLAY_YES;
+  }
+#endif
+
+#ifdef MOZ_GSTREAMER
+  if (IsH264Type(nsDependentCString(aMIMEType))) {
+    *aCodecList = gH264Codecs;
+    return CANPLAY_MAYBE;
+  }
+#endif
+#ifdef MOZ_WIDGET_GONK
+  if (IsOmxSupportedType(nsDependentCString(aMIMEType))) {
+    *aCodecList = gH264Codecs;
+    return CANPLAY_MAYBE;
+  }
+#endif
+#ifdef MOZ_MEDIA_PLUGINS
+  if (MediaDecoder::IsMediaPluginsEnabled() && GetMediaPluginHost()->FindDecoder(nsDependentCString(aMIMEType), aCodecList))
+    return CANPLAY_MAYBE;
+#endif
+  return CANPLAY_NO;
+}
+
+}
+
new file mode 100644
--- /dev/null
+++ b/content/media/DecoderTraits.h
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef DecoderTraits_h_
+#define DecoderTraits_h_
+
+#include "nsAString.h"
+
+namespace mozilla
+{
+
+enum CanPlayStatus {
+  CANPLAY_NO,
+  CANPLAY_MAYBE,
+  CANPLAY_YES
+};
+
+class DecoderTraits {
+public:
+  // Returns the CanPlayStatus indicating if we can handle this
+  // MIME type. The MIME type should not include the codecs parameter.
+  // If it returns anything other than CANPLAY_NO then it also
+  // returns a null-terminated list of supported codecs
+  // in *aSupportedCodecs. This list should not be freed, it is static data.
+  static CanPlayStatus CanHandleMediaType(const char* aMIMEType,
+                                          char const *const ** aSupportedCodecs);
+
+  // Returns true if we should handle this MIME type when it appears
+  // as an <object> or as a toplevel page. If, in practice, our support
+  // 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);
+
+#ifdef MOZ_RAW
+  static bool IsRawType(const nsACString& aType);
+#endif
+
+#ifdef MOZ_OGG
+  static bool IsOggType(const nsACString& aType);
+#endif
+
+#ifdef MOZ_WAVE
+  static bool IsWaveType(const nsACString& aType);
+#endif
+
+#ifdef MOZ_WEBM
+  static bool IsWebMType(const nsACString& aType);
+#endif
+
+#ifdef MOZ_GSTREAMER
+  static bool IsGStreamerSupportedType(const nsACString& aType);
+  static bool IsH264Type(const nsACString& aType);
+#endif
+
+#ifdef MOZ_WIDGET_GONK
+  static bool IsOmxSupportedType(const nsACString& aType);
+#endif
+
+#ifdef MOZ_MEDIA_PLUGINS
+  static bool IsMediaPluginsType(const nsACString& aType);
+#endif
+
+#ifdef MOZ_DASH
+  static bool IsDASHMPDType(const nsACString& aType);
+#endif
+
+};
+
+}
+
+#endif
+
--- a/content/media/Makefile.in
+++ b/content/media/Makefile.in
@@ -13,16 +13,17 @@ include $(DEPTH)/config/autoconf.mk
 MODULE = content
 LIBRARY_NAME = gkconmedia_s
 LIBXUL_LIBRARY = 1
 
 EXPORTS = \
   AbstractMediaDecoder.h \
   AudioSampleFormat.h \
   AudioSegment.h \
+  DecoderTraits.h \
   FileBlockCache.h \
   MediaDecoderOwner.h \
   MediaResource.h \
   MediaSegment.h \
   MediaStreamGraph.h \
   AudioAvailableEventManager.h \
   MediaDecoder.h \
   MediaDecoderStateMachine.h \
@@ -35,16 +36,17 @@ EXPORTS = \
   VideoFrameContainer.h \
   VideoUtils.h \
   VideoSegment.h \
   VorbisUtils.h \
   $(NULL)
 
 CPPSRCS = \
   AudioSegment.cpp \
+  DecoderTraits.cpp \
   FileBlockCache.cpp \
   MediaResource.cpp \
   MediaStreamGraph.cpp \
   AudioAvailableEventManager.cpp \
   MediaDecoder.cpp \
   MediaDecoderStateMachine.cpp \
   MediaDecoderReader.cpp \
   nsDOMMediaStream.cpp \
--- a/layout/build/nsContentDLF.cpp
+++ b/layout/build/nsContentDLF.cpp
@@ -18,23 +18,21 @@
 #include "nsNodeInfoManager.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsString.h"
 #include "nsContentCID.h"
 #include "prprf.h"
 #include "nsNetUtil.h"
 #include "nsCRT.h"
 #include "nsIViewSourceChannel.h"
-#ifdef MOZ_MEDIA
-#include "nsHTMLMediaElement.h"
-#endif
 #include "nsContentUtils.h"
 #include "imgLoader.h"
 #include "nsCharsetSource.h"
 #include "nsMimeTypes.h"
+#include "DecoderTraits.h"
 
 
 // plugins
 #include "nsIPluginHost.h"
 #include "nsPluginHost.h"
 static NS_DEFINE_CID(kPluginDocumentCID, NS_PLUGINDOCUMENT_CID);
 
 // Factory code for creating variations on html documents
@@ -244,17 +242,17 @@ nsContentDLF::CreateInstance(const char*
       return CreateXULDocument(aCommand,
                                aChannel, aLoadGroup,
                                aContentType, aContainer,
                                aExtraInfo, aDocListener, aDocViewer);
     }
   }
 
 #ifdef MOZ_MEDIA
-  if (nsHTMLMediaElement::ShouldHandleMediaType(aContentType)) {
+  if (mozilla::DecoderTraits::ShouldHandleMediaType(aContentType)) {
     return CreateDocument(aCommand, 
                           aChannel, aLoadGroup,
                           aContainer, kVideoDocumentCID,
                           aDocListener, aDocViewer);
   }  
 #endif
 
   // Try image types