avmedia/source/gtk/gtkplayer.cxx | 94 +++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 37 deletions(-)
New commits: commit b438854a0b5148880e455cbeeff14d4e3d825711 Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Sun Feb 20 21:11:19 2022 +0000 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Mon Feb 21 09:37:49 2022 +0100 gtk4: get getPreferredPlayerWindowSize working Change-Id: I5e5b02be6a902232c24120db513cdf3fc68b4421 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130224 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caol...@redhat.com> diff --git a/avmedia/source/gtk/gtkplayer.cxx b/avmedia/source/gtk/gtkplayer.cxx index d75d7078ebd9..7ce488f231ec 100644 --- a/avmedia/source/gtk/gtkplayer.cxx +++ b/avmedia/source/gtk/gtkplayer.cxx @@ -231,6 +231,41 @@ sal_Int16 SAL_CALL GtkPlayer::getVolumeDB() return m_nUnmutedVolume; } +namespace +{ +void invalidate_size(GdkPaintable* /*paintable*/, Timer* pTimer) { pTimer->Stop(); } + +Size GetPreferredPlayerWindowSize(GdkPaintable* pStream) +{ + Size aSize(gdk_paintable_get_intrinsic_width(pStream), + gdk_paintable_get_intrinsic_height(pStream)); + + // This is pretty nasty, maybe for the XFrameGrabber case it could be + // possible to implement an XGraphic which can be updated when the + // information becomes available rather than explicitly wait for it here, + // but the getPreferredPlayerWindowSize problem would remain. + if (aSize.Width() == 0 && aSize.Height() == 0) + { + Timer aTimer("gtkplayer waiting to find out size"); + aTimer.SetTimeout(3000); + + gulong nSignalId + = g_signal_connect(pStream, "invalidate-size", G_CALLBACK(invalidate_size), &aTimer); + + aTimer.Start(); + while (aTimer.IsActive()) + Application::Yield(); + + g_signal_handler_disconnect(pStream, nSignalId); + + aSize = Size(gdk_paintable_get_intrinsic_width(pStream), + gdk_paintable_get_intrinsic_height(pStream)); + } + + return aSize; +} +} + awt::Size SAL_CALL GtkPlayer::getPreferredPlayerWindowSize() { osl::MutexGuard aGuard(m_aMutex); @@ -239,14 +274,9 @@ awt::Size SAL_CALL GtkPlayer::getPreferredPlayerWindowSize() if (m_pStream) { - double width; - double height; - - gdk_paintable_compute_concrete_size(GDK_PAINTABLE(m_pStream), 0.0, 0.0, 100, 200, &width, - &height); - - aSize.Width = gdk_paintable_get_intrinsic_width(GDK_PAINTABLE(m_pStream)); - aSize.Height = gdk_paintable_get_intrinsic_height(GDK_PAINTABLE(m_pStream)); + Size aPrefSize = GetPreferredPlayerWindowSize(GDK_PAINTABLE(m_pStream)); + aSize.Width = aPrefSize.Width(); + aSize.Height = aPrefSize.Height(); } return aSize; @@ -299,19 +329,20 @@ namespace { class GtkFrameGrabber : public ::cppu::WeakImplHelper<css::media::XFrameGrabber> { +private: + awt::Size m_aSize; GtkMediaStream* m_pStream; public: - GtkFrameGrabber(GtkMediaStream* pStream) - : m_pStream(pStream) + GtkFrameGrabber(GtkMediaStream* pStream, const awt::Size& rSize) + : m_aSize(rSize) + , m_pStream(pStream) { g_object_ref(m_pStream); } virtual ~GtkFrameGrabber() override { g_object_unref(m_pStream); } - static void invalidate_size(GdkPaintable* /*paintable*/, Timer* pTimer) { pTimer->Stop(); } - // XFrameGrabber virtual css::uno::Reference<css::graphic::XGraphic> SAL_CALL grabFrame(double fMediaTime) override @@ -319,39 +350,11 @@ public: gint64 gst_position = llround(fMediaTime * 1000000); gtk_media_stream_seek(m_pStream, gst_position); - Size aSize(gdk_paintable_get_intrinsic_width(GDK_PAINTABLE(m_pStream)), - gdk_paintable_get_intrinsic_height(GDK_PAINTABLE(m_pStream))); - - // This is pretty nasty, maybe it could be possible to implement an - // XGraphic which can be updated when the information becomes available - // rather than explicitly wait for it here, but the - // getPreferredPlayerWindowSize problem would remain. - if (aSize.Width() == 0 && aSize.Height() == 0) - { - Timer aTimer("gtkplayer waiting to find out size"); - aTimer.SetTimeout(3000); - - gulong nSignalId = g_signal_connect(m_pStream, "invalidate-size", - G_CALLBACK(invalidate_size), &aTimer); - - aTimer.Start(); - while (aTimer.IsActive()) - Application::Yield(); - - g_signal_handler_disconnect(m_pStream, nSignalId); - - aSize = Size(gdk_paintable_get_intrinsic_width(GDK_PAINTABLE(m_pStream)), - gdk_paintable_get_intrinsic_height(GDK_PAINTABLE(m_pStream))); - } - - if (!aSize.Width() || !aSize.Height()) - return nullptr; - cairo_surface_t* surface - = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, aSize.Width(), aSize.Height()); + = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, m_aSize.Width, m_aSize.Height); GtkSnapshot* snapshot = gtk_snapshot_new(); - gdk_paintable_snapshot(GDK_PAINTABLE(m_pStream), snapshot, aSize.Width(), aSize.Height()); + gdk_paintable_snapshot(GDK_PAINTABLE(m_pStream), snapshot, m_aSize.Width, m_aSize.Height); GskRenderNode* node = gtk_snapshot_free_to_node(snapshot); cairo_t* cr = cairo_create(surface); @@ -360,7 +363,8 @@ public: gsk_render_node_unref(node); - std::unique_ptr<BitmapEx> xBitmap(vcl::bitmap::CreateFromCairoSurface(aSize, surface)); + std::unique_ptr<BitmapEx> xBitmap( + vcl::bitmap::CreateFromCairoSurface(Size(m_aSize.Width, m_aSize.Height), surface)); cairo_surface_destroy(surface); @@ -372,7 +376,14 @@ public: uno::Reference<media::XFrameGrabber> SAL_CALL GtkPlayer::createFrameGrabber() { osl::MutexGuard aGuard(m_aMutex); - rtl::Reference<GtkFrameGrabber> xFrameGrabber(new GtkFrameGrabber(m_pStream)); + + rtl::Reference<GtkFrameGrabber> xFrameGrabber; + + const awt::Size aPrefSize(getPreferredPlayerWindowSize()); + + if (aPrefSize.Width > 0 && aPrefSize.Height > 0) + xFrameGrabber.set(new GtkFrameGrabber(m_pStream, aPrefSize)); + return xFrameGrabber; } commit f049c3884f7a376374ed6cffea6746ef35b00186 Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Sun Feb 20 20:58:17 2022 +0000 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Mon Feb 21 09:37:35 2022 +0100 gtk4: get XFrameGrabber to work Change-Id: I737fd72d11b11d0c3592857113e422f29da76e77 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130223 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caol...@redhat.com> diff --git a/avmedia/source/gtk/gtkplayer.cxx b/avmedia/source/gtk/gtkplayer.cxx index 098e8b3b6fe6..d75d7078ebd9 100644 --- a/avmedia/source/gtk/gtkplayer.cxx +++ b/avmedia/source/gtk/gtkplayer.cxx @@ -13,12 +13,14 @@ #include <cppuhelper/supportsservice.hxx> #include <sal/log.hxx> -#include <vcl/BitmapTools.hxx> #include <rtl/string.hxx> +#include <tools/link.hxx> +#include <vcl/BitmapTools.hxx> #include <vcl/graph.hxx> #include <vcl/svapp.hxx> #include <vcl/syschild.hxx> #include <vcl/sysdata.hxx> +#include <vcl/timer.hxx> #include <gstwindow.hxx> #include "gtkplayer.hxx" @@ -237,6 +239,12 @@ awt::Size SAL_CALL GtkPlayer::getPreferredPlayerWindowSize() if (m_pStream) { + double width; + double height; + + gdk_paintable_compute_concrete_size(GDK_PAINTABLE(m_pStream), 0.0, 0.0, 100, 200, &width, + &height); + aSize.Width = gdk_paintable_get_intrinsic_width(GDK_PAINTABLE(m_pStream)); aSize.Height = gdk_paintable_get_intrinsic_height(GDK_PAINTABLE(m_pStream)); } @@ -297,40 +305,53 @@ public: GtkFrameGrabber(GtkMediaStream* pStream) : m_pStream(pStream) { + g_object_ref(m_pStream); } + virtual ~GtkFrameGrabber() override { g_object_unref(m_pStream); } + + static void invalidate_size(GdkPaintable* /*paintable*/, Timer* pTimer) { pTimer->Stop(); } + // XFrameGrabber virtual css::uno::Reference<css::graphic::XGraphic> SAL_CALL grabFrame(double fMediaTime) override { - GtkWidget* pWindow = gtk_window_new(); - GtkWidget* pVideo = gtk_picture_new_for_paintable(GDK_PAINTABLE(m_pStream)); - gtk_window_set_child(GTK_WINDOW(pWindow), pVideo); - gtk_widget_realize(pVideo); - gtk_widget_map(pVideo); - - //bool bMuted = gtk_media_stream_get_muted(m_pStream); - gtk_media_stream_set_muted(m_pStream, true); - gtk_media_stream_set_volume(m_pStream, 0); gint64 gst_position = llround(fMediaTime * 1000000); gtk_media_stream_seek(m_pStream, gst_position); - gtk_media_stream_play(m_pStream); - // while (!gtk_media_stream_is_prepared(m_pStream)) - // Application::Yield(); + Size aSize(gdk_paintable_get_intrinsic_width(GDK_PAINTABLE(m_pStream)), + gdk_paintable_get_intrinsic_height(GDK_PAINTABLE(m_pStream))); - gtk_media_stream_pause(m_pStream); + // This is pretty nasty, maybe it could be possible to implement an + // XGraphic which can be updated when the information becomes available + // rather than explicitly wait for it here, but the + // getPreferredPlayerWindowSize problem would remain. + if (aSize.Width() == 0 && aSize.Height() == 0) + { + Timer aTimer("gtkplayer waiting to find out size"); + aTimer.SetTimeout(3000); - GdkPaintable* current_paintable = gdk_paintable_get_current_image(GDK_PAINTABLE(m_pStream)); + gulong nSignalId = g_signal_connect(m_pStream, "invalidate-size", + G_CALLBACK(invalidate_size), &aTimer); - // gtk_media_stream_set_muted(m_pStream, bMuted); + aTimer.Start(); + while (aTimer.IsActive()) + Application::Yield(); + + g_signal_handler_disconnect(m_pStream, nSignalId); + + aSize = Size(gdk_paintable_get_intrinsic_width(GDK_PAINTABLE(m_pStream)), + gdk_paintable_get_intrinsic_height(GDK_PAINTABLE(m_pStream))); + } + + if (!aSize.Width() || !aSize.Height()) + return nullptr; - Size aSize(200, 200); cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, aSize.Width(), aSize.Height()); GtkSnapshot* snapshot = gtk_snapshot_new(); - gdk_paintable_snapshot(current_paintable, snapshot, aSize.Width(), aSize.Height()); + gdk_paintable_snapshot(GDK_PAINTABLE(m_pStream), snapshot, aSize.Width(), aSize.Height()); GskRenderNode* node = gtk_snapshot_free_to_node(snapshot); cairo_t* cr = cairo_create(surface); @@ -338,14 +359,11 @@ public: cairo_destroy(cr); gsk_render_node_unref(node); - g_object_unref(current_paintable); std::unique_ptr<BitmapEx> xBitmap(vcl::bitmap::CreateFromCairoSurface(aSize, surface)); cairo_surface_destroy(surface); - gtk_window_destroy(GTK_WINDOW(pWindow)); - return Graphic(*xBitmap).GetXGraphic(); } }; @@ -354,16 +372,7 @@ public: uno::Reference<media::XFrameGrabber> SAL_CALL GtkPlayer::createFrameGrabber() { osl::MutexGuard aGuard(m_aMutex); - rtl::Reference<GtkFrameGrabber> xFrameGrabber; - SAL_WARN("avmedia.gtk", "TODO: createFrameGrabber"); - - // const awt::Size aPrefSize(getPreferredPlayerWindowSize()); - - xFrameGrabber.set(new GtkFrameGrabber(m_pStream)); - - // if( ( aPrefSize.Width > 0 ) && ( aPrefSize.Height > 0 ) ) - // pFrameGrabber = FrameGrabber::create( maURL ); - + rtl::Reference<GtkFrameGrabber> xFrameGrabber(new GtkFrameGrabber(m_pStream)); return xFrameGrabber; }