Skip to content

Commit e05d356

Browse files
committed
[GStreamer][WPE] Replace platform ifdefs with runtime quirks
https://bugs.webkit.org/show_bug.cgi?id=269287 Reviewed by NOBODY (OOPS!). Compile-time quirks prevent re-usability of the same binaries across different platforms (using containers). The proposed solution is to always compile those, they don't depend on any specific APIs so that shouldn't be an issue. Then at runtime quirks can be tweaked using the WEBKIT_GST_QUIRKS and WEBKIT_GST_HOLE_PUNCH environment variables. * Source/WebCore/platform/SourcesGStreamer.txt: * Source/WebCore/platform/audio/gstreamer/AudioDestinationGStreamer.cpp: (WebCore::AudioDestinationGStreamer::AudioDestinationGStreamer): * Source/WebCore/platform/audio/gstreamer/AudioFileReaderGStreamer.cpp: (WebCore::decodebinAutoplugSelectCallback): (WebCore::AudioFileReader::~AudioFileReader): (WebCore::AudioFileReader::decodeAudioForBusCreation): * Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.cpp: (WebCore::ensureGStreamerInitialized): (WebCore::registerWebKitGStreamerElements): * Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp: (WebCore::GStreamerRegistryScanner::ElementFactories::ElementFactories): (WebCore::GStreamerRegistryScanner::ElementFactories::hasElementForCaps const): * Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp: (WebCore::MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer): (WebCore::MediaPlayerPrivateGStreamer::~MediaPlayerPrivateGStreamer): (WebCore::setSyncOnClock): (WebCore::MediaPlayerPrivateGStreamer::createAudioSink): (WebCore::MediaPlayerPrivateGStreamer::gstreamerPositionFromSinks const): (WebCore::MediaPlayerPrivateGStreamer::naturalSize const): (WebCore::MediaPlayerPrivateGStreamer::handleMessage): (WebCore::MediaPlayerPrivateGStreamer::configureElement): (WebCore::MediaPlayerPrivateGStreamer::configureElementPlatformQuirks): (WebCore::MediaPlayerPrivateGStreamer::createGSTPlayBin): (WebCore::MediaPlayerPrivateGStreamer::swapBuffersIfNeeded): (WebCore::setRectangleToVideoSink): (WebCore::MediaPlayerPrivateGStreamer::isHolePunchRenderingEnabled const): (WebCore::MediaPlayerPrivateGStreamer::createHolePunchVideoSink): (WebCore::MediaPlayerPrivateGStreamer::shouldIgnoreIntrinsicSize): (WebCore::MediaPlayerPrivateGStreamer::createVideoSink): * Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h: * Source/WebCore/platform/gstreamer/GStreamerHolePunchQuirkBcmNexus.cpp: Added. (WebCore::GStreamerHolePunchQuirkBcmNexus::setHolePunchVideoRectangle): * Source/WebCore/platform/gstreamer/GStreamerHolePunchQuirkBcmNexus.h: Added. * Source/WebCore/platform/gstreamer/GStreamerHolePunchQuirkWesteros.cpp: Added. (WebCore::GStreamerHolePunchQuirkWesteros::createHolePunchVideoSink): (WebCore::GStreamerHolePunchQuirkWesteros::setHolePunchVideoRectangle): * Source/WebCore/platform/gstreamer/GStreamerHolePunchQuirkWesteros.h: Added. * Source/WebCore/platform/gstreamer/GStreamerQuirkAmLogic.cpp: Added. (WebCore::GStreamerQuirkAmLogic::GStreamerQuirkAmLogic): (WebCore::GStreamerQuirkAmLogic::createWebAudioSink): (WebCore::GStreamerQuirkAmLogic::configureElement): * Source/WebCore/platform/gstreamer/GStreamerQuirkAmLogic.h: Added. * Source/WebCore/platform/gstreamer/GStreamerQuirkBcmNexus.cpp: Added. (WebCore::GStreamerQuirkBcmNexus::GStreamerQuirkBcmNexus): (WebCore::GStreamerQuirkBcmNexus::isHardwareAccelerated): * Source/WebCore/platform/gstreamer/GStreamerQuirkBcmNexus.h: Added. * Source/WebCore/platform/gstreamer/GStreamerQuirkBroadcom.cpp: Added. (WebCore::GStreamerQuirkBroadcom::GStreamerQuirkBroadcom): (WebCore::GStreamerQuirkBroadcom::configureElement): (WebCore::GStreamerQuirkBroadcom::isHardwareAccelerated): * Source/WebCore/platform/gstreamer/GStreamerQuirkBroadcom.h: Added. * Source/WebCore/platform/gstreamer/GStreamerQuirkRealtek.cpp: Added. (WebCore::GStreamerQuirkRealtek::GStreamerQuirkRealtek): (WebCore::GStreamerQuirkRealtek::createWebAudioSink): (WebCore::GStreamerQuirkRealtek::configureElement): (WebCore::GStreamerQuirkRealtek::isHardwareAccelerated): * Source/WebCore/platform/gstreamer/GStreamerQuirkRealtek.h: Added. * Source/WebCore/platform/gstreamer/GStreamerQuirkWesteros.cpp: Added. (WebCore::GStreamerQuirkWesteros::GStreamerQuirkWesteros): (WebCore::GStreamerQuirkWesteros::configureElement): (WebCore::GStreamerQuirkWesteros::isHardwareAccelerated): * Source/WebCore/platform/gstreamer/GStreamerQuirkWesteros.h: Added. * Source/WebCore/platform/gstreamer/GStreamerQuirks.cpp: Added. (WebCore::GStreamerQuirksManager::singleton): (WebCore::GStreamerQuirksManager::GStreamerQuirksManager): (WebCore::GStreamerQuirksManager::isEnabled const): (WebCore::GStreamerQuirksManager::createWebAudioSink): (WebCore::GStreamerQuirksManager::createHolePunchVideoSink): (WebCore::GStreamerQuirksManager::setHolePunchVideoRectangle): (WebCore::GStreamerQuirksManager::configureElement): (WebCore::GStreamerQuirksManager::isHardwareAccelerated const): (WebCore::GStreamerQuirksManager::supportsVideoHolePunchRendering const): (WebCore::GStreamerQuirksManager::audioVideoDecoderFactoryListType const): (WebCore::GStreamerQuirksManager::disallowedWebAudioDecoders const): * Source/WebCore/platform/gstreamer/GStreamerQuirks.h: Added. (WebCore::GStreamerQuirk::isPlatformSupported const): (WebCore::GStreamerQuirk::createWebAudioSink): (WebCore::GStreamerQuirk::configureElement): (WebCore::GStreamerQuirk::isHardwareAccelerated): (WebCore::GStreamerQuirk::audioVideoDecoderFactoryListType const): (WebCore::GStreamerQuirk::disallowedWebAudioDecoders const): (WebCore::GStreamerHolePunchQuirk::createHolePunchVideoSink): (WebCore::GStreamerHolePunchQuirk::setHolePunchVideoRectangle): * Source/cmake/OptionsWPE.cmake:
1 parent 4cec170 commit e05d356

