Bug 1208348 - Check whether DirectShow can decode MP3 before assuming it will work. r=jya
authorChris Pearce <cpearce@mozilla.com>
Mon, 28 Sep 2015 14:03:04 +1300
changeset 264588 9f73b03732fcd4902ddf5f8cb8f3dc6dea1eeaf0
parent 264587 8ba00818a9fa6341a7e6bb393f90569762feb5d6
child 264589 bc6762f527751c6ff993f55d54344c5a0dfcf721
push id65685
push usercpearce@mozilla.com
push dateMon, 28 Sep 2015 01:03:51 +0000
treeherdermozilla-inbound@28ede868e68c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya
bugs1208348
milestone44.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 1208348 - Check whether DirectShow can decode MP3 before assuming it will work. r=jya
dom/media/directshow/DirectShowDecoder.cpp
dom/media/directshow/DirectShowUtils.cpp
dom/media/directshow/DirectShowUtils.h
--- a/dom/media/directshow/DirectShowDecoder.cpp
+++ b/dom/media/directshow/DirectShowDecoder.cpp
@@ -40,17 +40,18 @@ DirectShowDecoder::GetSupportedCodecs(co
 
   return false;
 }
 
 /* static */
 bool
 DirectShowDecoder::IsEnabled()
 {
-  return Preferences::GetBool("media.directshow.enabled");
+  return CanDecodeMP3UsingDirectShow() &&
+         Preferences::GetBool("media.directshow.enabled");
 }
 
 DirectShowDecoder::DirectShowDecoder()
 {
   MOZ_COUNT_CTOR(DirectShowDecoder);
 }
 
 DirectShowDecoder::~DirectShowDecoder()
--- a/dom/media/directshow/DirectShowUtils.cpp
+++ b/dom/media/directshow/DirectShowUtils.cpp
@@ -203,20 +203,18 @@ CreateAndAddFilter(IGraphBuilder* aGraph
   }
 
   filter.forget(aOutFilter);
 
   return S_OK;
 }
 
 HRESULT
-AddMP3DMOWrapperFilter(IGraphBuilder* aGraph,
-                       IBaseFilter **aOutFilter)
+CreateMP3DMOWrapperFilter(IBaseFilter **aOutFilter)
 {
-  NS_ENSURE_TRUE(aGraph, E_POINTER);
   NS_ENSURE_TRUE(aOutFilter, E_POINTER);
   HRESULT hr;
 
   // Create the wrapper filter.
   nsRefPtr<IBaseFilter> filter;
   hr = CoCreateInstance(CLSID_DMOWrapperFilter,
                         nullptr,
                         CLSCTX_INPROC_SERVER,
@@ -240,28 +238,73 @@ AddMP3DMOWrapperFilter(IGraphBuilder* aG
   if (FAILED(hr)) {
     // Can't instantiate MP3 DMO. It doesn't exist on Windows XP, we're
     // probably hitting that. Don't log warning to console, this is an
     // expected error.
     WARN("dmoWrapper Init failed, hr=%x", hr);
     return hr;
   }
 
+  return S_OK;
+}
+
+HRESULT
+AddMP3DMOWrapperFilter(IGraphBuilder* aGraph,
+                       IBaseFilter **aOutFilter)
+{
+  NS_ENSURE_TRUE(aGraph, E_POINTER);
+  NS_ENSURE_TRUE(aOutFilter, E_POINTER);
+  HRESULT hr;
+
+  // Create the wrapper filter.
+  nsRefPtr<IBaseFilter> filter;
+  hr = CreateMP3DMOWrapperFilter(getter_AddRefs(filter));
+  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
+
   // Add the wrapper filter to graph.
   hr = aGraph->AddFilter(filter, L"MP3 Decoder DMO");
   if (FAILED(hr)) {
     WARN("AddFilter failed, hr=%x", hr);
     return hr;
   }
 
   filter.forget(aOutFilter);
 
   return S_OK;
 }
 
+bool
+CanDecodeMP3UsingDirectShow()
+{
+  nsRefPtr<IBaseFilter> filter;
+
+  // Can we create the MP3 demuxer filter?
+  if (FAILED(CoCreateInstance(CLSID_MPEG1Splitter,
+                              nullptr,
+                              CLSCTX_INPROC_SERVER,
+                              IID_IBaseFilter,
+                              getter_AddRefs(filter)))) {
+    return false;
+  }
+
+  // Can we create either the WinXP MP3 decoder filter or the MP3 DMO decoder?
+  if (FAILED(CoCreateInstance(CLSID_MPEG_LAYER_3_DECODER_FILTER,
+                              nullptr,
+                              CLSCTX_INPROC_SERVER,
+                              IID_IBaseFilter,
+                              getter_AddRefs(filter))) &&
+      FAILED(CreateMP3DMOWrapperFilter(getter_AddRefs(filter)))) {
+    return false;
+  }
+
+  // Else, we can create all of the components we need. Assume
+  // DirectShow is going to work...
+  return true;
+}
+
 // Match a pin by pin direction and connection state.
 HRESULT
 MatchUnconnectedPin(IPin* aPin,
                     PIN_DIRECTION aPinDir,
                     bool *aOutMatches)
 {
   NS_ENSURE_TRUE(aPin, E_POINTER);
   NS_ENSURE_TRUE(aOutMatches, E_POINTER);
--- a/dom/media/directshow/DirectShowUtils.h
+++ b/dom/media/directshow/DirectShowUtils.h
@@ -110,11 +110,16 @@ inline double
 RefTimeToSeconds(const REFERENCE_TIME aRefTime)
 {
   return double(aRefTime) / 10000000;
 }
 
 const char*
 GetDirectShowGuidName(const GUID& aGuid);
 
+// Returns true if we can instantiate an MP3 demuxer and decoder filters.
+// Use this to detect whether MP3 support is installed.
+bool
+CanDecodeMP3UsingDirectShow();
+
 } // namespace mozilla
 
 #endif