diff --git a/Source/WPE/CMakeLists.txt b/Source/WPE/CMakeLists.txt index deb0abf52c52f..68274ddc5f979 100644 --- a/Source/WPE/CMakeLists.txt +++ b/Source/WPE/CMakeLists.txt @@ -160,6 +160,7 @@ if (USE_WPE_BACKEND_WESTEROS) Source/ViewBackend/Westeros/ViewBackendWesteros.cpp Source/ViewBackend/Westeros/WesterosViewbackendInput.cpp + Source/ViewBackend/Westeros/WesterosViewbackendOutput.cpp ) endif () diff --git a/Source/WPE/Source/Graphics/Westeros/RenderingBackendWesteros.cpp b/Source/WPE/Source/Graphics/Westeros/RenderingBackendWesteros.cpp index 3e7c95ee2e997..de652d61f9c66 100644 --- a/Source/WPE/Source/Graphics/Westeros/RenderingBackendWesteros.cpp +++ b/Source/WPE/Source/Graphics/Westeros/RenderingBackendWesteros.cpp @@ -91,11 +91,7 @@ RenderingBackendWesteros::RenderingBackendWesteros() , m_registry(nullptr) , m_compositor(nullptr) { - if (const char* nestedDisplay = std::getenv("WPE_WESTEROS_NESTED_DISPLAY")) { - m_display = wl_display_connect(nestedDisplay); - } else { - m_display = wl_display_connect(nullptr); - } + m_display = wl_display_connect(nullptr); g_WlDisplay = m_display; if(!m_display) diff --git a/Source/WPE/Source/ViewBackend/Westeros/ViewBackendWesteros.cpp b/Source/WPE/Source/ViewBackend/Westeros/ViewBackendWesteros.cpp index d134342f0c496..7eebd38cd4d9b 100644 --- a/Source/WPE/Source/ViewBackend/Westeros/ViewBackendWesteros.cpp +++ b/Source/WPE/Source/ViewBackend/Westeros/ViewBackendWesteros.cpp @@ -4,6 +4,7 @@ #include "ViewBackendWesteros.h" #include "WesterosViewbackendInput.h" +#include "WesterosViewbackendOutput.h" #include namespace WPE { @@ -14,12 +15,14 @@ namespace ViewBackend { ViewBackendWesteros::ViewBackendWesteros() : m_client(nullptr) , m_input_handler(nullptr) + , m_output_handler(nullptr) { m_compositor = WstCompositorCreate(); if (!m_compositor) return; m_input_handler = new WesterosViewbackendInput(); + m_output_handler = new WesterosViewbackendOutput(); const char* nestedTargetDisplay = std::getenv("WAYLAND_DISPLAY"); if (nestedTargetDisplay) { fprintf(stderr, "ViewBackendWesteros: running as the nested compositor\n"); @@ -28,8 +31,9 @@ ViewBackendWesteros::ViewBackendWesteros() WstCompositorSetNestedDisplayName( m_compositor, nestedTargetDisplay); //Register for all the necessary callback before starting the compositor m_input_handler->initializeNestedInputHandler(m_compositor, this); + m_output_handler->initializeNestedOutputHandler(m_compositor, this); const char * nestedDisplayName = WstCompositorGetDisplayName(m_compositor); - setenv("WPE_WESTEROS_NESTED_DISPLAY", nestedDisplayName, 1); + setenv("WAYLAND_DISPLAY", nestedDisplayName, 1); } if (!WstCompositorStart(m_compositor)) @@ -38,6 +42,10 @@ ViewBackendWesteros::ViewBackendWesteros() WstCompositorGetLastErrorDetail(m_compositor)); WstCompositorDestroy(m_compositor); m_compositor = nullptr; + delete m_input_handler; + delete m_output_handler; + m_input_handler = nullptr; + m_output_handler = nullptr; } } @@ -45,25 +53,26 @@ ViewBackendWesteros::~ViewBackendWesteros() { if(m_input_handler) m_input_handler->unregisterInputClient(); + if(m_output_handler) + m_output_handler->unregisterClient(); m_client = nullptr; - if (!m_compositor) - return; - - WstCompositorStop(m_compositor); - WstCompositorDestroy(m_compositor); - m_compositor = nullptr; + if (m_compositor) { + WstCompositorStop(m_compositor); + WstCompositorDestroy(m_compositor); + m_compositor = nullptr; + } if(m_input_handler) delete m_input_handler; + if(m_output_handler) + delete m_output_handler; } void ViewBackendWesteros::setClient(Client* client) { m_client = client; - if(m_client && m_compositor) { - uint32_t width, height; - WstCompositorGetNestedSize( m_compositor, &width, &height ); - m_client->setSize(width, height); + if(m_output_handler) { + m_output_handler->registerClient(m_client); } } diff --git a/Source/WPE/Source/ViewBackend/Westeros/ViewBackendWesteros.h b/Source/WPE/Source/ViewBackend/Westeros/ViewBackendWesteros.h index 177806635984f..8b2e713fcd971 100644 --- a/Source/WPE/Source/ViewBackend/Westeros/ViewBackendWesteros.h +++ b/Source/WPE/Source/ViewBackend/Westeros/ViewBackendWesteros.h @@ -12,6 +12,7 @@ namespace WPE { namespace ViewBackend { class WesterosViewbackendInput; +class WesterosViewbackendOutput; class ViewBackendWesteros final : public ViewBackend { public: @@ -27,6 +28,7 @@ class ViewBackendWesteros final : public ViewBackend { private: WesterosViewbackendInput* m_input_handler; + WesterosViewbackendOutput* m_output_handler; WstCompositor* m_compositor; Client* m_client; uint32_t m_width; diff --git a/Source/WPE/Source/ViewBackend/Westeros/WesterosViewbackendOutput.cpp b/Source/WPE/Source/ViewBackend/Westeros/WesterosViewbackendOutput.cpp new file mode 100644 index 0000000000000..17c4c824fe99e --- /dev/null +++ b/Source/WPE/Source/ViewBackend/Westeros/WesterosViewbackendOutput.cpp @@ -0,0 +1,97 @@ +#include "Config.h" + +#if WPE_BACKEND(WESTEROS) + +#include "ViewBackendWesteros.h" +#include "WesterosViewbackendOutput.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace WPE { + +namespace ViewBackend { + +static WstOutputNestedListener output_listener = { + WesterosViewbackendOutput::handleGeometryCallback, + WesterosViewbackendOutput::handleModeCallback, + WesterosViewbackendOutput::handleDoneCallback, + WesterosViewbackendOutput::handleScaleCallback +}; + +void WesterosViewbackendOutput::handleGeometryCallback( void *userData, int32_t x, int32_t y, int32_t mmWidth, int32_t mmHeight, + int32_t subPixel, const char *make, const char *model, int32_t transform ) +{ +} + +void WesterosViewbackendOutput::handleModeCallback( void *userData, uint32_t flags, int32_t width, int32_t height, int32_t refreshRate ) +{ + auto& backend_output = *static_cast(userData); + if (flags == WesterosViewbackendModeCurrent) { + backend_output.m_width = width; + backend_output.m_height = height; + if(backend_output.m_client) + { + backend_output.m_client->setSize(backend_output.m_width, backend_output.m_height); + } + } +} + +void WesterosViewbackendOutput::handleDoneCallback( void *UserData ) +{ +} + +void WesterosViewbackendOutput::handleScaleCallback( void *UserData, int32_t scale ) +{ +} + +WesterosViewbackendOutput::WesterosViewbackendOutput() + : m_compositor(nullptr) + , m_viewbackend(nullptr) + , m_client(nullptr) + , m_width(0) + , m_height(0) +{ +} + +WesterosViewbackendOutput::~WesterosViewbackendOutput() +{ + m_compositor = nullptr; + m_viewbackend = nullptr; + m_client = nullptr; +} + +void WesterosViewbackendOutput::registerClient(Client* client) +{ + m_client = client; + if (m_client) + { + // If we get registerClient call before handleModeCallback, + // it will endup setting size to (0,0) and then again back to correct size in handleModeCallback. + m_client->setSize(m_width, m_height); + } +} + +void WesterosViewbackendOutput::initializeNestedOutputHandler(WstCompositor *compositor, ViewBackendWesteros *backend) +{ + m_compositor = compositor; + m_viewbackend = backend; + + if (m_compositor && m_viewbackend) { + if (!WstCompositorSetOutputNestedListener( m_compositor, &output_listener, this )) { + fprintf(stderr, "ViewBackendWesteros: failed to set output listener: %s\n", + WstCompositorGetLastErrorDetail(m_compositor)); + } + } +} + +} // namespace ViewBackend + +} // namespace WPE + +#endif // WPE_BACKEND(WESTEROS) diff --git a/Source/WPE/Source/ViewBackend/Westeros/WesterosViewbackendOutput.h b/Source/WPE/Source/ViewBackend/Westeros/WesterosViewbackendOutput.h new file mode 100644 index 0000000000000..2363f53799e73 --- /dev/null +++ b/Source/WPE/Source/ViewBackend/Westeros/WesterosViewbackendOutput.h @@ -0,0 +1,44 @@ +#ifndef WPE_ViewBackend_WesterosViewbackendOutput_h +#define WPE_ViewBackend_WesterosViewbackendOutput_h + +#if WPE_BACKEND(WESTEROS) + +#include "ViewBackendWesteros.h" + +namespace WPE { + +namespace ViewBackend { + +enum WesterosViewbackendOutputMode { + WesterosViewbackendModeCurrent = 0x1, + WesterosViewbackendModePreferred = 0x2 +}; + +class WesterosViewbackendOutput { +public: + WesterosViewbackendOutput(); + virtual ~WesterosViewbackendOutput(); + void registerClient(Client* client); + void unregisterClient() { m_client = nullptr; } + void initializeNestedOutputHandler(WstCompositor *compositor, ViewBackendWesteros *backend); + + static void handleGeometryCallback( void *userData, int32_t x, int32_t y, int32_t mmWidth, int32_t mmHeight, + int32_t subPixel, const char *make, const char *model, int32_t transform ); + static void handleModeCallback( void *userData, uint32_t flags, int32_t width, int32_t height, int32_t refreshRate ); + static void handleDoneCallback( void *UserData ); + static void handleScaleCallback( void *UserData, int32_t scale ); + +private: + WstCompositor* m_compositor; + ViewBackendWesteros* m_viewbackend; + Client* m_client; + uint32_t m_width; + uint32_t m_height; +}; + +} // namespace ViewBackend + +} // namespace WPE + +#endif // WPE_BACKEND(WESTEROS) +#endif // WPE_ViewBackend_WesterosViewbackendOutput_h diff --git a/Source/WebCore/html/HTMLMediaElement.cpp b/Source/WebCore/html/HTMLMediaElement.cpp index 55cc9f2b23dd1..4fb1e4aeb64af 100644 --- a/Source/WebCore/html/HTMLMediaElement.cpp +++ b/Source/WebCore/html/HTMLMediaElement.cpp @@ -4472,6 +4472,13 @@ void HTMLMediaElement::mediaPlayerSizeChanged(MediaPlayer*) scheduleResizeEventIfSizeChanged(); if (renderer()) renderer()->updateFromElement(); + +#if USE(HOLE_PUNCH_GSTREAMER) || USE(HOLE_PUNCH_EXTERNAL) + IntRect windowRect = document().view()->contentsToScreen(renderer()->absoluteBoundingBoxRect(true)); + //style() is having relative values w.r.t immediate container. Hence we need to substract left,top values from immediate container to get correct x,y values. + player()->setPosition(IntPoint(windowRect.x() - renderer()->style().left().intValue(),windowRect.y() -renderer()->style().top().intValue())); +#endif + endProcessingMediaPlayerCallback(); } diff --git a/Source/WebCore/platform/graphics/MediaPlayer.cpp b/Source/WebCore/platform/graphics/MediaPlayer.cpp index 96c403319480b..349bde2999289 100644 --- a/Source/WebCore/platform/graphics/MediaPlayer.cpp +++ b/Source/WebCore/platform/graphics/MediaPlayer.cpp @@ -153,6 +153,7 @@ class NullMediaPlayerPrivate : public MediaPlayerPrivateInterface { bool didLoadingProgress() const override { return false; } void setSize(const IntSize&) override { } + void setPosition(const IntPoint&) override { } void paint(GraphicsContext&, const FloatRect&) override { } @@ -813,6 +814,12 @@ void MediaPlayer::setSize(const IntSize& size) m_private->setSize(size); } +void MediaPlayer::setPosition(const IntPoint& position) +{ + m_private->setPosition(position); +} + + bool MediaPlayer::visible() const { return m_visible; diff --git a/Source/WebCore/platform/graphics/MediaPlayer.h b/Source/WebCore/platform/graphics/MediaPlayer.h index 5ea5587110593..3d4f033f7a027 100644 --- a/Source/WebCore/platform/graphics/MediaPlayer.h +++ b/Source/WebCore/platform/graphics/MediaPlayer.h @@ -328,6 +328,7 @@ class MediaPlayer : public MediaPlayerEnums { IntSize size() const { return m_size; } void setSize(const IntSize& size); + void setPosition(const IntPoint&); bool load(const URL&, const ContentType&, const String& keySystem); #if ENABLE(MEDIA_SOURCE) diff --git a/Source/WebCore/platform/graphics/MediaPlayerPrivate.h b/Source/WebCore/platform/graphics/MediaPlayerPrivate.h index 14b1e5edaa463..d72a9b238834a 100644 --- a/Source/WebCore/platform/graphics/MediaPlayerPrivate.h +++ b/Source/WebCore/platform/graphics/MediaPlayerPrivate.h @@ -146,6 +146,7 @@ class MediaPlayerPrivateInterface { virtual bool didLoadingProgress() const = 0; virtual void setSize(const IntSize&) = 0; + virtual void setPosition(const IntPoint&) {}; virtual void paint(GraphicsContext&, const FloatRect&) = 0; diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp index 26711068cefe6..17764989e0688 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp @@ -2156,7 +2156,17 @@ void MediaPlayerPrivateGStreamer::createGSTPlayBin() if (videoSinkPad) g_signal_connect_swapped(videoSinkPad.get(), "notify::caps", G_CALLBACK(videoSinkCapsChangedCallback), this); #endif + +#if USE(WESTEROS_SINK) && USE(HOLE_PUNCH_GSTREAMER) + GstElementFactory *westerosfactory = gst_element_factory_find("westerossink"); + GstElement* sinkElement = gst_element_factory_create(westerosfactory,"WesterosVideoSink"); + g_object_set(m_pipeline.get(), "video-sink", sinkElement, nullptr); + g_object_set(G_OBJECT(sinkElement),"zorder",0.0f,nullptr); +#endif + +#if !USE(WESTEROS_SINK) g_object_set(m_pipeline.get(), "audio-sink", createAudioSink(), nullptr); +#endif configurePlaySink(); // On 1.4.2 and newer we use the audio-filter property instead. diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp index 807234c172d8d..43184a8d0bfae 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp @@ -319,6 +319,17 @@ MediaPlayerPrivateGStreamerBase::~MediaPlayerPrivateGStreamerBase() void MediaPlayerPrivateGStreamerBase::setPipeline(GstElement* pipeline) { m_pipeline = pipeline; +#if USE(HOLE_PUNCH_GSTREAMER) + GstElement* sinkElement = nullptr; + g_object_get(m_pipeline.get(), "video-sink", &sinkElement, nullptr); + if(!sinkElement) + return; + + INFO_MEDIA_MESSAGE("setPipeline: Setting video sink size and position to x:%d y:%d, width=%d, height=%d\n",m_position.x(),m_position.y(), m_size.width(),m_size.height()); + gchar rectString[64] = {0}; + g_snprintf(rectString, sizeof(rectString), "%d,%d,%d,%d", m_position.x(), m_position.y(), m_size.width(),m_size.height()); + g_object_set(G_OBJECT(sinkElement),"window_set",rectString, nullptr); +#endif } void MediaPlayerPrivateGStreamerBase::clearSamples() @@ -837,6 +848,27 @@ void MediaPlayerPrivateGStreamerBase::setSize(const IntSize& size) m_size = size; } +void MediaPlayerPrivateGStreamerBase::setPosition(const IntPoint& position) +{ + if (position == m_position) + return; + + m_position = position; + + if(!m_pipeline) + return; + + GstElement* sinkElement = nullptr; + g_object_get(m_pipeline.get(), "video-sink", &sinkElement, nullptr); + if(!sinkElement) + return; + + INFO_MEDIA_MESSAGE("setPosition: Setting video sink size and position to x:%d y:%d, width=%d, height=%d\n",m_position.x(),m_position.y(), m_size.width(),m_size.height()); + gchar rectString[64] = {0}; + g_snprintf(rectString, sizeof(rectString), "%d,%d,%d,%d", m_position.x(), m_position.y(), m_size.width(),m_size.height()); + g_object_set(G_OBJECT(sinkElement),"window_set",rectString, nullptr); +} + void MediaPlayerPrivateGStreamerBase::paint(GraphicsContext& context, const FloatRect& rect) { #if USE(COORDINATED_GRAPHICS_THREADED) diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h index c2851518d9fb1..a04c96a852216 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h @@ -100,6 +100,7 @@ class MediaPlayerPrivateGStreamerBase : public MediaPlayerPrivateInterface void setVisible(bool) override { } void setSize(const IntSize&) override; + void setPosition(const IntPoint&) override; void sizeChanged(); void triggerDrain(); @@ -221,6 +222,7 @@ class MediaPlayerPrivateGStreamerBase : public MediaPlayerPrivateInterface mutable MediaPlayer::NetworkState m_networkState; mutable bool m_isEndReached; IntSize m_size; + IntPoint m_position; mutable GMutex m_sampleMutex; GRefPtr m_sample; #if USE(GSTREAMER_GL) diff --git a/Source/cmake/OptionsWPE.cmake b/Source/cmake/OptionsWPE.cmake index bd0bb0d47f7ad..2df27df93927e 100644 --- a/Source/cmake/OptionsWPE.cmake +++ b/Source/cmake/OptionsWPE.cmake @@ -39,6 +39,7 @@ WEBKIT_OPTION_DEFINE(USE_WPE_BACKEND_DRM "Whether to enable support for the DRM WEBKIT_OPTION_DEFINE(USE_WPE_BACKEND_DRM_TEGRA "Whether to enable support for the Tegra-specific quirks in the DRM WPE backend" PUBLIC OFF) WEBKIT_OPTION_DEFINE(USE_WPE_BACKEND_WAYLAND "Whether to enable support for the Wayland WPE backend" PUBLIC OFF) WEBKIT_OPTION_DEFINE(USE_WPE_BACKEND_WESTEROS "Whether to enable support for the Westeros WPE backend" PUBLIC OFF) +WEBKIT_OPTION_DEFINE(USE_WESTEROS_SINK "Westeros-Sink to be used as video-sink for GStreamer video player" PUBLIC OFF) WEBKIT_OPTION_DEFINE(USE_WPE_BUFFER_MANAGEMENT_GBM "Whether to enable support for the GBM WPE rendering backend" PUBLIC OFF) WEBKIT_OPTION_DEFINE(USE_WPE_BUFFER_MANAGEMENT_BCM_RPI "Whether to enable support for the BCM RPi rendering backend" PUBLIC OFF) WEBKIT_OPTION_DEFINE(USE_WPE_BUFFER_MANAGEMENT_BCM_NEXUS "Whether to enable support for the BCM_NEXUS rendering backend" PUBLIC OFF) @@ -69,7 +70,7 @@ find_package(ICU REQUIRED) find_package(Threads REQUIRED) find_package(ZLIB REQUIRED) find_package(GLIB 2.38.0 REQUIRED COMPONENTS gio gobject gthread gmodule) -find_package(GnuTLS 3.0.0 REQUIRED) +find_package(GnuTLS 2.12.23 REQUIRED) find_package(Cairo 1.10.2 REQUIRED) find_package(Fontconfig 2.8.0 REQUIRED)