23 files changed

Lines changed: 1202 additions & 219 deletions

Source/WebCore/platform/GStreamer.cmake

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ if (ENABLE_VIDEO OR ENABLE_WEB_AUDIO)
6767
platform/graphics/gstreamer/mse/WebKitMediaSourceGStreamer.cpp
6868

6969
platform/gstreamer/GStreamerCodecUtilities.cpp
70+
platform/gstreamer/GStreamerHolePunchQuirkBcmNexus.cpp
71+
platform/gstreamer/GStreamerHolePunchQuirkWesteros.cpp
72+
platform/gstreamer/GStreamerQuirkAmLogic.cpp
73+
platform/gstreamer/GStreamerQuirkBcmNexus.cpp
74+
platform/gstreamer/GStreamerQuirkBroadcom.cpp
75+
platform/gstreamer/GStreamerQuirkRealtek.cpp
76+
platform/gstreamer/GStreamerQuirkWesteros.cpp
77+
platform/gstreamer/GStreamerQuirks.cpp
7078
platform/gstreamer/VideoEncoderPrivateGStreamer.cpp
7179

7280
platform/mediarecorder/MediaRecorderPrivateGStreamer.cpp

Source/WebCore/platform/audio/gstreamer/AudioDestinationGStreamer.cpp

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "AudioSourceProvider.h"
2828
#include "AudioUtilities.h"
2929
#include "GStreamerCommon.h"
30+
#include "GStreamerQuirks.h"
3031
#include "Logging.h"
3132
#include "WebKitAudioSinkGStreamer.h"
3233
#include "WebKitWebAudioSourceGStreamer.h"
@@ -124,34 +125,19 @@ AudioDestinationGStreamer::AudioDestinationGStreamer(AudioIOCallback& callback,
124125
m_src = GST_ELEMENT_CAST(g_object_new(WEBKIT_TYPE_WEB_AUDIO_SRC, "rate", sampleRate,
125126
"bus", m_renderBus.get(), "destination", this, "frames", AudioUtilities::renderQuantumSize, nullptr));
126127

127-
#if PLATFORM(AMLOGIC)
128-
// autoaudiosink changes child element state to READY internally in auto detection phase
129-
// that causes resource acquisition in some cases interrupting any playback already running.
130-
// On Amlogic we need to set direct-mode=false prop before changing state to READY
131-
// but this is not possible with autoaudiosink.
132-
GRefPtr<GstElement> audioSink = makeGStreamerElement("amlhalasink", nullptr);
133-
ASSERT_WITH_MESSAGE(audioSink, "amlhalasink should be available in the system but it is not");
134-
g_object_set(audioSink.get(), "direct-mode", FALSE, nullptr);
135-
#else
136-
GRefPtr<GstElement> audioSink = createPlatformAudioSink("music"_s);
137-
#endif
128+
auto& quirksManager = GStreamerQuirksManager::singleton();
129+
GRefPtr<GstElement> audioSink = quirksManager.createWebAudioSink();
138130
m_audioSinkAvailable = audioSink;
139131
if (!audioSink) {
140132
GST_ERROR("Failed to create GStreamer audio sink element");
141133
return;
142134
}
143135

144-
// Probe platform early on for a working audio output device. This is not needed for the WebKit
145-
// custom audio sink because it doesn't rely on autoaudiosink.
146-
if (!WEBKIT_IS_AUDIO_SINK(audioSink.get())) {
136+
// Probe platform early on for a working audio output device in autoaudiosink.
137+
if (g_str_has_prefix(GST_OBJECT_NAME(audioSink.get()), "autoaudiosink")) {
147138
g_signal_connect(audioSink.get(), "child-added", G_CALLBACK(+[](GstChildProxy*, GObject* object, gchar*, gpointer) {
148139
if (GST_IS_AUDIO_BASE_SINK(object))
149140
g_object_set(GST_AUDIO_BASE_SINK(object), "buffer-time", static_cast<gint64>(100000), nullptr);
150-
151-
#if PLATFORM(REALTEK)
152-
if (!g_strcmp0(G_OBJECT_TYPE_NAME(object), "GstRTKAudioSink"))
153-
g_object_set(object, "media-tunnel", FALSE, "audio-service", TRUE, nullptr);
154-
#endif
155141
}), nullptr);
156142

157143
// Autoaudiosink does the real sink detection in the GST_STATE_NULL->READY transition

Source/WebCore/platform/audio/gstreamer/AudioFileReaderGStreamer.cpp

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include "AudioBus.h"
2626
#include "GStreamerCommon.h"
27+
#include "GStreamerQuirks.h"
2728
#include <gio/gio.h>
2829
#include <gst/app/gstappsink.h>
2930
#include <gst/audio/audio-info.h>
@@ -85,11 +86,11 @@ class AudioFileReader : public CanMakeWeakPtr<AudioFileReader> {
8586
bool m_errorOccurred { false };
8687
};
8788

88-
#if PLATFORM(BCM_NEXUS) || PLATFORM(BROADCOM) || PLATFORM(REALTEK)
8989
int decodebinAutoplugSelectCallback(GstElement*, GstPad*, GstCaps*, GstElementFactory* factory, gpointer)
9090
{
9191
static int GST_AUTOPLUG_SELECT_SKIP;
9292
static int GST_AUTOPLUG_SELECT_TRY;
93+
static Vector<String> pluginsToSkip;
9394
static std::once_flag onceFlag;
9495
std::call_once(onceFlag, [] {
9596
GEnumClass* enumClass = G_ENUM_CLASS(g_type_class_ref(g_type_from_name("GstAutoplugSelectResult")));
@@ -98,32 +99,17 @@ int decodebinAutoplugSelectCallback(GstElement*, GstPad*, GstCaps*, GstElementFa
9899
value = g_enum_get_value_by_name(enumClass, "GST_AUTOPLUG_SELECT_TRY");
99100
GST_AUTOPLUG_SELECT_TRY = value->value;
100101
g_type_class_unref(enumClass);
102+
103+
pluginsToSkip = GStreamerQuirksManager::singleton().disallowedWebAudioDecoders();
101104
});
102105

103-
const Vector<String> pluginsToSkip = {
104-
#if PLATFORM(BCM_NEXUS) || PLATFORM(BROADCOM)
105-
"brcmaudfilter"_s,
106-
#endif
107-
#if PLATFORM(REALTEK)
108-
"omxaacdec"_s,
109-
"omxac3dec"_s,
110-
"omxac4dec"_s,
111-
"omxeac3dec"_s,
112-
"omxflacdec"_s,
113-
"omxlpcmdec"_s,
114-
"omxmp3dec"_s,
115-
"omxopusdec"_s,
116-
"omxvorbisdec"_s,
117-
#endif
118-
};
119106
auto factoryName = StringView::fromLatin1(gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(factory)));
120107
for (const auto& pluginToSkip : pluginsToSkip) {
121108
if (pluginToSkip == factoryName)
122109
return GST_AUTOPLUG_SELECT_SKIP;
123110
}
124111
return GST_AUTOPLUG_SELECT_TRY;
125112
}
126-
#endif
127113

128114
static void copyGstreamerBuffersToAudioChannel(const GRefPtr<GstBufferList>& buffers, AudioChannel* audioChannel)
129115
{
@@ -173,9 +159,7 @@ AudioFileReader::~AudioFileReader()
173159

174160
if (m_decodebin) {
175161
g_signal_handlers_disconnect_matched(m_decodebin.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this);
176-
#if PLATFORM(BCM_NEXUS) || PLATFORM(BROADCOM) || PLATFORM(REALTEK)
177162
g_signal_handlers_disconnect_matched(m_decodebin.get(), G_SIGNAL_MATCH_FUNC, 0, 0, nullptr, reinterpret_cast<gpointer>(decodebinAutoplugSelectCallback), nullptr);
178-
#endif
179163
m_decodebin = nullptr;
180164
}
181165

@@ -426,9 +410,7 @@ void AudioFileReader::decodeAudioForBusCreation()
426410
g_object_set(source, "stream", memoryStream.get(), nullptr);
427411

428412
m_decodebin = makeGStreamerElement("decodebin", "decodebin");
429-
#if PLATFORM(BCM_NEXUS) || PLATFORM(BROADCOM) || PLATFORM(REALTEK)
430413
g_signal_connect(m_decodebin.get(), "autoplug-select", G_CALLBACK(decodebinAutoplugSelectCallback), nullptr);
431-
#endif
432414
g_signal_connect_swapped(m_decodebin.get(), "pad-added", G_CALLBACK(decodebinPadAddedCallback), this);
433415

434416
gst_bin_add_many(GST_BIN(m_pipeline.get()), source, m_decodebin.get(), nullptr);

Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.cpp

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "DMABufVideoSinkGStreamer.h"
2828
#include "GLVideoSinkGStreamer.h"
2929
#include "GStreamerAudioMixer.h"
30+
#include "GStreamerQuirks.h"
3031
#include "GStreamerRegistryScanner.h"
3132
#include "GStreamerSinksWorkarounds.h"
3233
#include "GUniquePtrGStreamer.h"
@@ -307,19 +308,6 @@ bool ensureGStreamerInitialized()
307308
gst_mpegts_initialize();
308309
#endif
309310

310-
#if PLATFORM(BCM_NEXUS)
311-
{
312-
auto registry = gst_registry_get();
313-
GRefPtr<GstPluginFeature> brcmaudfilter = adoptGRef(gst_registry_lookup_feature(registry, "brcmaudfilter"));
314-
GRefPtr<GstPluginFeature> mpegaudioparse = adoptGRef(gst_registry_lookup_feature(registry, "mpegaudioparse"));
315-
316-
if (brcmaudfilter && mpegaudioparse) {
317-
GST_INFO("overriding mpegaudioparse rank with brcmaudfilter rank + 1");
318-
gst_plugin_feature_set_rank(mpegaudioparse.get(), gst_plugin_feature_get_rank(brcmaudfilter.get()) + 1);
319-
}
320-
}
321-
#endif
322-
323311
registerAppsinkWithWorkaroundsIfNeeded();
324312
#endif
325313
});
@@ -421,6 +409,10 @@ void registerWebKitGStreamerElements()
421409
if (auto vaapiPlugin = adoptGRef(gst_registry_find_plugin(registry, "vaapi")))
422410
gst_registry_remove_plugin(registry, vaapiPlugin.get());
423411
}
412+
413+
// Make sure the quirks are created as early as possible.
414+
[[maybe_unused]] auto& quirksManager = GStreamerQuirksManager::singleton();
415+
424416
registryWasUpdated = true;
425417
});
426418

Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "config.h"
2121
#include "GStreamerRegistryScanner.h"
22+
#include "GStreamerQuirks.h"
2223

