To enable Rialto in WebKit, apply patch below and rebuild webkit using bitbake command.
Solution tested with Broadcom device only. Change tested with WebKit 2.38.2 (e585b369185b29fbc514afd959295efd02df9426)
diff --git a/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.cpp b/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.cpp
index 08bdac7e1e45..5aa17911bbfc 100644
--- a/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.cpp
+++ b/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.cpp
@@ -402,12 +402,16 @@ void registerWebKitGStreamerElements()
// The VAAPI plugin is not much maintained anymore and prone to rendering issues. In the
// mid-term we will leverage the new stateless VA decoders. Disable the legacy plugin,
// unless the WEBKIT_GST_ENABLE_LEGACY_VAAPI environment variable is set to 1.
+ auto* registry = gst_registry_get();
const char* enableLegacyVAAPIPlugin = getenv("WEBKIT_GST_ENABLE_LEGACY_VAAPI");
if (!enableLegacyVAAPIPlugin || !strcmp(enableLegacyVAAPIPlugin, "0")) {
- auto* registry = gst_registry_get();
if (auto vaapiPlugin = adoptGRef(gst_registry_find_plugin(registry, "vaapi")))
gst_registry_remove_plugin(registry, vaapiPlugin.get());
}
+ if (auto brcmVidFilterPlugin = adoptGRef(gst_registry_find_plugin(registry, "brcmvidfilter")))
+ gst_registry_remove_plugin(registry, brcmVidFilterPlugin.get());
+ if (auto brcmAudFilterPlugin = adoptGRef(gst_registry_find_plugin(registry, "brcmaudfilter")))
+ gst_registry_remove_plugin(registry, brcmAudFilterPlugin.get());
registryWasUpdated = true;
});
diff --git a/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp b/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp
index d2bbf1416e9b..6b4a5ddd6c45 100644
--- a/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp
+++ b/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp
@@ -77,17 +77,10 @@ void GStreamerRegistryScanner::getSupportedDecodingTypes(HashSet<String, ASCIICa
GStreamerRegistryScanner::ElementFactories::ElementFactories(OptionSet<ElementFactories::Type> types)
{
-#if PLATFORM(BCM_NEXUS) || PLATFORM(BROADCOM)
- if (types.contains(Type::AudioDecoder))
- audioDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_PARSER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_MARGINAL);
- if (types.contains(Type::VideoDecoder))
- videoDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_PARSER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, GST_RANK_MARGINAL);
-#else
if (types.contains(Type::AudioDecoder))
audioDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_MARGINAL);
if (types.contains(Type::VideoDecoder))
videoDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, GST_RANK_MARGINAL);
-#endif
if (types.contains(Type::AudioParser))
audioParserFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_PARSER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_NONE);
if (types.contains(Type::VideoParser))
diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
index 6e46736d07d0..8855840217ce 100644
--- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
+++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
@@ -1321,28 +1321,12 @@ void MediaPlayerPrivateGStreamer::loadingFailed(MediaPlayer::NetworkState networ
GstElement* MediaPlayerPrivateGStreamer::createAudioSink()
{
-#if PLATFORM(BROADCOM) || USE(WESTEROS_SINK) || PLATFORM(AMLOGIC) || PLATFORM(REALTEK)
- // If audio is being controlled by an another pipeline, creating sink here may interfere with
- // audio playback. Instead, check if an audio sink was setup in handleMessage and use it.
- return nullptr;
-#endif
-
- // For platform specific audio sinks, they need to be properly upranked so that they get properly autoplugged.
-
- auto role = m_player->isVideoPlayer() ? "video"_s : "music"_s;
- GstElement* audioSink = createPlatformAudioSink(role);
- RELEASE_ASSERT(audioSink);
- if (!audioSink)
- return nullptr;
-
-#if ENABLE(WEB_AUDIO)
- GstElement* audioSinkBin = gst_bin_new("audio-sink");
- ensureAudioSourceProvider();
- m_audioSourceProvider->configureAudioBin(audioSinkBin, audioSink);
- return audioSinkBin;
-#else
- return audioSink;
-#endif
+// #if ENABLE(WEB_AUDIO)
+// // Rialto webaudio doesnt work, investigation needed
+// return gst_element_factory_make("rialtowebaudiosink", "rialtowebaudiosink");
+// #else
+ return gst_element_factory_make("rialtomseaudiosink", "rialtomseaudiosink");
+// #endif
}
GstElement* MediaPlayerPrivateGStreamer::audioSink() const
@@ -1941,7 +1925,6 @@ void MediaPlayerPrivateGStreamer::handleMessage(GstMessage* message)
}
}
#endif
-
#if PLATFORM(BROADCOM) || USE(WESTEROS_SINK) || PLATFORM(AMLOGIC) || PLATFORM(REALTEK)
if (currentState <= GST_STATE_READY && newState >= GST_STATE_READY) {
// Detect an audio sink element and store reference to it if it supersedes what we currently have.
@@ -4150,7 +4133,7 @@ GstElement* MediaPlayerPrivateGStreamer::createHolePunchVideoSink()
if (m_isLegacyPlaybin && !isPIPRequested)
return nullptr;
// Westeros using holepunch.
- GstElement* videoSink = makeGStreamerElement("westerossink", "WesterosVideoSink");
+ GstElement* videoSink = gst_element_factory_make("rialtomsevideosink", "rialtomsevideosink");
g_object_set(G_OBJECT(videoSink), "zorder", 0.0f, nullptr);
if (isPIPRequested) {
g_object_set(G_OBJECT(videoSink), "res-usage", 0u, nullptr);
@@ -4572,7 +4555,6 @@ std::optional<VideoFrameMetadata> MediaPlayerPrivateGStreamer::videoFrameMetadat
void MediaPlayerPrivateGStreamer::setPageIsVisible(bool visible)
{
-
if (m_visible != visible) {
#if USE(GSTREAMER_HOLEPUNCH)
Locker locker { m_holePunchLock };
diff --git a/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp b/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp
index fc7241444484..ad28e3722888 100644
--- a/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp
+++ b/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp
@@ -229,6 +229,30 @@ MediaTime MediaPlayerPrivateGStreamerMSE::durationMediaTime() const
void MediaPlayerPrivateGStreamerMSE::seek(const MediaTime& time)
{
+ // Rialto doesnt like when seek is performed below paused state
+ if (m_isSeeking) {
+ if (m_isSeekPending) {
+ m_seekTime = time;
+ return;
+ }
+ }
+
+ if (pipeline())
+ {
+ GstState state;
+ GstStateChangeReturn getStateResult = gst_element_get_state(pipeline(), &state, nullptr, 0);
+ if (getStateResult == GST_STATE_CHANGE_FAILURE || getStateResult == GST_STATE_CHANGE_NO_PREROLL) {
+ GST_DEBUG_OBJECT(pipeline(), "[Seek] cannot seek, current state change is %s", gst_element_state_change_return_get_name(getStateResult));
+ return;
+ }
+ if (getStateResult == GST_STATE_CHANGE_ASYNC || state < GST_STATE_PAUSED || m_isEndReached) {
+ m_isSeekPending = true;
+ m_isSeeking = true;
+ m_seekTime = time;
+ m_isEndReached = false;
+ return;
+ }
+ }
GST_DEBUG_OBJECT(pipeline(), "Requested seek to %s", time.toString().utf8().data());
doSeek(time, m_playbackRate, GST_SEEK_FLAG_FLUSH);
}
@@ -257,10 +281,21 @@ bool MediaPlayerPrivateGStreamerMSE::doSeek(const MediaTime& position, float rat
m_isWaitingForPreroll = true;
m_isEndReached = false;
- // Important: In order to ensure correct propagation whether pre-roll has happened or not, we send the seek directly
- // to the source element, rather than letting playbin do the routing.
- gst_element_seek(m_source.get(), rate, GST_FORMAT_TIME, seekFlags,
- GST_SEEK_TYPE_SET, toGstClockTime(m_seekTime), GST_SEEK_TYPE_NONE, 0);
+ // Seek with m_source doesnt always forward seek event to all rialto sinks which causes seek problem.
+ if (pipeline())
+ {
+ fprintf(stderr, "Using pipeline to seek");
+ gst_element_seek(pipeline(), rate, GST_FORMAT_TIME, seekFlags,
+ GST_SEEK_TYPE_SET, toGstClockTime(m_seekTime), GST_SEEK_TYPE_NONE, 0);
+ }
+ else
+ {
+ // Important: In order to ensure correct propagation whether pre-roll has happened or not, we send the seek directly
+ // to the source element, rather than letting playbin do the routing.
+ fprintf(stderr, "Using source to seek");
+ gst_element_seek(m_source.get(), rate, GST_FORMAT_TIME, seekFlags,
+ GST_SEEK_TYPE_SET, toGstClockTime(m_seekTime), GST_SEEK_TYPE_NONE, 0);
+ }
invalidateCachedPosition();
// Notify MediaSource and have new frames enqueued (when they're available).
@@ -409,6 +444,17 @@ void MediaPlayerPrivateGStreamerMSE::updateStates()
GST_ERROR_OBJECT(pipeline(), "Setting the pipeline to PAUSED failed");
m_isPipelinePlaying = false;
}
+ if (getStateResult == GST_STATE_CHANGE_SUCCESS && m_currentState >= GST_STATE_PAUSED) {
+ if (m_isSeekPending) {
+ GST_DEBUG_OBJECT(pipeline(), "[Seek] committing pending seek to %s", toString(m_seekTime).utf8().data());
+ m_isSeekPending = false;
+ m_isSeeking = doSeek(m_seekTime, m_player->rate(), static_cast<GstSeekFlags>(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE));
+ if (!m_isSeeking) {
+ invalidateCachedPosition();
+ GST_DEBUG_OBJECT(pipeline(), "[Seek] seeking to %s failed", toString(m_seekTime).utf8().data());
+ }
+ }
+ }
}
bool MediaPlayerPrivateGStreamerMSE::isTimeBuffered(const MediaTime &time) const