forked from pool/MozillaFirefox
e44b8338d6
* removed upstreamed patch firefox-712763.patch * removed disabled mozilla-disable-neon-option.patch OBS-URL: https://build.opensuse.org/package/show/mozilla:Factory/MozillaFirefox?expand=0&rev=333
542 lines
16 KiB
Diff
542 lines
16 KiB
Diff
# HG changeset patch
|
|
# Parent 74ba8ebd0dc72be84280bd4806f84d9ec1f4e130
|
|
Bug 760140 - Query the GstRegistry for the required demuxers/decoders from canPlayType (TM: 22)
|
|
|
|
diff --git a/content/media/DecoderTraits.cpp b/content/media/DecoderTraits.cpp
|
|
--- a/content/media/DecoderTraits.cpp
|
|
+++ b/content/media/DecoderTraits.cpp
|
|
@@ -7,16 +7,18 @@
|
|
#include "DecoderTraits.h"
|
|
#include "MediaDecoder.h"
|
|
#include "nsCharSeparatedTokenizer.h"
|
|
#ifdef MOZ_MEDIA_PLUGINS
|
|
#include "MediaPluginHost.h"
|
|
#endif
|
|
#ifdef MOZ_GSTREAMER
|
|
#include "mozilla/Preferences.h"
|
|
+#include "GStreamerDecoder.h"
|
|
+#include "nsXPCOMStrings.h"
|
|
#endif
|
|
#ifdef MOZ_WMF
|
|
#include "WMFDecoder.h"
|
|
#endif
|
|
|
|
namespace mozilla
|
|
{
|
|
|
|
@@ -137,48 +139,35 @@ DecoderTraits::IsWebMType(const nsACStri
|
|
return false;
|
|
}
|
|
|
|
return CodecListContains(gWebMTypes, aType);
|
|
}
|
|
#endif
|
|
|
|
#ifdef MOZ_GSTREAMER
|
|
-static const char* const gH264Types[4] = {
|
|
- "video/mp4",
|
|
- "video/3gpp",
|
|
- "video/quicktime",
|
|
- nullptr
|
|
-};
|
|
-
|
|
bool
|
|
DecoderTraits::IsGStreamerSupportedType(const nsACString& aMimeType)
|
|
{
|
|
if (!MediaDecoder::IsGStreamerEnabled())
|
|
return false;
|
|
- if (IsH264Type(aMimeType))
|
|
+ if (GStreamerDecoder::CanHandleMediaType(aMimeType, nullptr))
|
|
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)
|
|
-{
|
|
- return CodecListContains(gH264Types, aType);
|
|
-}
|
|
#endif
|
|
|
|
#ifdef MOZ_WIDGET_GONK
|
|
static const char* const gOmxTypes[6] = {
|
|
"audio/mpeg",
|
|
"audio/mp4",
|
|
"video/mp4",
|
|
"video/3gpp",
|
|
@@ -190,19 +179,17 @@ bool
|
|
DecoderTraits::IsOmxSupportedType(const nsACString& aType)
|
|
{
|
|
if (!MediaDecoder::IsOmxEnabled()) {
|
|
return false;
|
|
}
|
|
|
|
return CodecListContains(gOmxTypes, aType);
|
|
}
|
|
-#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
|
|
@@ -303,19 +290,19 @@ DecoderTraits::CanHandleMediaType(const
|
|
#ifdef MOZ_DASH
|
|
if (IsDASHMPDType(nsDependentCString(aMIMEType))) {
|
|
// DASH manifest uses WebM codecs only.
|
|
codecList = gWebMCodecs;
|
|
result = CANPLAY_YES;
|
|
}
|
|
#endif
|
|
#ifdef MOZ_GSTREAMER
|
|
- if (IsH264Type(nsDependentCString(aMIMEType))) {
|
|
- codecList = gH264Codecs;
|
|
- result = CANPLAY_MAYBE;
|
|
+ if (GStreamerDecoder::CanHandleMediaType(nsDependentCString(aMIMEType),
|
|
+ aHaveRequestedCodecs ? &aRequestedCodecs : nullptr)) {
|
|
+ return CANPLAY_YES;
|
|
}
|
|
#endif
|
|
#ifdef MOZ_WIDGET_GONK
|
|
if (IsOmxSupportedType(nsDependentCString(aMIMEType))) {
|
|
codecList = gH264Codecs;
|
|
result = CANPLAY_MAYBE;
|
|
}
|
|
#endif
|
|
@@ -324,17 +311,17 @@ DecoderTraits::CanHandleMediaType(const
|
|
result = CANPLAY_MAYBE;
|
|
}
|
|
#endif
|
|
#ifdef MOZ_MEDIA_PLUGINS
|
|
if (MediaDecoder::IsMediaPluginsEnabled() &&
|
|
GetMediaPluginHost()->FindDecoder(nsDependentCString(aMIMEType), &codecList))
|
|
result = CANPLAY_MAYBE;
|
|
#endif
|
|
- if (result == CANPLAY_NO || !aHaveRequestedCodecs) {
|
|
+ if (result == CANPLAY_NO || !aHaveRequestedCodecs || !codecList) {
|
|
return result;
|
|
}
|
|
|
|
// See http://www.rfc-editor.org/rfc/rfc4281.txt for the description
|
|
// of the 'codecs' parameter
|
|
nsCharSeparatedTokenizer tokenizer(aRequestedCodecs, ',');
|
|
bool expectMoreTokens = false;
|
|
while (tokenizer.hasMoreTokens()) {
|
|
diff --git a/content/media/DecoderTraits.h b/content/media/DecoderTraits.h
|
|
--- a/content/media/DecoderTraits.h
|
|
+++ b/content/media/DecoderTraits.h
|
|
@@ -51,17 +51,16 @@ public:
|
|
#ifdef MOZ_WEBM
|
|
static bool IsWebMType(const nsACString& aType);
|
|
#endif
|
|
|
|
#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.
|
|
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);
|
|
diff --git a/content/media/gstreamer/GStreamerDecoder.cpp b/content/media/gstreamer/GStreamerDecoder.cpp
|
|
--- a/content/media/gstreamer/GStreamerDecoder.cpp
|
|
+++ b/content/media/gstreamer/GStreamerDecoder.cpp
|
|
@@ -2,18 +2,26 @@
|
|
/* 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 "MediaDecoderStateMachine.h"
|
|
#include "GStreamerReader.h"
|
|
#include "GStreamerDecoder.h"
|
|
+#include "GStreamerFormatHelper.h"
|
|
|
|
namespace mozilla {
|
|
|
|
MediaDecoderStateMachine* GStreamerDecoder::CreateStateMachine()
|
|
{
|
|
return new MediaDecoderStateMachine(this, new GStreamerReader(this));
|
|
}
|
|
|
|
+bool
|
|
+GStreamerDecoder::CanHandleMediaType(const nsACString& aMIMEType,
|
|
+ const nsAString* aCodecs)
|
|
+{
|
|
+ return GStreamerFormatHelper::Instance()->CanHandleMediaType(aMIMEType, aCodecs);
|
|
+}
|
|
+
|
|
} // namespace mozilla
|
|
|
|
diff --git a/content/media/gstreamer/GStreamerDecoder.h b/content/media/gstreamer/GStreamerDecoder.h
|
|
--- a/content/media/gstreamer/GStreamerDecoder.h
|
|
+++ b/content/media/gstreamer/GStreamerDecoder.h
|
|
@@ -3,21 +3,23 @@
|
|
/* 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/. */
|
|
|
|
#if !defined(GStreamerDecoder_h_)
|
|
#define GStreamerDecoder_h_
|
|
|
|
#include "MediaDecoder.h"
|
|
+#include "nsXPCOMStrings.h"
|
|
|
|
namespace mozilla {
|
|
|
|
class GStreamerDecoder : public MediaDecoder
|
|
{
|
|
public:
|
|
virtual MediaDecoder* Clone() { return new GStreamerDecoder(); }
|
|
virtual MediaDecoderStateMachine* CreateStateMachine();
|
|
+ static bool CanHandleMediaType(const nsACString& aMIMEType, const nsAString* aCodecs);
|
|
};
|
|
|
|
} // namespace mozilla
|
|
|
|
#endif
|
|
diff --git a/content/media/gstreamer/GStreamerFormatHelper.cpp b/content/media/gstreamer/GStreamerFormatHelper.cpp
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/content/media/gstreamer/GStreamerFormatHelper.cpp
|
|
@@ -0,0 +1,159 @@
|
|
+/* -*- 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 "GStreamerFormatHelper.h"
|
|
+#include "nsCharSeparatedTokenizer.h"
|
|
+#include "nsXPCOMStrings.h"
|
|
+
|
|
+#define ENTRY_FORMAT(entry) entry[0]
|
|
+#define ENTRY_CAPS(entry) entry[1]
|
|
+
|
|
+GStreamerFormatHelper* GStreamerFormatHelper::gInstance = nullptr;
|
|
+
|
|
+GStreamerFormatHelper* GStreamerFormatHelper::Instance() {
|
|
+ if (!gInstance) {
|
|
+ gst_init(nullptr, nullptr);
|
|
+ gInstance = new GStreamerFormatHelper();
|
|
+ }
|
|
+
|
|
+ return gInstance;
|
|
+}
|
|
+
|
|
+void GStreamerFormatHelper::Shutdown() {
|
|
+ if (gInstance) {
|
|
+ delete gInstance;
|
|
+ gInstance = nullptr;
|
|
+ }
|
|
+}
|
|
+
|
|
+char const *const GStreamerFormatHelper::mContainers[4][2] = {
|
|
+ {"video/mp4", "video/quicktime"},
|
|
+ {"video/quicktime", "video/quicktime"},
|
|
+ {"audio/mp4", "audio/mpeg, mpegversion=(int)4"},
|
|
+ {"audio/mpeg", "audio/mpeg, mpegversion=(int)1"},
|
|
+};
|
|
+
|
|
+char const *const GStreamerFormatHelper::mCodecs[8][2] = {
|
|
+ {"avc1.42E01E", "video/x-h264"},
|
|
+ {"avc1.42001E", "video/x-h264"},
|
|
+ {"avc1.58A01E", "video/x-h264"},
|
|
+ {"avc1.4D401E", "video/x-h264"},
|
|
+ {"avc1.64001E", "video/x-h264"},
|
|
+ {"avc1.64001F", "video/x-h264"},
|
|
+ {"mp4v.20.3", "video/3gpp"},
|
|
+ {"mp4a.40.2", "audio/mpeg, mpegversion=(int)4"},
|
|
+};
|
|
+
|
|
+GStreamerFormatHelper::GStreamerFormatHelper()
|
|
+ : mFactories(nullptr),
|
|
+ mCookie(static_cast<uint32_t>(-1))
|
|
+{
|
|
+}
|
|
+
|
|
+GStreamerFormatHelper::~GStreamerFormatHelper() {
|
|
+ if (mFactories)
|
|
+ g_list_free(mFactories);
|
|
+}
|
|
+
|
|
+bool GStreamerFormatHelper::CanHandleMediaType(const nsACString& aMIMEType,
|
|
+ const nsAString* aCodecs) {
|
|
+ const char *type;
|
|
+ NS_CStringGetData(aMIMEType, &type, NULL);
|
|
+
|
|
+ GstCaps* caps = ConvertFormatsToCaps(type, aCodecs);
|
|
+ if (!caps) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ bool ret = HaveElementsToProcessCaps(caps);
|
|
+ gst_caps_unref(caps);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+GstCaps* GStreamerFormatHelper::ConvertFormatsToCaps(const char* aMIMEType,
|
|
+ const nsAString* aCodecs) {
|
|
+ unsigned int i;
|
|
+
|
|
+ /* convert aMIMEType to gst container caps */
|
|
+ const char* capsString = nullptr;
|
|
+ for (i = 0; i < G_N_ELEMENTS(mContainers); i++) {
|
|
+ if (!strcmp(ENTRY_FORMAT(mContainers[i]), aMIMEType)) {
|
|
+ capsString = ENTRY_CAPS(mContainers[i]);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!capsString) {
|
|
+ /* we couldn't find any matching caps */
|
|
+ return nullptr;
|
|
+ }
|
|
+
|
|
+ GstCaps* caps = gst_caps_from_string(capsString);
|
|
+ /* container only */
|
|
+ if (!aCodecs) {
|
|
+ return caps;
|
|
+ }
|
|
+
|
|
+ nsCharSeparatedTokenizer tokenizer(*aCodecs, ',');
|
|
+ while (tokenizer.hasMoreTokens()) {
|
|
+ const nsSubstring& codec = tokenizer.nextToken();
|
|
+ capsString = nullptr;
|
|
+
|
|
+ for (i = 0; i < G_N_ELEMENTS(mCodecs); i++) {
|
|
+ if (codec.EqualsASCII(ENTRY_FORMAT(mCodecs[i]))) {
|
|
+ capsString = ENTRY_CAPS(mCodecs[i]);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!capsString) {
|
|
+ gst_caps_unref(caps);
|
|
+ return nullptr;
|
|
+ }
|
|
+
|
|
+ GstCaps* tmp = gst_caps_from_string(capsString);
|
|
+ /* appends and frees tmp */
|
|
+ gst_caps_append(caps, tmp);
|
|
+ }
|
|
+
|
|
+ return caps;
|
|
+}
|
|
+
|
|
+bool GStreamerFormatHelper::HaveElementsToProcessCaps(GstCaps* aCaps) {
|
|
+
|
|
+ GList* factories = GetFactories();
|
|
+
|
|
+ GList* list;
|
|
+ /* here aCaps contains [containerCaps, [codecCaps1, [codecCaps2, ...]]] so process
|
|
+ * caps structures individually as we want one element for _each_
|
|
+ * structure */
|
|
+ for (unsigned int i = 0; i < gst_caps_get_size(aCaps); i++) {
|
|
+ GstStructure* s = gst_caps_get_structure(aCaps, i);
|
|
+ GstCaps* caps = gst_caps_new_full(gst_structure_copy(s), nullptr);
|
|
+ list = gst_element_factory_list_filter (factories, caps, GST_PAD_SINK, FALSE);
|
|
+ gst_caps_unref(caps);
|
|
+ if (!list) {
|
|
+ return false;
|
|
+ }
|
|
+ g_list_free(list);
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+GList* GStreamerFormatHelper::GetFactories() {
|
|
+ uint32_t cookie = gst_default_registry_get_feature_list_cookie ();
|
|
+ if (cookie != mCookie) {
|
|
+ g_list_free(mFactories);
|
|
+ mFactories = gst_element_factory_list_get_elements
|
|
+ (GST_ELEMENT_FACTORY_TYPE_DEMUXER | GST_ELEMENT_FACTORY_TYPE_DECODER,
|
|
+ GST_RANK_MARGINAL);
|
|
+ mCookie = cookie;
|
|
+ }
|
|
+
|
|
+ return mFactories;
|
|
+}
|
|
diff --git a/content/media/gstreamer/GStreamerFormatHelper.h b/content/media/gstreamer/GStreamerFormatHelper.h
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/content/media/gstreamer/GStreamerFormatHelper.h
|
|
@@ -0,0 +1,60 @@
|
|
+/* -*- 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/. */
|
|
+
|
|
+#if !defined(GStreamerFormatHelper_h_)
|
|
+#define GStreamerFormatHelper_h_
|
|
+
|
|
+#include <gst/gst.h>
|
|
+#include <mozilla/Types.h>
|
|
+#include "nsXPCOMStrings.h"
|
|
+
|
|
+class GStreamerFormatHelper {
|
|
+ /* This class can be used to query the GStreamer registry for the required
|
|
+ * demuxers/decoders from nsHTMLMediaElement::CanPlayType.
|
|
+ * It implements looking at the GstRegistry to check if elements to
|
|
+ * demux/decode the formats passed to CanPlayType() are actually installed.
|
|
+ */
|
|
+ public:
|
|
+ static GStreamerFormatHelper* Instance();
|
|
+ ~GStreamerFormatHelper();
|
|
+
|
|
+ bool CanHandleMediaType(const nsACString& aMIMEType,
|
|
+ const nsAString* aCodecs);
|
|
+
|
|
+ static void Shutdown();
|
|
+
|
|
+ private:
|
|
+ GStreamerFormatHelper();
|
|
+ GstCaps* ConvertFormatsToCaps(const char* aMIMEType,
|
|
+ const nsAString* aCodecs);
|
|
+ char* const *CodecListFromCaps(GstCaps* aCaps);
|
|
+ bool HaveElementsToProcessCaps(GstCaps* aCaps);
|
|
+ GList* GetFactories();
|
|
+
|
|
+ static GStreamerFormatHelper* gInstance;
|
|
+
|
|
+ /* table to convert from container MIME types to GStreamer elements */
|
|
+ static char const *const mContainers[4][2];
|
|
+
|
|
+ /* table to convert from codec MIME types to GStreamer elements */
|
|
+ static char const *const mCodecs[8][2];
|
|
+
|
|
+ /* list of GStreamer element factories
|
|
+ * Element factories are the basic types retrieved from the GStreamer
|
|
+ * registry, they describe all plugins and elements that GStreamer can
|
|
+ * create.
|
|
+ * This means that element factories are useful for automated element
|
|
+ * instancing, such as what autopluggers do,
|
|
+ * and for creating lists of available elements. */
|
|
+ GList* mFactories;
|
|
+
|
|
+ /* Storage for the default registrys feature list cookie.
|
|
+ * It changes every time a feature is added to or removed from the
|
|
+ * GStreamer registry. */
|
|
+ uint32_t mCookie;
|
|
+};
|
|
+
|
|
+#endif
|
|
diff --git a/content/media/gstreamer/Makefile.in b/content/media/gstreamer/Makefile.in
|
|
--- a/content/media/gstreamer/Makefile.in
|
|
+++ b/content/media/gstreamer/Makefile.in
|
|
@@ -13,21 +13,23 @@ include $(DEPTH)/config/autoconf.mk
|
|
MODULE = content
|
|
LIBRARY_NAME = gkcongstreamer_s
|
|
LIBXUL_LIBRARY = 1
|
|
|
|
|
|
EXPORTS += \
|
|
GStreamerDecoder.h \
|
|
GStreamerReader.h \
|
|
+ GStreamerFormatHelper.h \
|
|
$(NULL)
|
|
|
|
CPPSRCS = \
|
|
GStreamerReader.cpp \
|
|
GStreamerDecoder.cpp \
|
|
+ GStreamerFormatHelper.cpp \
|
|
$(NULL)
|
|
|
|
FORCE_STATIC_LIB = 1
|
|
|
|
include $(topsrcdir)/config/rules.mk
|
|
|
|
CFLAGS += $(GSTREAMER_CFLAGS)
|
|
CXXFLAGS += $(GSTREAMER_CFLAGS)
|
|
diff --git a/layout/build/Makefile.in b/layout/build/Makefile.in
|
|
--- a/layout/build/Makefile.in
|
|
+++ b/layout/build/Makefile.in
|
|
@@ -318,16 +318,20 @@ LOCAL_INCLUDES += -I$(srcdir)/../base \
|
|
-I$(topsrcdir)/js/xpconnect/loader \
|
|
-I$(topsrcdir)/caps/include \
|
|
-I$(topsrcdir)/netwerk/base/src \
|
|
-I$(topsrcdir)/content/svg/content/src \
|
|
-I$(topsrcdir)/extensions/cookie \
|
|
-I$(topsrcdir)/netwerk/cookie \
|
|
$(NULL)
|
|
|
|
+ifdef MOZ_GSTREAMER
|
|
+LOCAL_INCLUDES += $(GSTREAMER_CFLAGS)
|
|
+endif
|
|
+
|
|
ifdef MOZ_B2G_RIL #{
|
|
LOCAL_INCLUDES += -I$(topsrcdir)/dom/system/gonk
|
|
endif #}
|
|
|
|
ifdef MOZ_B2G_FM #{
|
|
LOCAL_INCLUDES += -I$(topsrcdir)/dom/fm
|
|
endif #}
|
|
|
|
diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp
|
|
--- a/layout/build/nsLayoutStatics.cpp
|
|
+++ b/layout/build/nsLayoutStatics.cpp
|
|
@@ -79,16 +79,20 @@
|
|
#ifdef MOZ_MEDIA_PLUGINS
|
|
#include "MediaPluginHost.h"
|
|
#endif
|
|
|
|
#ifdef MOZ_WMF
|
|
#include "WMFDecoder.h"
|
|
#endif
|
|
|
|
+#ifdef MOZ_GSTREAMER
|
|
+#include "GStreamerFormatHelper.h"
|
|
+#endif
|
|
+
|
|
#ifdef MOZ_SYDNEYAUDIO
|
|
#include "AudioStream.h"
|
|
#endif
|
|
|
|
#ifdef MOZ_WIDGET_GONK
|
|
#include "nsVolumeService.h"
|
|
using namespace mozilla::system;
|
|
#endif
|
|
@@ -344,16 +348,20 @@ nsLayoutStatics::Shutdown()
|
|
nsXBLService::Shutdown();
|
|
nsAutoCopyListener::Shutdown();
|
|
FrameLayerBuilder::Shutdown();
|
|
|
|
#ifdef MOZ_MEDIA_PLUGINS
|
|
MediaPluginHost::Shutdown();
|
|
#endif
|
|
|
|
+#ifdef MOZ_GSTREAMER
|
|
+ GStreamerFormatHelper::Shutdown();
|
|
+#endif
|
|
+
|
|
#ifdef MOZ_SYDNEYAUDIO
|
|
AudioStream::ShutdownLibrary();
|
|
#endif
|
|
|
|
#ifdef MOZ_WMF
|
|
WMFDecoder::UnloadDLLs();
|
|
#endif
|
|
|