2324
#if USE(GSTREAMER)
2425
#include "ContentType.h"
@@ -77,17 +78,12 @@ void GStreamerRegistryScanner::getSupportedDecodingTypes(HashSet<String, ASCIICa
7778

7879
GStreamerRegistryScanner::ElementFactories::ElementFactories(OptionSet<ElementFactories::Type> types)
7980
{
80-
#if PLATFORM(BCM_NEXUS) || PLATFORM(BROADCOM)
81+
auto& quirksManager = GStreamerQuirksManager::singleton();
82+
auto audioVideoDecoderFactory = quirksManager.audioVideoDecoderFactoryListType();
8183
if (types.contains(Type::AudioDecoder))
82-
audioDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_PARSER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_MARGINAL);
84+
audioDecoderFactories = gst_element_factory_list_get_elements(audioVideoDecoderFactory | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_MARGINAL);
8385
if (types.contains(Type::VideoDecoder))
84-
videoDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_PARSER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, GST_RANK_MARGINAL);
85-
#else
86-
if (types.contains(Type::AudioDecoder))
87-
audioDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_MARGINAL);
88-
if (types.contains(Type::VideoDecoder))
89-
videoDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, GST_RANK_MARGINAL);
90-
#endif
86+
videoDecoderFactories = gst_element_factory_list_get_elements(audioVideoDecoderFactory | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, GST_RANK_MARGINAL);
9187
if (types.contains(Type::AudioParser))
9288
audioParserFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_PARSER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_NONE);
9389
if (types.contains(Type::VideoParser))
@@ -236,15 +232,16 @@ GStreamerRegistryScanner::RegistryLookupResult GStreamerRegistryScanner::Element
236232
auto* factory = reinterpret_cast<GstElementFactory*>(factories->data);
237233
auto metadata = String::fromLatin1(gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS));
238234
auto components = metadata.split('/');
239-
if (components.contains("Hardware"_s)
240-
#if PLATFORM(BCM_NEXUS) || PLATFORM(BROADCOM)
241-
|| g_str_has_prefix(GST_OBJECT_NAME(factory), "brcm")
242-
#elif PLATFORM(REALTEK)
243-
|| g_str_has_prefix(GST_OBJECT_NAME(factory), "omx")
244-
#elif USE(WESTEROS_SINK)
245-
|| g_str_has_prefix(GST_OBJECT_NAME(factory), "westeros")
246-
#endif
247-
) {
235+
auto& quirksManager = GStreamerQuirksManager::singleton();
236+
if (quirksManager.isEnabled()) {
237+
auto isAccelerated = quirksManager.isHardwareAccelerated(factory);
238+
if (isAccelerated && *isAccelerated) {
239+
isUsingHardware = true;
240+
selectedFactory = factory;
241+
break;
242+
}
243+
}
244+
if (components.contains("Hardware"_s)) {
248245
isUsingHardware = true;
249246
selectedFactory = factory;
250247
break;

0 commit comments

Comments
 (0)