Bug 1056032 - Make sure COM is initialized when trying to decode an mp3 using decodeAudioData. r=cpearce, a=lmandel
--- a/content/media/SharedThreadPool.cpp
+++ b/content/media/SharedThreadPool.cpp
@@ -6,20 +6,18 @@
#include "SharedThreadPool.h"
#include "mozilla/Monitor.h"
#include "mozilla/StaticPtr.h"
#include "nsDataHashtable.h"
#include "VideoUtils.h"
#include "nsXPCOMCIDInternal.h"
#include "nsComponentManagerUtils.h"
-
#ifdef XP_WIN
-// Required to init MSCOM by MSCOMInitThreadPoolListener.
-#include <objbase.h>
+#include "ThreadPoolCOMListener.h"
#endif
namespace mozilla {
// Created and destroyed on the main thread.
static StaticAutoPtr<ReentrantMonitor> sMonitor;
// Hashtable, maps thread pool name to SharedThreadPool instance.
@@ -182,48 +180,16 @@ SharedThreadPool::SharedThreadPool(const
mEventTarget = do_QueryInterface(aPool);
}
SharedThreadPool::~SharedThreadPool()
{
MOZ_COUNT_DTOR(SharedThreadPool);
}
-#ifdef XP_WIN
-
-// Thread pool listener which ensures that MSCOM is initialized and
-// deinitialized on the thread pool thread. We may call into WMF or
-// DirectShow on this thread, so we need MSCOM working.
-class MSCOMInitThreadPoolListener MOZ_FINAL : public nsIThreadPoolListener {
-public:
- NS_DECL_THREADSAFE_ISUPPORTS
- NS_DECL_NSITHREADPOOLLISTENER
-};
-
-NS_IMPL_ISUPPORTS(MSCOMInitThreadPoolListener, nsIThreadPoolListener)
-
-NS_IMETHODIMP
-MSCOMInitThreadPoolListener::OnThreadCreated()
-{
- HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
- if (FAILED(hr)) {
- NS_WARNING("Failed to initialize MSCOM on WMFByteStream thread.");
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-MSCOMInitThreadPoolListener::OnThreadShuttingDown()
-{
- CoUninitialize();
- return NS_OK;
-}
-
-#endif // XP_WIN
-
nsresult
SharedThreadPool::EnsureThreadLimitIsAtLeast(uint32_t aLimit)
{
// We limit the number of threads that we use for media. Note that we
// set the thread limit to the same as the idle limit so that we're not
// constantly creating and destroying threads (see Bug 881954). When the
// thread pool threads shutdown they dispatch an event to the main thread
// to call nsIThread::Shutdown(), and if we're very busy that can take a
new file mode 100644
--- /dev/null
+++ b/content/media/ThreadPoolCOMListener.cpp
@@ -0,0 +1,30 @@
+/* -*- 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 "ThreadPoolCOMListener.h"
+
+namespace mozilla {
+
+NS_IMPL_ISUPPORTS(MSCOMInitThreadPoolListener, nsIThreadPoolListener)
+
+NS_IMETHODIMP
+MSCOMInitThreadPoolListener::OnThreadCreated()
+{
+ HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
+ if (FAILED(hr)) {
+ NS_WARNING("Failed to initialize MSCOM on decoder thread.");
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+MSCOMInitThreadPoolListener::OnThreadShuttingDown()
+{
+ CoUninitialize();
+ return NS_OK;
+}
+
+}
new file mode 100644
--- /dev/null
+++ b/content/media/ThreadPoolCOMListener.h
@@ -0,0 +1,28 @@
+/* -*- 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 MSCOMInitThreadPoolListener_h_
+#define MSCOMInitThreadPoolListener_h_
+
+#include "nsIThreadPool.h"
+#include <objbase.h>
+
+namespace mozilla {
+
+// Thread pool listener which ensures that MSCOM is initialized and
+// deinitialized on the thread pool thread. We may call into WMF or
+// DirectShow on this thread, so we need MSCOM working.
+class MSCOMInitThreadPoolListener MOZ_FINAL : public nsIThreadPoolListener {
+ ~MSCOMInitThreadPoolListener() {}
+ public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSITHREADPOOLLISTENER
+};
+
+} // namespace mozilla
+
+
+#endif // MSCOMInitThreadPoolListener_h_
--- a/content/media/moz.build
+++ b/content/media/moz.build
@@ -90,16 +90,17 @@ EXPORTS += [
'MediaSegment.h',
'MediaStreamGraph.h',
'MediaTaskQueue.h',
'MP3FrameParser.h',
'RtspMediaResource.h',
'SharedBuffer.h',
'SharedThreadPool.h',
'StreamBuffer.h',
+ 'ThreadPoolCOMListener.h',
'TimeVarying.h',
'TrackUnionStream.h',
'VideoFrameContainer.h',
'VideoSegment.h',
'VideoUtils.h',
'VorbisUtils.h',
]
@@ -151,16 +152,19 @@ UNIFIED_SOURCES += [
'VideoFrameContainer.cpp',
'VideoPlaybackQuality.cpp',
'VideoSegment.cpp',
'VideoStreamTrack.cpp',
'VideoUtils.cpp',
'WebVTTListener.cpp',
]
+if CONFIG['OS_TARGET'] == 'WINNT':
+ SOURCES += [ 'ThreadPoolCOMListener.cpp' ]
+
# DecoderTraits.cpp needs to be built separately because of Mac OS X headers.
# Latency.cpp needs to be built separately because it forces NSPR logging.
SOURCES += [
'DecoderTraits.cpp',
'Latency.cpp',
]
FAIL_ON_WARNINGS = True
--- a/content/media/webaudio/MediaBufferDecoder.cpp
+++ b/content/media/webaudio/MediaBufferDecoder.cpp
@@ -15,16 +15,19 @@
#include "BufferMediaResource.h"
#include "DecoderTraits.h"
#include "AudioContext.h"
#include "AudioBuffer.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsIScriptError.h"
#include "nsMimeTypes.h"
#include "WebAudioUtils.h"
+#ifdef XP_WIN
+#include "ThreadPoolCOMListener.h"
+#endif
namespace mozilla {
NS_IMPL_CYCLE_COLLECTION_CLASS(WebAudioDecodeJob)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WebAudioDecodeJob)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutput)
@@ -469,16 +472,22 @@ bool
MediaBufferDecoder::EnsureThreadPoolInitialized()
{
if (!mThreadPool) {
mThreadPool = do_CreateInstance(NS_THREADPOOL_CONTRACTID);
if (!mThreadPool) {
return false;
}
mThreadPool->SetName(NS_LITERAL_CSTRING("MediaBufferDecoder"));
+#ifdef XP_WIN
+ // Ensure MSCOM is initialized on the thread pools threads.
+ nsCOMPtr<nsIThreadPoolListener> listener = new MSCOMInitThreadPoolListener();
+ nsresult rv = mThreadPool->SetListener(listener);
+ NS_ENSURE_SUCCESS(rv, nullptr);
+#endif
}
return true;
}
void
MediaBufferDecoder::Shutdown() {
if (mThreadPool) {
// Setting threadLimit to 0 causes threads to exit when all events have