[gtk/wip/gstmediafile-input: 2/2] wip: Add a bin to handle input streams




commit 92989dd89ab23dd177e069b4ccb3e3b3b0ef7850
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Jul 17 14:09:44 2021 -0400

    wip: Add a bin to handle input streams
    
    We want to use GstPlayer with input streams. The way
    to do that is to work around the uri-based GstPlayer
    api with a custom bin and a custom uri. Go gstreamer!

 modules/media/gtkgstbin.c        | 104 +++++++++++++++++++++++++++++++++++++++
 modules/media/gtkgstbinprivate.h |  33 +++++++++++++
 modules/media/gtkgstmediafile.c  |  62 +++++++++++++++--------
 modules/media/meson.build        |   1 +
 4 files changed, 180 insertions(+), 20 deletions(-)
---
diff --git a/modules/media/gtkgstbin.c b/modules/media/gtkgstbin.c
new file mode 100644
index 0000000000..56680c1d1d
--- /dev/null
+++ b/modules/media/gtkgstbin.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2021 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "gtkgstbinprivate.h"
+
+struct _GtkGstBin {
+  GstBin parent;
+
+  GstElement *src;
+  char *uri;
+};
+
+struct _GtkGstBinClass {
+  GstBinClass parent_class;
+};
+
+static GstURIType
+gtk_gst_uri_handler_get_type (GType type)
+{
+  return GST_URI_SRC;
+}
+
+static const char * const *
+gtk_gst_uri_handler_get_protocols (GType type)
+{
+  static const char *protocols[] = { "gtk-media-stream", NULL };
+
+  return protocols;
+}
+
+static char *
+gtk_gst_uri_handler_get_uri (GstURIHandler *handler)
+{
+  GtkGstBin *self = GTK_GST_BIN (handler);
+
+  return g_strdup (self->uri);
+}
+
+static gboolean
+gtk_gst_uri_handler_set_uri (GstURIHandler  *handler,
+                             const char     *uri,
+                             GError        **error)
+{
+  GtkGstBin *self = GTK_GST_BIN (handler);
+
+  g_free (self->uri);
+  self->uri = g_strdup (uri);
+
+  return TRUE;
+}
+
+static void
+gtk_gst_uri_handler_iface_init (GstURIHandlerInterface *iface)
+{
+  iface->get_type = gtk_gst_uri_handler_get_type;
+  iface->get_protocols = gtk_gst_uri_handler_get_protocols;
+  iface->get_uri = gtk_gst_uri_handler_get_uri;
+  iface->set_uri = gtk_gst_uri_handler_set_uri;
+}
+
+G_DEFINE_TYPE_WITH_CODE (GtkGstBin, gtk_gst_bin, GST_TYPE_BIN,
+                         G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER, gtk_gst_uri_handler_iface_init))
+
+static void
+gtk_gst_bin_init (GtkGstBin *self)
+{
+  self->src = gst_element_factory_make ("giostreamsrc", "src");
+  g_object_ref_sink (self->src);
+  gst_bin_add (GST_BIN (self), self->src);
+}
+
+static void
+gtk_gst_bin_class_init (GtkGstBinClass *class)
+{
+  gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (class),
+                                         "GtkGstBin",
+                                         "Source", "Handles GtkMediaFile sources",
+                                         "Matthias Clasen");
+}
+
+void
+gtk_gst_bin_set_stream (GtkGstBin    *bin,
+                        GInputStream *stream)
+{
+  g_object_set (bin->src, "stream", stream, NULL);
+}
diff --git a/modules/media/gtkgstbinprivate.h b/modules/media/gtkgstbinprivate.h
new file mode 100644
index 0000000000..8e6099e37e
--- /dev/null
+++ b/modules/media/gtkgstbinprivate.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GTK_GST_BIN_PRIVATE_H__
+#define __GTK_GST_BIN_PRIVATE_H__
+
+#include <gio/gio.h>
+#include <gst/gst.h>
+
+#define GTK_TYPE_GST_BIN (gtk_gst_bin_get_type ())
+G_DECLARE_FINAL_TYPE (GtkGstBin, gtk_gst_bin, GTK, GST_BIN, GstBin);
+
+void
+gtk_gst_bin_set_stream (GtkGstBin    *bin,
+                        GInputStream *stream);
+
+#endif /* __GTK_GST_BIN_PRIVATE_H__ */
diff --git a/modules/media/gtkgstmediafile.c b/modules/media/gtkgstmediafile.c
index 9e9edbd68c..6116a2183c 100644
--- a/modules/media/gtkgstmediafile.c
+++ b/modules/media/gtkgstmediafile.c
@@ -21,6 +21,7 @@
 
 #include "gtkgstmediafileprivate.h"
 #include "gtkgstpaintableprivate.h"
+#include "gtkgstbinprivate.h"
 
 #include <gst/player/gstplayer.h>
 #include <gst/player/gstplayer-g-main-context-signal-dispatcher.h>
@@ -31,6 +32,8 @@ struct _GtkGstMediaFile
 
   GstPlayer *player;
   GdkPaintable *paintable;
