[cheese/wip/hadess/remove-clutter: 1/2] Port libcheese away from clutter
- From: Bastien Nocera <hadess src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [cheese/wip/hadess/remove-clutter: 1/2] Port libcheese away from clutter
- Date: Sun, 6 Feb 2022 18:18:56 +0000 (UTC)
commit 3cca9c14c17dbab3c90f0f62357b5f4195ee45bd
Author: Bastien Nocera <hadess hadess net>
Date: Sun Feb 6 19:05:19 2022 +0100
Port libcheese away from clutter
Use GStreamer's gtkglsink to display video instead of
clutter{-gst,-gtk,}.
--
TODO:
- There's no replacement for cheese_camera_size_change_cb() to handle
setting a decent size for the video display widget
- Performance seems slightly worse than clutter-gst, but there's at
least a chance to get it accelerated with the vaapi widgets for
MJPEG cameras.
- The effects pipeline is untested as there weren't any tests for
that in the tests/ subdirectory
libcheese/cheese-camera.c | 96 +++++++++++++++++-----------------------------
libcheese/cheese-camera.h | 8 ++--
libcheese/cheese-gtk.c | 11 +-----
libcheese/cheese-widget.c | 27 ++++---------
libcheese/cheese-widget.h | 2 -
libcheese/cheese.c | 11 ++----
libcheese/meson.build | 8 ++--
tests/cheese-test-camera.c | 22 ++---------
8 files changed, 57 insertions(+), 128 deletions(-)
---
diff --git a/libcheese/cheese-camera.c b/libcheese/cheese-camera.c
index e123ff34..149bef92 100644
--- a/libcheese/cheese-camera.c
+++ b/libcheese/cheese-camera.c
@@ -28,8 +28,6 @@
#include <glib-object.h>
#include <glib.h>
#include <glib/gi18n-lib.h>
-#include <clutter/clutter.h>
-#include <clutter-gst/clutter-gst.h>
#include <gst/gst.h>
/* Avoid a warning. */
#define GST_USE_UNSTABLE_API
@@ -66,7 +64,7 @@ struct _CheeseCameraPrivate
GstElement *video_source;
GstElement *camera_source;
- ClutterActor *video_texture;
+ GtkWidget *video_widget;
GstElement *effect_filter, *effects_capsfilter;
GstElement *video_balance;
@@ -99,7 +97,7 @@ G_DEFINE_TYPE_WITH_PRIVATE (CheeseCamera, cheese_camera, G_TYPE_OBJECT)
enum
{
PROP_0,
- PROP_VIDEO_TEXTURE,
+ PROP_WIDGET,
PROP_DEVICE,
PROP_FORMAT,
PROP_NUM_CAMERA_DEVICES,
@@ -1009,28 +1007,24 @@ cheese_camera_toggle_effects_pipeline (CheeseCamera *camera, gboolean active)
priv->effect_pipeline_is_playing = active;
}
-static void
-cheese_camera_connected_size_change_cb (ClutterGstContent *content, gint width, gint height, ClutterActor
*actor)
-{
- clutter_actor_set_size (actor, width, height);
-}
-
/**
* cheese_camera_connect_effect_texture:
* @camera: a #CheeseCamera
* @effect: a #CheeseEffect
- * @texture: a #ClutterActor
+ * @container: a #GtkContainer
*
- * Connect the supplied @texture to the @camera, using @effect.
+ * Insert a video widget connected to the @camera in the supplied @container, using @effect.
*/
void
-cheese_camera_connect_effect_texture (CheeseCamera *camera, CheeseEffect *effect, ClutterActor *texture)
+cheese_camera_connect_effect_texture (CheeseCamera *camera, CheeseEffect *effect, GtkContainer *container)
{
CheeseCameraPrivate *priv;
GstElement *effect_filter;
- GstElement *display_element;
+ GstElement *video_sink;
+ GstElement *glsinkbin;
GstElement *display_queue;
GstElement *control_valve;
+ GtkWidget *video_widget;
gboolean ok;
g_return_if_fail (CHEESE_IS_CAMERA (camera));
@@ -1046,27 +1040,24 @@ cheese_camera_connect_effect_texture (CheeseCamera *camera, CheeseEffect *effect
effect_filter = cheese_camera_element_from_effect (camera, effect);
- display_element = GST_ELEMENT (clutter_gst_video_sink_new ());
- g_object_set (G_OBJECT (texture),
- "content", g_object_new (CLUTTER_GST_TYPE_CONTENT,
- "sink", display_element,
- NULL),
- NULL);
-
- g_signal_connect (G_OBJECT (clutter_actor_get_content (texture)),
- "size-change", G_CALLBACK (cheese_camera_connected_size_change_cb), texture);
+ video_sink = gst_element_factory_make ("gtkglsink", "gtkglsink");
+ glsinkbin = gst_element_factory_make ("glsinkbin", "glsinkbin");
+ g_object_set (glsinkbin, "sink", video_sink, NULL);
+ g_object_get (video_sink, "widget", &video_widget, NULL);
+ gtk_container_add (container, video_widget);
+ g_object_unref (video_widget);
- gst_bin_add_many (GST_BIN (priv->video_filter_bin), control_valve, effect_filter, display_queue,
display_element, NULL);
+ gst_bin_add_many (GST_BIN (priv->video_filter_bin), control_valve, effect_filter, display_queue,
glsinkbin, NULL);
- ok = gst_element_link_many (priv->effects_tee, control_valve, effect_filter, display_queue,
display_element, NULL);
+ ok = gst_element_link_many (priv->effects_tee, control_valve, effect_filter, display_queue, glsinkbin,
NULL);
g_return_if_fail (ok);
/* HACK: I don't understand GStreamer enough to know why this works. */
gst_element_set_state (control_valve, GST_STATE_PLAYING);
gst_element_set_state (effect_filter, GST_STATE_PLAYING);
gst_element_set_state (display_queue, GST_STATE_PLAYING);
- gst_element_set_state (display_element, GST_STATE_PLAYING);
- gst_element_set_locked_state (display_element, TRUE);
+ gst_element_set_state (glsinkbin, GST_STATE_PLAYING);
+ gst_element_set_locked_state (glsinkbin, TRUE);
if (!ok)
g_warning ("Could not create effects pipeline");
@@ -1319,8 +1310,8 @@ cheese_camera_get_property (GObject *object, guint prop_id, GValue *value,
switch (prop_id)
{
- case PROP_VIDEO_TEXTURE:
- g_value_set_pointer (value, priv->video_texture);
+ case PROP_WIDGET:
+ g_value_set_pointer (value, priv->video_widget);
break;
case PROP_DEVICE:
g_value_set_object (value, priv->device);
@@ -1349,9 +1340,6 @@ cheese_camera_set_property (GObject *object, guint prop_id, const GValue *value,
switch (prop_id)
{
- case PROP_VIDEO_TEXTURE:
- priv->video_texture = g_value_get_pointer (value);
- break;
case PROP_DEVICE:
g_clear_object (&priv->device);
priv->device = g_value_dup_object (value);
@@ -1439,15 +1427,15 @@ cheese_camera_class_init (CheeseCameraClass *klass)
/**
- * CheeseCamera:video-texture:
+ * CheeseCamera:widget:
*
* The video texture for the #CheeseCamera to render into.
*/
- properties[PROP_VIDEO_TEXTURE] = g_param_spec_pointer ("video-texture",
- "Video texture",
- "The video texture for the CheeseCamera to render
into",
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS);
+ properties[PROP_WIDGET] = g_param_spec_pointer ("widget",
+ "Widget",
+ "The video widget for the CheeseCamera to render into",
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS);
/**
* CheeseCamera:device:
@@ -1502,7 +1490,6 @@ cheese_camera_init (CheeseCamera *camera)
/**
* cheese_camera_new:
- * @video_texture: an actor in which to render the video
* @name: (allow-none): the name of the device
* @x_resolution: the resolution width
* @y_resolution: the resolution height
@@ -1512,13 +1499,12 @@ cheese_camera_init (CheeseCamera *camera)
* Returns: a new #CheeseCamera
*/
CheeseCamera *
-cheese_camera_new (ClutterActor *video_texture, const gchar *name,
- gint x_resolution, gint y_resolution)
+cheese_camera_new (const gchar *name, gint x_resolution, gint y_resolution)
{
CheeseCamera *camera;
CheeseVideoFormat format = { x_resolution, y_resolution };
- camera = g_object_new (CHEESE_TYPE_CAMERA, "video-texture", video_texture,
+ camera = g_object_new (CHEESE_TYPE_CAMERA,
"format", &format, NULL);
if (name)
@@ -1546,14 +1532,6 @@ cheese_camera_set_device (CheeseCamera *camera, CheeseCameraDevice *device)
g_object_set (camera, "device", device, NULL);
}
-static void
-cheese_camera_size_change_cb (ClutterGstContent *content, gint width, gint height, CheeseCamera* camera)
-{
- CheeseCameraPrivate *priv = cheese_camera_get_instance_private (camera);
-
- clutter_actor_set_size (priv->video_texture, width, height);
-}
-
/**
* cheese_camera_setup:
* @camera: a #CheeseCamera
@@ -1567,7 +1545,7 @@ cheese_camera_setup (CheeseCamera *camera, CheeseCameraDevice *device, GError **
{
CheeseCameraPrivate *priv;
GError *tmp_error = NULL;
- GstElement *video_sink;
+ GstElement *video_sink, *glsinkbin;
g_return_if_fail (error == NULL || *error == NULL);
g_return_if_fail (CHEESE_IS_CAMERA (camera));
@@ -1614,18 +1592,14 @@ cheese_camera_setup (CheeseCamera *camera, CheeseCameraDevice *device, GError **
}
g_object_set (priv->camerabin, "camera-source", priv->camera_source, NULL);
- /* Create a clutter-gst sink and set it as camerabin sink*/
+ /* Create a GTK GL sink and set it as camerabin sink*/
- video_sink = GST_ELEMENT (clutter_gst_video_sink_new ());
- g_object_set (G_OBJECT (priv->video_texture),
- "content", g_object_new (CLUTTER_GST_TYPE_CONTENT,
- "sink", video_sink,
- NULL),
- NULL);
- g_signal_connect (G_OBJECT (clutter_actor_get_content (priv->video_texture)),
- "size-change", G_CALLBACK(cheese_camera_size_change_cb), camera);
+ video_sink = gst_element_factory_make ("gtkglsink", "gtkglsink");
+ glsinkbin = gst_element_factory_make ("glsinkbin", "glsinkbin");
+ g_object_set (glsinkbin, "sink", video_sink, NULL);
+ g_object_get (video_sink, "widget", &priv->video_widget, NULL);
- g_object_set (G_OBJECT (priv->camerabin), "viewfinder-sink", video_sink, NULL);
+ g_object_set (G_OBJECT (priv->camerabin), "viewfinder-sink", glsinkbin, NULL);
/* Set flags to enable conversions*/
diff --git a/libcheese/cheese-camera.h b/libcheese/cheese-camera.h
index 6756dff7..b87d085c 100644
--- a/libcheese/cheese-camera.h
+++ b/libcheese/cheese-camera.h
@@ -25,10 +25,9 @@
#define __CHEESE_CAMERA_H__
#include <glib-object.h>
-#include <clutter/clutter.h>
#include <cheese-camera-device.h>
#include <cheese-effect.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gtk/gtk.h>
G_BEGIN_DECLS
@@ -95,8 +94,7 @@ typedef enum
} CheeseCameraError;
GType cheese_camera_get_type (void);
-CheeseCamera *cheese_camera_new (ClutterActor *video_texture,
- const gchar *name,
+CheeseCamera *cheese_camera_new (const gchar *name,
gint x_resolution,
gint y_resolution);
@@ -107,7 +105,7 @@ void cheese_camera_stop (CheeseCamera *camera);
void cheese_camera_set_effect (CheeseCamera *camera, CheeseEffect *effect);
void cheese_camera_connect_effect_texture (CheeseCamera *camera,
CheeseEffect *effect,
- ClutterActor *texture);
+ GtkContainer *container);
void cheese_camera_start_video_recording (CheeseCamera *camera, const gchar *filename);
void cheese_camera_stop_video_recording (CheeseCamera *camera);
gboolean cheese_camera_take_photo (CheeseCamera *camera, const gchar *filename);
diff --git a/libcheese/cheese-gtk.c b/libcheese/cheese-gtk.c
index 08cca76e..faea7291 100644
--- a/libcheese/cheese-gtk.c
+++ b/libcheese/cheese-gtk.c
@@ -21,7 +21,6 @@
#ifdef GDK_WINDOWING_X11
#include <X11/Xlib.h>
#endif
-#include <clutter-gtk/clutter-gtk.h>
#include "cheese-gtk.h"
#include "cheese.h"
@@ -41,7 +40,7 @@
* @argc: (allow-none): pointer to the argument list count
* @argv: (allow-none): pointer to the argument list vector
*
- * Initialize libcheese-gtk, by initializing Clutter, GStreamer and GTK+. This
+ * Initialize libcheese-gtk, by initializing GStreamer and GTK+. This
* automatically calls cheese_init(), initializing libcheese.
*
* Returns: %TRUE if the initialization was successful, %FALSE otherwise
@@ -49,17 +48,11 @@
gboolean
cheese_gtk_init (int *argc, char ***argv)
{
- ClutterInitError error;
-
#ifdef GDK_WINDOWING_X11
XInitThreads ();
#endif
- error = gtk_clutter_init (argc, argv);
-
- if (error != CLUTTER_INIT_SUCCESS)
- return FALSE;
-
+ gtk_init (argc, argv);
if (!cheese_init (argc, argv))
return FALSE;
diff --git a/libcheese/cheese-widget.c b/libcheese/cheese-widget.c
index be697a7b..996cd41c 100644
--- a/libcheese/cheese-widget.c
+++ b/libcheese/cheese-widget.c
@@ -20,13 +20,11 @@
#include "config.h"
#include <glib/gi18n-lib.h>
-#include <clutter-gst/clutter-gst.h>
#include "cheese-widget.h"
#include "cheese-widget-private.h"
#include "cheese-camera.h"
#include "cheese-enums.h"
-#include "totem-aspect-frame.h"
/**
* SECTION:cheese-widget
@@ -70,7 +68,6 @@ typedef struct
{
GtkWidget *spinner;
GtkWidget *screen;
- ClutterActor *texture;
GtkWidget *problem;
GSettings *settings;
CheeseCamera *webcam;
@@ -201,8 +198,6 @@ cheese_widget_init (CheeseWidget *widget)
{
CheeseWidgetPrivate *priv = cheese_widget_get_instance_private (widget);
GtkWidget *box;
- ClutterActor *stage, *frame;
- ClutterColor black = { 0x00, 0x00, 0x00, 0xff };
priv->state = CHEESE_WIDGET_STATE_NONE;
priv->error = NULL;
@@ -223,20 +218,8 @@ cheese_widget_init (CheeseWidget *widget)
box, gtk_label_new ("spinner"));
/* Webcam page */
- priv->screen = gtk_clutter_embed_new ();
- gtk_widget_set_size_request (priv->screen, 460, 345);
- stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (priv->screen));
- clutter_actor_set_background_color (stage, &black);
- frame = totem_aspect_frame_new ();
-
- priv->texture = clutter_actor_new ();
- totem_aspect_frame_set_child (TOTEM_ASPECT_FRAME (frame), priv->texture);
-
- clutter_actor_set_layout_manager (stage, clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_FILL,
CLUTTER_BIN_ALIGNMENT_FILL));
- clutter_actor_add_child (stage, frame);
-
+ priv->screen = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_show (priv->screen);
- clutter_actor_show (priv->texture);
gtk_notebook_append_page (GTK_NOTEBOOK (widget),
priv->screen, gtk_label_new ("webcam"));
@@ -309,18 +292,22 @@ setup_camera (CheeseWidget *widget)
gchar *webcam_device;
gint x_resolution;
gint y_resolution;
+ GtkWidget *video_widget;
x_resolution = g_settings_get_int (priv->settings, "photo-x-resolution");
y_resolution = g_settings_get_int (priv->settings, "photo-y-resolution");
webcam_device = g_settings_get_string (priv->settings, "camera");
- priv->webcam = cheese_camera_new (priv->texture,
- webcam_device, x_resolution,
+ priv->webcam = cheese_camera_new (webcam_device,
+ x_resolution,
y_resolution);
g_free (webcam_device);
cheese_camera_setup (priv->webcam, NULL, &priv->error);
+ g_object_get (G_OBJECT (priv->webcam), "widget", &video_widget, NULL);
+ gtk_container_add (GTK_CONTAINER (priv->screen), video_widget);
+ gtk_widget_show (video_widget);
gtk_spinner_stop (GTK_SPINNER (priv->spinner));
diff --git a/libcheese/cheese-widget.h b/libcheese/cheese-widget.h
index e8923877..3aa0ad8c 100644
--- a/libcheese/cheese-widget.h
+++ b/libcheese/cheese-widget.h
@@ -22,8 +22,6 @@
#include <glib-object.h>
#include <gtk/gtk.h>
-#include <clutter/clutter.h>
-#include <clutter-gtk/clutter-gtk.h>
G_BEGIN_DECLS
diff --git a/libcheese/cheese.c b/libcheese/cheese.c
index 0e2e33e2..257d6f59 100644
--- a/libcheese/cheese.c
+++ b/libcheese/cheese.c
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <clutter-gst/clutter-gst.h>
+#include <gst/gst.h>
#include "cheese.h"
@@ -36,19 +36,14 @@
* @argc: (allow-none): pointer to the argument list count
* @argv: (allow-none): pointer to the argument list vector
*
- * Initialize libcheese, by initializing Clutter and GStreamer.
+ * Initialize libcheese, by initializing GStreamer.
*
* Returns: %TRUE if the initialization was successful, %FALSE otherwise
*/
gboolean
cheese_init (int *argc, char ***argv)
{
- ClutterInitError error;
-
- error = clutter_gst_init (argc, argv);
-
- if (error != CLUTTER_INIT_SUCCESS)
- return FALSE;
+ gst_init (argc, argv);
return TRUE;
}
diff --git a/libcheese/meson.build b/libcheese/meson.build
index 4265f878..eae80758 100644
--- a/libcheese/meson.build
+++ b/libcheese/meson.build
@@ -33,15 +33,15 @@ sources = files(
)
deps = [
- clutter_dep,
gdk_pixbuf_dep,
gio_dep,
glib_dep,
+ gtk_dep,
gstreamer_dep,
]
private_deps = [
- clutter_gst_dep,
+ gstreamer_dep,
gstreamer_pbutils_dep,
gstreamer_plugins_bad_dep,
x11_dep,
@@ -78,7 +78,6 @@ pkg.generate(
# GObject Introspection
if enable_gir
incs = [
- 'Clutter-1.0',
'GdkPixbuf-2.0',
'Gst-1.0',
]
@@ -113,12 +112,11 @@ enum_sources = gnome.mkenums_simple(
)
deps = [
- clutter_gtk_dep,
gtk_dep,
]
private_deps = [
- clutter_gst_dep,
+ gstreamer_dep,
libcanberra_gtk3_dep,
m_dep,
x11_dep,
diff --git a/tests/cheese-test-camera.c b/tests/cheese-test-camera.c
index fd058f0d..5bb64209 100644
--- a/tests/cheese-test-camera.c
+++ b/tests/cheese-test-camera.c
@@ -5,7 +5,6 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
-#include <clutter-gtk/clutter-gtk.h>
#include <gst/gst.h>
#include "cheese-camera.h"
#include "cheese.h"
@@ -34,38 +33,25 @@ main (int argc, char **argv)
GtkWidget *window;
GtkWidget *screen;
CheeseCamera *camera;
- ClutterActor *stage;
- ClutterActor *texture;
bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
- if (gtk_clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
- return EXIT_FAILURE;
-
if (!cheese_init (&argc, &argv))
return EXIT_FAILURE;
+ gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
g_signal_connect (G_OBJECT (window), "delete-event",
G_CALLBACK (delete_callback), NULL);
- screen = gtk_clutter_embed_new ();
- stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (screen));
- texture = clutter_actor_new ();
-
- clutter_actor_set_size (texture, 400, 300);
- clutter_actor_add_child (stage, texture);
-
- gtk_widget_show (screen);
- clutter_actor_show (texture);
-
- camera = cheese_camera_new (texture, NULL, 640, 480);
-
+ camera = cheese_camera_new (NULL, 640, 480);
cheese_camera_setup (camera, NULL, NULL);
+ g_object_get (G_OBJECT (camera), "widget", &screen, NULL);
+ gtk_widget_show (screen);
gtk_container_add (GTK_CONTAINER (window), screen);
gtk_widget_show_all (window);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]