+  GstElement *playbin;
+  GtkGstBin *src;
 };
 
 struct _GtkGstMediaFileClass
@@ -213,6 +216,35 @@ gtk_gst_media_file_end_of_stream_cb (GstPlayer       *player,
   gtk_media_stream_stream_ended (GTK_MEDIA_STREAM (self));
 }
 
+static void
+gtk_gst_media_file_source_setup_cb (GstElement      *playbin,
+                                    GstElement      *source,
+                                    GtkGstMediaFile *self)
+{
+  GFile *file;
+  GInputStream *stream;
+
+  g_return_if_fail (GTK_IS_GST_BIN (source));
+
+  self->src = GTK_GST_BIN (g_object_ref (source));
+
+  file = gtk_media_file_get_file (GTK_MEDIA_FILE (self));
+  stream = gtk_media_file_get_input_stream (GTK_MEDIA_FILE (self));
+
+  if (stream)
+    g_object_ref (stream);
+  else if (file)
+    stream = G_INPUT_STREAM (g_file_read (file, NULL, NULL));
+  else
+    stream = NULL;
+
+  g_return_if_fail (stream != NULL);
+
+  gtk_gst_bin_set_stream (self->src, stream);
+
+  g_clear_object (&stream);
+}
+
 static void
 gtk_gst_media_file_destroy_player (GtkGstMediaFile *self)
 {
@@ -223,8 +255,10 @@ gtk_gst_media_file_destroy_player (GtkGstMediaFile *self)
   g_signal_handlers_disconnect_by_func (self->player, gtk_gst_media_file_end_of_stream_cb, self);
   g_signal_handlers_disconnect_by_func (self->player, gtk_gst_media_file_seek_done_cb, self);
   g_signal_handlers_disconnect_by_func (self->player, gtk_gst_media_file_error_cb, self);
-  g_object_unref (self->player);
-  self->player = NULL;
+  g_signal_handlers_disconnect_by_func (self->playbin, gtk_gst_media_file_source_setup_cb, self);
+  g_clear_object (&self->player);
+  g_clear_object (&self->playbin);
+  g_clear_object (&self->src);
 }
 
 static void
@@ -241,32 +275,19 @@ gtk_gst_media_file_create_player (GtkGstMediaFile *file)
   g_signal_connect (self->player, "end-of-stream", G_CALLBACK (gtk_gst_media_file_end_of_stream_cb), self);
   g_signal_connect (self->player, "seek-done", G_CALLBACK (gtk_gst_media_file_seek_done_cb), self);
   g_signal_connect (self->player, "error", G_CALLBACK (gtk_gst_media_file_error_cb), self);
+
+  self->playbin = gst_player_get_pipeline (self->player);
+  g_signal_connect (self->playbin, "source-setup", G_CALLBACK (gtk_gst_media_file_source_setup_cb), self);
 }
 
 static void
 gtk_gst_media_file_open (GtkMediaFile *media_file)
 {
   GtkGstMediaFile *self = GTK_GST_MEDIA_FILE (media_file);
-  GFile *file;
 
   gtk_gst_media_file_create_player (self);
 
-  file = gtk_media_file_get_file (media_file);
-
-  if (file)
-    {
-      /* XXX: This is technically incorrect because GFile uris aren't real uris */
-      char *uri = g_file_get_uri (file);
-
-      gst_player_set_uri (self->player, uri);
-
-      g_free (uri);
-    }
-  else
-    {
-      /* It's an input stream */
-      g_assert_not_reached ();
-    }
+  gst_player_set_uri (self->player, "gtk-media-stream://");
 
   gst_player_pause (self->player);
 }
@@ -361,6 +382,8 @@ gtk_gst_media_file_class_init (GtkGstMediaFileClass *klass)
   GtkMediaStreamClass *stream_class = GTK_MEDIA_STREAM_CLASS (klass);
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
+  gst_element_register (NULL, "GtkGstBin", GST_RANK_PRIMARY, GTK_TYPE_GST_BIN);
+
   file_class->open = gtk_gst_media_file_open;
   file_class->close = gtk_gst_media_file_close;
 
@@ -381,4 +404,3 @@ gtk_gst_media_file_init (GtkGstMediaFile *self)
   g_signal_connect_swapped (self->paintable, "invalidate-size", G_CALLBACK (gdk_paintable_invalidate_size), 
self);
   g_signal_connect_swapped (self->paintable, "invalidate-contents", G_CALLBACK 
(gdk_paintable_invalidate_contents), self);
 }
-
diff --git a/modules/media/meson.build b/modules/media/meson.build
index 1bd91821d8..7c0ab8fc2a 100644
--- a/modules/media/meson.build
+++ b/modules/media/meson.build
@@ -69,6 +69,7 @@ if gstplayer_dep.found() and gstgl_dep.found()
       'gtkgstmediafile.c',
       'gtkgstpaintable.c',
       'gtkgstsink.c',
+      'gtkgstbin.c',
     ],
     c_args: extra_c_args + extra_win_cflags,
     dependencies: [ libm, libgtk_dep, gstplayer_dep, gstgl_dep ],


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]