diff options
-rw-r--r-- | clutter-gst/clutter-gst-aspectratio.c | 413 | ||||
-rw-r--r-- | clutter-gst/clutter-gst-aspectratio.h | 14 | ||||
-rw-r--r-- | clutter-gst/clutter-gst-camera.c | 21 | ||||
-rw-r--r-- | clutter-gst/clutter-gst-content.c | 138 | ||||
-rw-r--r-- | clutter-gst/clutter-gst-content.h | 12 | ||||
-rw-r--r-- | clutter-gst/clutter-gst-crop.c | 181 | ||||
-rw-r--r-- | clutter-gst/clutter-gst-crop.h | 6 | ||||
-rw-r--r-- | clutter-gst/clutter-gst-playback.c | 23 | ||||
-rw-r--r-- | clutter-gst/clutter-gst-player.c | 24 | ||||
-rw-r--r-- | clutter-gst/clutter-gst-player.h | 5 | ||||
-rw-r--r-- | clutter-gst/clutter-gst-private.h | 14 | ||||
-rw-r--r-- | clutter-gst/clutter-gst-types.c | 36 | ||||
-rw-r--r-- | clutter-gst/clutter-gst-types.h | 3 | ||||
-rw-r--r-- | examples/camera-player.c | 17 | ||||
-rw-r--r-- | examples/pieces.js | 17 | ||||
-rw-r--r-- | examples/video-flip.js | 56 | ||||
-rw-r--r-- | examples/video-flip2.js | 46 | ||||
-rw-r--r-- | examples/video-player.c | 10 | ||||
-rw-r--r-- | examples/video-wall.js | 14 | ||||
-rw-r--r-- | tests/test-alpha.c | 63 | ||||
-rw-r--r-- | tests/test-rgb-upload.c | 56 | ||||
-rw-r--r-- | tests/test-start-stop.c | 54 | ||||
-rw-r--r-- | tests/test-video-actor-new-unref-loop.c | 8 | ||||
-rw-r--r-- | tests/test-yuv-upload.c | 57 |
24 files changed, 781 insertions, 507 deletions
diff --git a/clutter-gst/clutter-gst-aspectratio.c b/clutter-gst/clutter-gst-aspectratio.c index 7baa127..c875a58 100644 --- a/clutter-gst/clutter-gst-aspectratio.c +++ b/clutter-gst/clutter-gst-aspectratio.c @@ -3,8 +3,9 @@ * * GStreamer integration library for Clutter. * - * clutter-gst-aspectratio.c - An actor rendering a video with respect - * to its aspect ratio. + * clutter-gst-aspectratio.c - An object implementing the + * ClutterContent interface to render a video with respect to its + * aspect ratio. * * Authored by Lionel Landwerlin <lionel.g.landwerlin@linux.intel.com> * @@ -29,19 +30,21 @@ #include "clutter-gst-aspectratio.h" #include "clutter-gst-private.h" -G_DEFINE_TYPE (ClutterGstAspectratio, clutter_gst_aspectratio, CLUTTER_GST_TYPE_ACTOR) +static void content_iface_init (ClutterContentIface *iface); -#define ASPECTRATIO_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), CLUTTER_GST_TYPE_ASPECTRATIO, ClutterGstAspectratioPrivate)) +G_DEFINE_TYPE_WITH_CODE (ClutterGstAspectratio, + clutter_gst_aspectratio, + CLUTTER_GST_TYPE_CONTENT, + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT, + content_iface_init)) + +#define ASPECTRATIO_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ + CLUTTER_GST_TYPE_ASPECTRATIO, \ + ClutterGstAspectratioPrivate)) struct _ClutterGstAspectratioPrivate { - ClutterGstPlayer *player; - - gint frame_width; - gint frame_height; - ClutterActorBox paint_box; - gboolean paint_borders; }; @@ -55,114 +58,22 @@ enum /**/ static void -clutter_gst_aspectratio_get_preferred_width (ClutterActor *actor, - gfloat for_height, - gfloat *min_width, - gfloat *nat_width) -{ - ClutterGstAspectratioPrivate *priv = CLUTTER_GST_ASPECTRATIO (actor)->priv; - - if (min_width) - *min_width = 0; - if (nat_width) - { - gdouble aspect = (gdouble) priv->frame_width / (gdouble) priv->frame_height; - - if (for_height > 0) - *nat_width = for_height * aspect; - else - *nat_width = priv->frame_width; - } -} - -static void -clutter_gst_aspectratio_get_preferred_height (ClutterActor *actor, - gfloat for_width, - gfloat *min_height, - gfloat *nat_height) -{ - ClutterGstAspectratioPrivate *priv = CLUTTER_GST_ASPECTRATIO (actor)->priv; - - if (min_height) - *min_height = 0; - if (nat_height) - { - gdouble aspect = (gdouble) priv->frame_width / (gdouble) priv->frame_height; - - if (for_width > 0) - *nat_height = for_width / aspect; - else - *nat_height = priv->frame_height; - } -} - - -static void -clutter_gst_aspectratio_paint_frame (ClutterGstActor *self, - ClutterGstFrame *frame) -{ - ClutterGstAspectratioPrivate *priv = CLUTTER_GST_ASPECTRATIO (self)->priv; - guint8 paint_opacity; - - paint_opacity = clutter_actor_get_paint_opacity (CLUTTER_ACTOR (self)); - cogl_pipeline_set_color4ub (frame->pipeline, - paint_opacity, - paint_opacity, - paint_opacity, - paint_opacity); - cogl_set_source (frame->pipeline); - - cogl_rectangle (priv->paint_box.x1, priv->paint_box.y1, - priv->paint_box.x2, priv->paint_box.y2); - - if (priv->paint_borders) - { - ClutterColor bg_color; - ClutterActorBox box; - gfloat box_width, box_height; - - clutter_actor_get_background_color (CLUTTER_ACTOR (self), &bg_color); - clutter_actor_get_allocation_box (CLUTTER_ACTOR (self), &box); - - box_width = clutter_actor_box_get_width (&box); - box_height = clutter_actor_box_get_height (&box); - - cogl_set_source_color4ub (bg_color.red, - bg_color.green, - bg_color.blue, - paint_opacity); - - if (box_width != clutter_actor_box_get_width (&priv->paint_box)) - { - cogl_rectangle (0, 0, priv->paint_box.x1, box_height); - cogl_rectangle (priv->paint_box.x2, 0, box_width, box_height); - } - if (box_height != clutter_actor_box_get_height (&priv->paint_box)) - { - cogl_rectangle (0, 0, box_width, priv->paint_box.y1); - cogl_rectangle (0, priv->paint_box.y2, box_width, box_height); - } - } -} - -static void -_recompute_paint_box (ClutterGstAspectratio *self) +clutter_gst_aspectratio_get_frame_box (ClutterGstAspectratio *self, + ClutterGstBox *paint_box, + ClutterActorBox *content_box, + ClutterGstFrame *frame) { - ClutterGstAspectratioPrivate *priv = self->priv; - ClutterActorBox box; gfloat actor_width, actor_height; gdouble new_width, new_height; gdouble frame_aspect, actor_aspect; - clutter_actor_get_allocation_box (CLUTTER_ACTOR (self), &box); - - actor_width = box.x2 - box.x1; - actor_height = box.y2 - box.y1; + actor_width = clutter_actor_box_get_width (content_box); + actor_height = clutter_actor_box_get_height (content_box); if (actor_width <= 0 || actor_height <= 0) return; - frame_aspect = (gdouble) priv->frame_width / (gdouble) priv->frame_height; + frame_aspect = (gdouble) frame->resolution.width / (gdouble) frame->resolution.height; actor_aspect = actor_width / actor_height; if (actor_aspect < frame_aspect) @@ -176,54 +87,255 @@ _recompute_paint_box (ClutterGstAspectratio *self) new_width = actor_height * frame_aspect; } - priv->paint_box.x1 = (actor_width - new_width) / 2; - priv->paint_box.y1 = (actor_height - new_height) / 2; - priv->paint_box.x2 = priv->paint_box.x1 + new_width; - priv->paint_box.y2 = priv->paint_box.y1 + new_height; + paint_box->x1 = (actor_width - new_width) / 2; + paint_box->y1 = (actor_height - new_height) / 2; + paint_box->x2 = paint_box->x1 + new_width; + paint_box->y2 = paint_box->y1 + new_height; } -static void -_player_size_changed (ClutterGstPlayer *player, - gint width, - gint height, - ClutterGstAspectratio *self) +/**/ + +static gboolean +clutter_gst_aspectratio_get_preferred_size (ClutterContent *content, + gfloat *width, + gfloat *height) { - ClutterGstAspectratioPrivate *priv = self->priv; + ClutterGstFrame *frame = + clutter_gst_content_get_frame (CLUTTER_GST_CONTENT (content)); + + if (!frame) + return FALSE; - priv->frame_width = width; - priv->frame_height = height; + if (width) + *width = frame->resolution.width; + if (height) + *height = frame->resolution.height; - _recompute_paint_box (self); - clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); + return TRUE; } static void -_player_changed (ClutterGstAspectratio *self, - GParamSpec *spec, - gpointer user_data) +clutter_gst_aspectratio_paint_content (ClutterContent *content, + ClutterActor *actor, + ClutterPaintNode *root) { + ClutterGstAspectratio *self = CLUTTER_GST_ASPECTRATIO (content); ClutterGstAspectratioPrivate *priv = self->priv; - ClutterGstPlayer *player = clutter_gst_actor_get_player (CLUTTER_GST_ACTOR (self)); + ClutterGstFrame *frame = + clutter_gst_content_get_frame (CLUTTER_GST_CONTENT (content)); + ClutterGstBox paint_box; + ClutterActorBox content_box; + ClutterPaintNode *node; + guint8 paint_opacity = clutter_actor_get_paint_opacity (actor); + ClutterColor color; + + clutter_actor_get_content_box (actor, &content_box); + + if (!frame) + { + /* No frame to paint, just paint the background color of the + actor. */ + if (priv->paint_borders) + { + clutter_actor_get_background_color (actor, &color); + color.alpha = paint_opacity; + + clutter_paint_node_add_rectangle_custom (node, + content_box.x1, content_box.y1, + content_box.x2, content_box.y2); + clutter_paint_node_add_child (root, node); + clutter_paint_node_unref (node); + } + + return; + } + + clutter_gst_aspectratio_get_frame_box (self, &paint_box, &content_box, frame); - if (priv->player) - g_signal_handlers_disconnect_by_func (priv->player, _player_size_changed, self); - priv->player = player; - if (priv->player) + if (priv->paint_borders) { - ClutterGstFrame *frame = clutter_gst_player_get_frame (player); + clutter_actor_get_background_color (actor, &color); + color.alpha = paint_opacity; - priv->frame_width = frame->resolution.width; - priv->frame_height = frame->resolution.height; + node = clutter_color_node_new (&color); + clutter_paint_node_set_name (node, "AspectRatioVideoBorders"); - g_signal_connect (priv->player, "size-change", - G_CALLBACK (_player_size_changed), self); + if (clutter_actor_box_get_width (&content_box) != + clutter_gst_box_get_width (&paint_box)) + { + clutter_paint_node_add_rectangle_custom (node, + content_box.x1, content_box.y1, + paint_box.x1, content_box.y2); + clutter_paint_node_add_rectangle_custom (node, + paint_box.x2, content_box.y1, + content_box.x2, content_box.y2); + } + if (clutter_actor_box_get_height (&content_box) != + clutter_gst_box_get_height (&paint_box)) + { + clutter_paint_node_add_rectangle_custom (node, + content_box.x1, content_box.y1, + content_box.x2, paint_box.y1); + clutter_paint_node_add_rectangle_custom (node, + content_box.x1, paint_box.y2, + content_box.x2, content_box.y2); + } + + clutter_paint_node_add_child (root, node); + clutter_paint_node_unref (node); } - _recompute_paint_box (self); + cogl_pipeline_set_color4ub (frame->pipeline, + paint_opacity, paint_opacity, + paint_opacity, paint_opacity); + + node = clutter_pipeline_node_new (frame->pipeline); + clutter_paint_node_set_name (node, "AspectRatioVideoFrame"); + + clutter_paint_node_add_rectangle_custom (node, + paint_box.x1, paint_box.y1, + paint_box.x2, paint_box.y2); + + clutter_paint_node_add_child (root, node); + clutter_paint_node_unref (node); +} + +static void +content_iface_init (ClutterContentIface *iface) +{ + iface->get_preferred_size = clutter_gst_aspectratio_get_preferred_size; + iface->paint_content = clutter_gst_aspectratio_paint_content; } /**/ +/* static void */ +/* clutter_gst_aspectratio_paint_frame (ClutterGstActor *self, */ +/* ClutterGstFrame *frame) */ +/* { */ +/* ClutterGstAspectratioPrivate *priv = CLUTTER_GST_ASPECTRATIO (self)->priv; */ +/* guint8 paint_opacity; */ + +/* paint_opacity = clutter_actor_get_paint_opacity (CLUTTER_ACTOR (self)); */ +/* cogl_pipeline_set_color4ub (frame->pipeline, */ +/* paint_opacity, */ +/* paint_opacity, */ +/* paint_opacity, */ +/* paint_opacity); */ +/* cogl_set_source (frame->pipeline); */ + +/* cogl_rectangle (priv->paint_box.x1, priv->paint_box.y1, */ +/* priv->paint_box.x2, priv->paint_box.y2); */ + +/* if (priv->paint_borders) */ +/* { */ +/* ClutterColor bg_color; */ +/* ClutterActorBox box; */ +/* gfloat box_width, box_height; */ + +/* clutter_actor_get_background_color (CLUTTER_ACTOR (self), &bg_color); */ +/* clutter_actor_get_allocation_box (CLUTTER_ACTOR (self), &box); */ + +/* box_width = clutter_actor_box_get_width (&box); */ +/* box_height = clutter_actor_box_get_height (&box); */ + +/* cogl_set_source_color4ub (bg_color.red, */ +/* bg_color.green, */ +/* bg_color.blue, */ +/* paint_opacity); */ + +/* if (box_width != clutter_actor_box_get_width (&priv->paint_box)) */ +/* { */ +/* cogl_rectangle (0, 0, priv->paint_box.x1, box_height); */ +/* cogl_rectangle (priv->paint_box.x2, 0, box_width, box_height); */ +/* } */ +/* if (box_height != clutter_actor_box_get_height (&priv->paint_box)) */ +/* { */ +/* cogl_rectangle (0, 0, box_width, priv->paint_box.y1); */ +/* cogl_rectangle (0, priv->paint_box.y2, box_width, box_height); */ +/* } */ +/* } */ +/* } */ + +/* static void */ +/* _recompute_paint_box (ClutterGstAspectratio *self) */ +/* { */ +/* ClutterGstAspectratioPrivate *priv = self->priv; */ +/* ClutterActorBox box; */ +/* gfloat actor_width, actor_height; */ +/* gdouble new_width, new_height; */ +/* gdouble frame_aspect, actor_aspect; */ + +/* clutter_actor_get_allocation_box (CLUTTER_ACTOR (self), &box); */ + +/* actor_width = box.x2 - box.x1; */ +/* actor_height = box.y2 - box.y1; */ + +/* if (actor_width <= 0 || actor_height <= 0) */ +/* return; */ + +/* frame_aspect = (gdouble) priv->frame_width / (gdouble) priv->frame_height; */ +/* actor_aspect = actor_width / actor_height; */ + +/* if (actor_aspect < frame_aspect) */ +/* { */ +/* new_width = actor_width; */ +/* new_height = actor_width / frame_aspect; */ +/* } */ +/* else */ +/* { */ +/* new_height = actor_height; */ +/* new_width = actor_height * frame_aspect; */ +/* } */ + +/* priv->paint_box.x1 = (actor_width - new_width) / 2; */ +/* priv->paint_box.y1 = (actor_height - new_height) / 2; */ +/* priv->paint_box.x2 = priv->paint_box.x1 + new_width; */ +/* priv->paint_box.y2 = priv->paint_box.y1 + new_height; */ +/* } */ + +/* static void */ +/* _player_size_changed (ClutterGstPlayer *player, */ +/* gint width, */ +/* gint height, */ +/* ClutterGstAspectratio *self) */ +/* { */ +/* ClutterGstAspectratioPrivate *priv = self->priv; */ + +/* priv->frame_width = width; */ +/* priv->frame_height = height; */ + +/* _recompute_paint_box (self); */ +/* clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); */ +/* } */ + +/* static void */ +/* _player_changed (ClutterGstAspectratio *self, */ +/* GParamSpec *spec, */ +/* gpointer user_data) */ +/* { */ +/* ClutterGstAspectratioPrivate *priv = self->priv; */ +/* ClutterGstPlayer *player = clutter_gst_actor_get_player (CLUTTER_GST_ACTOR (self)); */ + +/* if (priv->player) */ +/* g_signal_handlers_disconnect_by_func (priv->player, _player_size_changed, self); */ +/* priv->player = player; */ +/* if (priv->player) */ +/* { */ +/* ClutterGstFrame *frame = clutter_gst_player_get_frame (player); */ + +/* priv->frame_width = frame->resolution.width; */ +/* priv->frame_height = frame->resolution.height; */ + +/* g_signal_connect (priv->player, "size-change", */ +/* G_CALLBACK (_player_size_changed), self); */ +/* } */ + +/* _recompute_paint_box (self); */ +/* } */ + +/**/ + static void clutter_gst_aspectratio_get_property (GObject *object, guint property_id, @@ -253,7 +365,11 @@ clutter_gst_aspectratio_set_property (GObject *object, switch (property_id) { case PROP_PAINT_BORDERS: - priv->paint_borders = g_value_get_boolean (value); + if (priv->paint_borders != g_value_get_boolean (value)) + { + priv->paint_borders = g_value_get_boolean (value); + clutter_content_invalidate (CLUTTER_CONTENT (object)); + } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -276,8 +392,6 @@ static void clutter_gst_aspectratio_class_init (ClutterGstAspectratioClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); - ClutterGstActorClass *gst_actor_class = CLUTTER_GST_ACTOR_CLASS (klass); GParamSpec *pspec; g_type_class_add_private (klass, sizeof (ClutterGstAspectratioPrivate)); @@ -287,11 +401,6 @@ clutter_gst_aspectratio_class_init (ClutterGstAspectratioClass *klass) object_class->dispose = clutter_gst_aspectratio_dispose; object_class->finalize = clutter_gst_aspectratio_finalize; - actor_class->get_preferred_width = clutter_gst_aspectratio_get_preferred_width; - actor_class->get_preferred_height = clutter_gst_aspectratio_get_preferred_height; - - gst_actor_class->paint_frame = clutter_gst_aspectratio_paint_frame; - /** * ClutterGstAspectratio:paint-borders: * @@ -311,14 +420,14 @@ static void clutter_gst_aspectratio_init (ClutterGstAspectratio *self) { self->priv = ASPECTRATIO_PRIVATE (self); - - g_signal_connect (self, "notify::player", - G_CALLBACK (_player_changed), NULL); - g_signal_connect_swapped (self, "allocation-changed", - G_CALLBACK (_recompute_paint_box), self); } -ClutterActor * +/** + * clutter_gst_aspectratio_new: + * + * Returns: (transfer full): a new #ClutterGstAspectratio instance + */ +ClutterContent * clutter_gst_aspectratio_new (void) { return g_object_new (CLUTTER_GST_TYPE_ASPECTRATIO, NULL); diff --git a/clutter-gst/clutter-gst-aspectratio.h b/clutter-gst/clutter-gst-aspectratio.h index fa9d8c1..3f30dad 100644 --- a/clutter-gst/clutter-gst-aspectratio.h +++ b/clutter-gst/clutter-gst-aspectratio.h @@ -3,8 +3,9 @@ * * GStreamer integration library for Clutter. * - * clutter-gst-aspectratio.c - An actor rendering a video with respect - * to its aspect ratio. + * clutter-gst-aspectratio.c - An object implementing the + * ClutterContent interface to render a video with respect to its + * aspect ratio. * * Authored by Lionel Landwerlin <lionel.g.landwerlin@linux.intel.com> * @@ -35,7 +36,7 @@ #include <glib-object.h> -#include <clutter-gst/clutter-gst-actor.h> +#include <clutter-gst/clutter-gst-content.h> G_BEGIN_DECLS @@ -67,19 +68,20 @@ typedef struct _ClutterGstAspectratioPrivate ClutterGstAspectratioPrivate; struct _ClutterGstAspectratio { - ClutterGstActor parent; + /*< private >*/ + ClutterGstContent parent; ClutterGstAspectratioPrivate *priv; }; struct _ClutterGstAspectratioClass { - ClutterGstActorClass parent_class; + ClutterGstContentClass parent_class; }; GType clutter_gst_aspectratio_get_type (void) G_GNUC_CONST; -ClutterActor *clutter_gst_aspectratio_new (void); +ClutterContent *clutter_gst_aspectratio_new (void); G_END_DECLS diff --git a/clutter-gst/clutter-gst-camera.c b/clutter-gst/clutter-gst-camera.c index 142eb48..a5736db 100644 --- a/clutter-gst/clutter-gst-camera.c +++ b/clutter-gst/clutter-gst-camera.c @@ -70,6 +70,7 @@ struct _ClutterGstCameraPrivate GstBus *bus; GstElement *camerabin; GstElement *camera_source; + CoglGstVideoSink *video_sink; /* video filter */ GstElement *video_filter_bin; @@ -137,6 +138,14 @@ clutter_gst_camera_get_pipeline (ClutterGstPlayer *player) return priv->camerabin; } +static CoglGstVideoSink * +clutter_gst_camera_get_video_sink (ClutterGstPlayer *player) +{ + ClutterGstCameraPrivate *priv = CLUTTER_GST_CAMERA (player)->priv; + + return priv->video_sink; +} + static gboolean clutter_gst_camera_get_idle (ClutterGstPlayer *player) { @@ -198,6 +207,8 @@ player_iface_init (ClutterGstPlayerIface *iface) { iface->get_frame = clutter_gst_camera_get_frame; iface->get_pipeline = clutter_gst_camera_get_pipeline; + iface->get_video_sink = clutter_gst_camera_get_video_sink; + iface->get_idle = clutter_gst_camera_get_idle; iface->get_audio_volume = clutter_gst_camera_get_audio_volume; @@ -863,18 +874,18 @@ setup_pipeline (ClutterGstCamera *self) return FALSE; } - video_sink = cogl_gst_video_sink_new (clutter_gst_get_cogl_context ()); + priv->video_sink = cogl_gst_video_sink_new (clutter_gst_get_cogl_context ()); - g_signal_connect (video_sink, "new-frame", + g_signal_connect (priv->video_sink, "new-frame", G_CALLBACK (_new_frame_from_pipeline), self); - g_signal_connect (video_sink, "pipeline-ready", + g_signal_connect (priv->video_sink, "pipeline-ready", G_CALLBACK (_ready_from_pipeline), self); - g_signal_connect (video_sink, "notify::pixel-aspect-ratio", + g_signal_connect (priv->video_sink, "notify::pixel-aspect-ratio", G_CALLBACK (_pixel_aspect_ratio_changed), self); g_object_set (priv->camerabin, - "viewfinder-sink", video_sink, + "viewfinder-sink", priv->video_sink, NULL); set_video_profile (self); diff --git a/clutter-gst/clutter-gst-content.c b/clutter-gst/clutter-gst-content.c index 2a8fea7..b1e819f 100644 --- a/clutter-gst/clutter-gst-content.c +++ b/clutter-gst/clutter-gst-content.c @@ -33,11 +33,12 @@ #include "clutter-gst-private.h" #include "clutter-gst-marshal.h" -static void clutter_content_iface_init (ClutterContentIface *iface); +static void content_iface_init (ClutterContentIface *iface); -G_DEFINE_TYPE_WITH_CODE (ClutterGstContent, clutter_gst_content, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT, - clutter_content_iface_init)); +G_DEFINE_TYPE_WITH_CODE (ClutterGstContent, + clutter_gst_content, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT, content_iface_init)) #define CLUTTER_GST_CONTENT_GET_PRIVATE(obj)\ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ @@ -48,6 +49,7 @@ G_DEFINE_TYPE_WITH_CODE (ClutterGstContent, clutter_gst_content, G_TYPE_OBJECT, struct _ClutterGstContentPrivate { CoglGstVideoSink *sink; + ClutterGstPlayer *player; ClutterGstFrame *current_frame; }; @@ -56,6 +58,7 @@ enum PROP_0, PROP_VIDEO_SINK, + PROP_PLAYER, PROP_LAST }; @@ -115,15 +118,50 @@ _pixel_aspect_ratio_changed (CoglGstVideoSink *sink, sink); } +static void content_set_sink (ClutterGstContent *self, + CoglGstVideoSink *sink, + gboolean set_from_player); + +static void +content_set_player (ClutterGstContent *self, + ClutterGstPlayer *player) +{ + ClutterGstContentPrivate *priv = self->priv; + + if (priv->player == player) + return; + + if (priv->player) + g_clear_object (&priv->sink); + + if (player) + { + priv->player = g_object_ref_sink (player); + content_set_sink (self, clutter_gst_player_get_video_sink (player), TRUE); + /* g_signal_connect (priv->player, "new-frame", */ + /* G_CALLBACK (_new_frame_from_pipeline), self); */ + /* g_signal_connect (priv->player, "notify::pixel-aspect-ratio", */ + /* G_CALLBACK (_pixel_aspect_ratio_changed), self); */ + } + else + content_set_sink (self, NULL, TRUE); + + g_object_notify (G_OBJECT (self), "player"); +} + static void content_set_sink (ClutterGstContent *self, - CoglGstVideoSink *sink) + CoglGstVideoSink *sink, + gboolean set_from_player) { ClutterGstContentPrivate *priv = self->priv; if (priv->sink == sink) return; + if (!set_from_player) + content_set_player (self, NULL); + if (priv->sink) { g_signal_handlers_disconnect_by_func (priv->sink, @@ -217,7 +255,7 @@ clutter_gst_content_paint_content (ClutterContent *content, } static void -clutter_content_iface_init (ClutterContentIface *iface) +content_iface_init (ClutterContentIface *iface) { iface->get_preferred_size = clutter_gst_content_get_preferred_size; iface->paint_content = clutter_gst_content_paint_content; @@ -234,7 +272,12 @@ clutter_gst_content_set_property (GObject *object, switch (prop_id) { case PROP_VIDEO_SINK: - content_set_sink (self, g_value_get_object (value)); + content_set_sink (self, g_value_get_object (value), FALSE); + break; + + case PROP_PLAYER: + content_set_player (self, + CLUTTER_GST_PLAYER (g_value_get_object (value))); break; default: @@ -257,6 +300,10 @@ clutter_gst_content_get_property (GObject *object, g_value_set_object (value, priv->sink); break; + case PROP_PLAYER: + g_value_set_object (value, priv->player); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -297,10 +344,17 @@ clutter_gst_content_class_init (ClutterGstContentClass *klass) g_type_class_add_private (klass, sizeof (ClutterGstContentPrivate)); + props[PROP_PLAYER] = + g_param_spec_object ("player", + "ClutterGst Player", + "ClutterGst Player", + G_TYPE_OBJECT, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + props[PROP_VIDEO_SINK] = g_param_spec_object ("video-sink", - "video-sink", - "video-sink", + "Cogl Video Sink", + "Cogl Video Sink", COGL_GST_TYPE_VIDEO_SINK, G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); g_object_class_install_properties (gobject_class, PROP_LAST, props); @@ -357,6 +411,8 @@ clutter_gst_content_new (void) * clutter_gst_content_new_with_sink: * * Returns: (transfer full): a new #ClutterGstContent instance + * + * Since: 3.0 */ ClutterContent * clutter_gst_content_new_with_sink (CoglGstVideoSink *sink) @@ -366,11 +422,44 @@ clutter_gst_content_new_with_sink (CoglGstVideoSink *sink) NULL); } +/** + * clutter_gst_content_get_frame: + * @self: A #ClutterGstContent + * + * Returns: (transfer none): The #ClutterGstFrame currently attached to @self. + * + * Since: 3.0 + */ +ClutterGstFrame * +clutter_gst_content_get_frame (ClutterGstContent *self) +{ + g_return_val_if_fail (CLUTTER_GST_IS_CONTENT (self), NULL); + + return self->priv->current_frame; +} + +/** + * clutter_gst_content_get_sink: + * @self: A #ClutterGstContent + * + * Returns: (transfer none): The #CoglGstVideoSink currently attached to @self. + * + * Since: 3.0 + */ +CoglGstVideoSink * +clutter_gst_content_get_sink (ClutterGstContent *self) +{ + g_return_val_if_fail (CLUTTER_GST_IS_CONTENT (self), NULL); + + return self->priv->sink; +} /** * clutter_gst_content_set_sink: * @self: A #ClutterGstContent * @sink: A #CoglGstVideoSink or %NULL + * + * Since: 3.0 */ void clutter_gst_content_set_sink (ClutterGstContent *self, @@ -379,19 +468,38 @@ clutter_gst_content_set_sink (ClutterGstContent *self, g_return_if_fail (CLUTTER_GST_IS_CONTENT (self)); g_return_if_fail (sink == NULL || COGL_GST_IS_VIDEO_SINK (sink)); - content_set_sink (self, sink); + content_set_sink (self, sink, FALSE); } /** - * clutter_gst_content_get_sink: + * clutter_gst_content_get_player: * @self: A #ClutterGstContent * - * Returns: (transfer none): + * Returns: (transfer none): The #ClutterGstPlayer currently attached to @self. + * + * Since: 3.0 */ -CoglGstVideoSink * -clutter_gst_content_get_sink (ClutterGstContent *self) +ClutterGstPlayer * +clutter_gst_content_get_player (ClutterGstContent *self) { g_return_val_if_fail (CLUTTER_GST_IS_CONTENT (self), NULL); - return self->priv->sink; + return self->priv->player; +} + +/** + * clutter_gst_content_set_player: + * @self: A #ClutterGstContent + * @player: A #ClutterGstPlayer or %NULL + * + * Since: 3.0 + */ +void +clutter_gst_content_set_player (ClutterGstContent *self, + ClutterGstPlayer *player) +{ + g_return_if_fail (CLUTTER_GST_IS_CONTENT (self)); + g_return_if_fail (player == NULL || CLUTTER_GST_IS_PLAYER (player)); + + content_set_player (self, player); } diff --git a/clutter-gst/clutter-gst-content.h b/clutter-gst/clutter-gst-content.h index 15d1337..c362782 100644 --- a/clutter-gst/clutter-gst-content.h +++ b/clutter-gst/clutter-gst-content.h @@ -28,6 +28,7 @@ #include <cogl-gst/cogl-gst.h> #include <clutter/clutter.h> +#include <clutter-gst/clutter-gst-player.h> G_BEGIN_DECLS @@ -56,7 +57,7 @@ typedef struct _ClutterGstContentClass ClutterGstContentClass; struct _ClutterGstContent { /*< private >*/ - GObject parent_instance; + GObject parent; ClutterGstContentPrivate *priv; }; @@ -77,15 +78,18 @@ struct _ClutterGstContentClass GType clutter_gst_content_get_type (void) G_GNUC_CONST; -ClutterContent * clutter_gst_content_new (void); - -ClutterContent * clutter_gst_content_new_with_sink (CoglGstVideoSink *sink); +ClutterGstFrame * clutter_gst_content_get_frame (ClutterGstContent *self); void clutter_gst_content_set_sink (ClutterGstContent *self, CoglGstVideoSink *sink); CoglGstVideoSink * clutter_gst_content_get_sink (ClutterGstContent *self); +ClutterGstPlayer * clutter_gst_content_get_player (ClutterGstContent *self); + +void clutter_gst_content_set_player (ClutterGstContent *self, + ClutterGstPlayer *player); + G_END_DECLS #endif /* __CLUTTER_GST_CONTENT_H__ */ diff --git a/clutter-gst/clutter-gst-crop.c b/clutter-gst/clutter-gst-crop.c index c608cdb..da5f110 100644 --- a/clutter-gst/clutter-gst-crop.c +++ b/clutter-gst/clutter-gst-crop.c @@ -29,7 +29,13 @@ #include "clutter-gst-crop.h" #include "clutter-gst-private.h" -G_DEFINE_TYPE (ClutterGstCrop, clutter_gst_crop, CLUTTER_GST_TYPE_ACTOR) +static void content_iface_init (ClutterContentIface *iface); + +G_DEFINE_TYPE_WITH_CODE (ClutterGstCrop, + clutter_gst_crop, + CLUTTER_GST_TYPE_CONTENT, + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT, + content_iface_init)) #define CROP_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CLUTTER_GST_TYPE_CROP, ClutterGstCropPrivate)) @@ -55,38 +61,63 @@ enum /**/ +static gboolean +clutter_gst_crop_get_preferred_size (ClutterContent *content, + gfloat *width, + gfloat *height) +{ + ClutterGstFrame *frame = + clutter_gst_content_get_frame (CLUTTER_GST_CONTENT (content)); + + if (!frame) + return FALSE; + + if (width) + *width = frame->resolution.width; + if (height) + *height = frame->resolution.height; + + return TRUE; +} + static void -clutter_gst_crop_paint_frame (ClutterGstActor *self, - ClutterGstFrame *frame) +clutter_gst_crop_paint_content (ClutterContent *content, + ClutterActor *actor, + ClutterPaintNode *root) { - ClutterGstCropPrivate *priv = CLUTTER_GST_CROP (self)->priv; - guint8 paint_opacity; - ClutterActorBox box; + ClutterGstCrop *self = CLUTTER_GST_CROP (content); + ClutterGstCropPrivate *priv = self->priv; + ClutterGstFrame *frame = + clutter_gst_content_get_frame (CLUTTER_GST_CONTENT (content)); + guint8 paint_opacity = clutter_actor_get_paint_opacity (actor); + ClutterActorBox content_box; gfloat box_width, box_height; + ClutterColor color; + ClutterPaintNode *node; - clutter_actor_get_allocation_box (CLUTTER_ACTOR (self), &box); - box_width = clutter_actor_box_get_width (&box); - box_height = clutter_actor_box_get_height (&box); + clutter_actor_get_content_box (actor, &content_box); - paint_opacity = clutter_actor_get_paint_opacity (CLUTTER_ACTOR (self)); - cogl_pipeline_set_color4ub (frame->pipeline, - paint_opacity, - paint_opacity, - paint_opacity, - paint_opacity); - if (priv->cull_backface) - cogl_pipeline_set_cull_face_mode (frame->pipeline, - COGL_PIPELINE_CULL_FACE_MODE_BACK); - cogl_set_source (frame->pipeline); + if (!frame) + { + /* No frame to paint, just paint the background color of the + actor. */ + if (priv->paint_borders) + { + clutter_actor_get_background_color (actor, &color); + color.alpha = paint_opacity; + + clutter_paint_node_add_rectangle_custom (node, + content_box.x1, content_box.y1, + content_box.x2, content_box.y2); + clutter_paint_node_add_child (root, node); + clutter_paint_node_unref (node); + } + + return; + } - cogl_rectangle_with_texture_coords (priv->output_region.x1 * box_width, - priv->output_region.y1 * box_height, - priv->output_region.x2 * box_width, - priv->output_region.y2 * box_height, - priv->input_region.x1, - priv->input_region.y1, - priv->input_region.x2, - priv->input_region.y2); + box_width = clutter_actor_box_get_width (&content_box); + box_height = clutter_actor_box_get_height (&content_box); if (priv->paint_borders && (priv->output_region.x1 > 0 || @@ -94,32 +125,77 @@ clutter_gst_crop_paint_frame (ClutterGstActor *self, priv->output_region.y1 > 0 || priv->output_region.y2 < 1)) { - ClutterColor bg_color; + clutter_actor_get_background_color (actor, &color); + color.alpha = paint_opacity; - clutter_actor_get_background_color (CLUTTER_ACTOR (self), &bg_color); - - cogl_set_source_color4ub (bg_color.red, - bg_color.green, - bg_color.blue, - paint_opacity); + node = clutter_color_node_new (&color); + clutter_paint_node_set_name (node, "CropVideoBorders"); if (priv->output_region.x1 > 0) - cogl_rectangle (0, 0, priv->output_region.x1 * box_width, 1); + clutter_paint_node_add_rectangle_custom (node, + content_box.x1, + content_box.y1, + content_box.x1 + box_width * priv->output_region.x1, + content_box.y2); if (priv->output_region.x2 < 1) - cogl_rectangle (priv->output_region.x2 * box_width, 0, 1, 1); + clutter_paint_node_add_rectangle_custom (node, + content_box.x1 + box_width * priv->output_region.x2, + content_box.y1, + content_box.x2, + content_box.y2); if (priv->output_region.y1 > 0) - cogl_rectangle (priv->output_region.x1 * box_width, - 0, - priv->output_region.x2 * box_width, - priv->output_region.y1 * box_height); + clutter_paint_node_add_rectangle_custom (node, + content_box.x1 + box_width * priv->output_region.x1, + content_box.y1, + content_box.x1 + box_width * priv->output_region.x2, + content_box.y1 + box_height * priv->output_region.y1); if (priv->output_region.y2 < 1) - cogl_rectangle (priv->output_region.x1 * box_width, - priv->output_region.y2 * box_height, - priv->output_region.x2 * box_width, - 0); + clutter_paint_node_add_rectangle_custom (node, + content_box.x1 + box_width * priv->output_region.x1, + content_box.y1 + box_height * priv->output_region.y2, + content_box.x1 + box_width * priv->output_region.x2, + content_box.y2); + + clutter_paint_node_add_child (root, node); + clutter_paint_node_unref (node); } + + + cogl_pipeline_set_color4ub (frame->pipeline, + paint_opacity, + paint_opacity, + paint_opacity, + paint_opacity); + if (priv->cull_backface) + cogl_pipeline_set_cull_face_mode (frame->pipeline, + COGL_PIPELINE_CULL_FACE_MODE_BACK); + + node = clutter_pipeline_node_new (frame->pipeline); + clutter_paint_node_set_name (node, "CropVideoFrame"); + + clutter_paint_node_add_texture_rectangle_custom (node, + content_box.x1 + box_width * priv->output_region.x1, + content_box.y1 + box_height * priv->output_region.y1, + content_box.x1 + box_width * priv->output_region.x2, + content_box.y1 + box_height * priv->output_region.y2, + priv->input_region.x1, + priv->input_region.y1, + priv->input_region.x2, + priv->input_region.y2); + + clutter_paint_node_add_child (root, node); + clutter_paint_node_unref (node); } +static void +content_iface_init (ClutterContentIface *iface) +{ + iface->get_preferred_size = clutter_gst_crop_get_preferred_size; + iface->paint_content = clutter_gst_crop_paint_content; +} + +/**/ + static gboolean _validate_box (ClutterGstBox *box) { @@ -178,7 +254,11 @@ clutter_gst_crop_set_property (GObject *object, switch (property_id) { case PROP_PAINT_BORDERS: - priv->paint_borders = g_value_get_boolean (value); + if (priv->paint_borders != g_value_get_boolean (value)) + { + priv->paint_borders = g_value_get_boolean (value); + clutter_content_invalidate (CLUTTER_CONTENT (object)); + } break; case PROP_CULL_BACKFACE: priv->cull_backface = g_value_get_boolean (value); @@ -187,7 +267,7 @@ clutter_gst_crop_set_property (GObject *object, box = (ClutterGstBox *) g_value_get_boxed (value); if (_validate_box (box)) { priv->input_region = *box; - clutter_actor_queue_redraw (CLUTTER_ACTOR (object)); + clutter_content_invalidate (CLUTTER_CONTENT (object)); } else g_warning ("Input region must be given in [0, 1] values."); break; @@ -195,7 +275,7 @@ clutter_gst_crop_set_property (GObject *object, box = (ClutterGstBox *) g_value_get_boxed (value); if (_validate_box (box)) { priv->output_region = *box; - clutter_actor_queue_redraw (CLUTTER_ACTOR (object)); + clutter_content_invalidate (CLUTTER_CONTENT (object)); } else g_warning ("Output region must be given in [0, 1] values."); break; @@ -230,8 +310,6 @@ clutter_gst_crop_class_init (ClutterGstCropClass *klass) object_class->dispose = clutter_gst_crop_dispose; object_class->finalize = clutter_gst_crop_finalize; - gst_actor_class->paint_frame = clutter_gst_crop_paint_frame; - /** * ClutterGstCrop:paint-borders: * @@ -304,6 +382,11 @@ clutter_gst_crop_init (ClutterGstCrop *self) priv->output_region = priv->input_region; } +/** + * clutter_gst_crop_new: + * + * Returns: (transfer full): a new #ClutterGstCrop instance + */ ClutterActor * clutter_gst_crop_new (void) { diff --git a/clutter-gst/clutter-gst-crop.h b/clutter-gst/clutter-gst-crop.h index 41a5fdf..0ec830d 100644 --- a/clutter-gst/clutter-gst-crop.h +++ b/clutter-gst/clutter-gst-crop.h @@ -35,7 +35,7 @@ #include <glib-object.h> -#include <clutter-gst/clutter-gst-actor.h> +#include <clutter-gst/clutter-gst-content.h> G_BEGIN_DECLS @@ -67,14 +67,14 @@ typedef struct _ClutterGstCropPrivate ClutterGstCropPrivate; struct _ClutterGstCrop { - ClutterGstActor parent; + ClutterGstContent parent; ClutterGstCropPrivate *priv; }; struct _ClutterGstCropClass { - ClutterGstActorClass parent_class; + ClutterGstContentClass parent_class; }; GType clutter_gst_crop_get_type (void) G_GNUC_CONST; diff --git a/clutter-gst/clutter-gst-playback.c b/clutter-gst/clutter-gst-playback.c index a368de1..7939fbb 100644 --- a/clutter-gst/clutter-gst-playback.c +++ b/clutter-gst/clutter-gst-playback.c @@ -116,6 +116,7 @@ struct _ClutterGstPlaybackPrivate { GstElement *pipeline; GstBus *bus; + CoglGstVideoSink *video_sink; ClutterGstFrame *current_frame; @@ -1378,6 +1379,14 @@ clutter_gst_playback_get_pipeline (ClutterGstPlayer *self) return priv->pipeline; } +static CoglGstVideoSink * +clutter_gst_playback_get_video_sink (ClutterGstPlayer *self) +{ + ClutterGstPlaybackPrivate *priv = CLUTTER_GST_PLAYBACK (self)->priv; + + return priv->video_sink; +} + static gboolean clutter_gst_playback_get_idle (ClutterGstPlayer *self) { @@ -1417,6 +1426,8 @@ player_iface_init (ClutterGstPlayerIface *iface) { iface->get_frame = clutter_gst_playback_get_frame; iface->get_pipeline = clutter_gst_playback_get_pipeline; + iface->get_video_sink = clutter_gst_playback_get_video_sink; + iface->get_idle = clutter_gst_playback_get_idle; iface->get_audio_volume = clutter_gst_playback_get_audio_volume; @@ -1911,8 +1922,8 @@ _pixel_aspect_ratio_changed (CoglGstVideoSink *sink, static GstElement * get_pipeline (ClutterGstPlayback *self) { + ClutterGstPlaybackPrivate *priv = self->priv; GstElement *pipeline, *audio_sink; - CoglGstVideoSink *video_sink; pipeline = gst_element_factory_make ("playbin", "pipeline"); if (!pipeline) @@ -1937,18 +1948,18 @@ get_pipeline (ClutterGstPlayback *self) } } - video_sink = cogl_gst_video_sink_new (clutter_gst_get_cogl_context ()); + priv->video_sink = cogl_gst_video_sink_new (clutter_gst_get_cogl_context ()); - g_signal_connect (video_sink, "new-frame", + g_signal_connect (priv->video_sink, "new-frame", G_CALLBACK (_new_frame_from_pipeline), self); - g_signal_connect (video_sink, "pipeline-ready", + g_signal_connect (priv->video_sink, "pipeline-ready", G_CALLBACK (_ready_from_pipeline), self); - g_signal_connect (video_sink, "notify::pixel-aspect-ratio", + g_signal_connect (priv->video_sink, "notify::pixel-aspect-ratio", G_CALLBACK (_pixel_aspect_ratio_changed), self); g_object_set (G_OBJECT (pipeline), "audio-sink", audio_sink, - "video-sink", video_sink, + "video-sink", priv->video_sink, "subtitle-font-desc", "Sans 16", NULL); diff --git a/clutter-gst/clutter-gst-player.c b/clutter-gst/clutter-gst-player.c index 7fea14e..186ff9a 100644 --- a/clutter-gst/clutter-gst-player.c +++ b/clutter-gst/clutter-gst-player.c @@ -118,6 +118,7 @@ clutter_gst_player_default_init (ClutterGstPlayerIface *iface) /** * ClutterGstPlayer::new-frame: * @player: the #ClutterGstPlayer instance that received the signal + * @frame: the #ClutterGstFrame newly receive from the video sink * * The ::ready signal is emitted each time the gstreamer pipeline * becomes ready. @@ -245,6 +246,29 @@ clutter_gst_player_get_pipeline (ClutterGstPlayer *self) } /** + * clutter_gst_player_get_video_sink: + * @self: a #ClutterGstPlayer + * + * Retrieves the #CoglGstVideoSink used by the @self. + * + * Return value: (transfer none): the #CoglGstVideoSink element used by the player + * + * Since: 3.0 + */ +CoglGstVideoSink * +clutter_gst_player_get_video_sink (ClutterGstPlayer *self) +{ + ClutterGstPlayerIface *iface; + + g_return_val_if_fail (CLUTTER_GST_IS_PLAYER (self), NULL); + + iface = CLUTTER_GST_PLAYER_GET_INTERFACE (self); + + return iface->get_video_sink (self); + +} + +/** * clutter_gst_player_get_playing: * @self: A #ClutterGstPlayer object * diff --git a/clutter-gst/clutter-gst-player.h b/clutter-gst/clutter-gst-player.h index ede3f64..5d0ea7f 100644 --- a/clutter-gst/clutter-gst-player.h +++ b/clutter-gst/clutter-gst-player.h @@ -39,8 +39,8 @@ #define __CLUTTER_GST_PLAYER_H__ #include <glib-object.h> -#include <cogl/cogl.h> #include <gst/gst.h> +#include <cogl-gst/cogl-gst.h> #include <clutter-gst/clutter-gst-types.h> @@ -93,6 +93,7 @@ struct _ClutterGstPlayerIface /*< public >*/ ClutterGstFrame * (* get_frame) (ClutterGstPlayer *self); GstElement * (* get_pipeline) (ClutterGstPlayer *self); + CoglGstVideoSink *(* get_video_sink) (ClutterGstPlayer *self); gboolean (* get_idle) (ClutterGstPlayer *self); @@ -136,6 +137,8 @@ ClutterGstFrame * clutter_gst_player_get_frame (ClutterGstPlayer GstElement * clutter_gst_player_get_pipeline (ClutterGstPlayer *self); +CoglGstVideoSink * clutter_gst_player_get_video_sink (ClutterGstPlayer *self); + gboolean clutter_gst_player_get_idle (ClutterGstPlayer *self); gboolean clutter_gst_player_get_playing (ClutterGstPlayer *self); diff --git a/clutter-gst/clutter-gst-private.h b/clutter-gst/clutter-gst-private.h index 9fa9939..6483329 100644 --- a/clutter-gst/clutter-gst-private.h +++ b/clutter-gst/clutter-gst-private.h @@ -47,6 +47,19 @@ G_BEGIN_DECLS #define CLUTTER_GST_PARAM_READWRITE \ (G_PARAM_READABLE | G_PARAM_WRITABLE | CLUTTER_GST_PARAM_STATIC) +#define clutter_paint_node_add_rectangle_custom(node,x1,y1,x2,y2) \ + do { \ + ClutterActorBox _box = { x1, y1, x2, y2 }; \ + clutter_paint_node_add_rectangle (node, &_box); \ + } while (0) + +#define clutter_paint_node_add_texture_rectangle_custom(node,x1,y1,x2,y2,tx1,ty1,tx2,ty2) \ + do { \ + ClutterActorBox _box = { x1, y1, x2, y2 }; \ + clutter_paint_node_add_texture_rectangle (node, &_box, \ + tx1, ty1, tx2, ty2); \ + } while (0) + gboolean _internal_plugin_init (GstPlugin *plugin); @@ -64,7 +77,6 @@ void clutter_gst_player_update_frame (ClutterGstPlayer *player, void clutter_gst_frame_update_pixel_aspect_ratio (ClutterGstFrame *frame, CoglGstVideoSink *sink); - G_END_DECLS #endif /* __CLUTTER_GST_PRIVATE_H__ */ diff --git a/clutter-gst/clutter-gst-types.c b/clutter-gst/clutter-gst-types.c index 00b8a1b..ebab80e 100644 --- a/clutter-gst/clutter-gst-types.c +++ b/clutter-gst/clutter-gst-types.c @@ -98,3 +98,39 @@ G_DEFINE_BOXED_TYPE (ClutterGstBox, clutter_gst_box, clutter_gst_box_copy, clutter_gst_box_free); + +/** + * clutter_gst_box_get_width: + * @box: a #ClutterGstBox + * + * Retrieves the width of the @box + * + * Return value: the width of the box + * + * Since: 3.0 + */ +gfloat +clutter_gst_box_get_width (const ClutterGstBox *box) +{ + g_return_val_if_fail (box != NULL, 0.); + + return box->x2 - box->x1; +} + +/** + * clutter_gst_box_get_height: + * @box: a #ClutterGstBox + * + * Retrieves the height of the @box + * + * Return value: the height of the box + * + * Since: 3.0 + */ +gfloat +clutter_gst_box_get_height (const ClutterGstBox *box) +{ + g_return_val_if_fail (box != NULL, 0.); + + return box->y2 - box->y1; +} diff --git a/clutter-gst/clutter-gst-types.h b/clutter-gst/clutter-gst-types.h index 8a38106..0aeb94d 100644 --- a/clutter-gst/clutter-gst-types.h +++ b/clutter-gst/clutter-gst-types.h @@ -124,4 +124,7 @@ struct _ClutterGstBox GType clutter_gst_frame_get_type (void) G_GNUC_CONST; GType clutter_gst_box_get_type (void) G_GNUC_CONST; +gfloat clutter_gst_box_get_width (const ClutterGstBox *box); +gfloat clutter_gst_box_get_height (const ClutterGstBox *box); + #endif /* __CLUTTER_GST_TYPES_H__ */ diff --git a/examples/camera-player.c b/examples/camera-player.c index e601d50..e5e25a1 100644 --- a/examples/camera-player.c +++ b/examples/camera-player.c @@ -329,9 +329,8 @@ size_change (ClutterGstPlayer *player, /* base_width and base_height are the actual dimensions of the buffers before * taking the pixel aspect ratio into account. We need to get the actual * size of the texture to display */ - clutter_actor_get_preferred_size (app->camera_actor, - NULL, NULL, - &frame_width, &frame_height); + clutter_content_get_preferred_size (clutter_actor_get_content (app->camera_actor), + &frame_width, &frame_height); new_height = (frame_height * stage_width) / frame_width; if (new_height <= stage_height) @@ -386,7 +385,6 @@ main (int argc, char *argv[]) app = g_new0(CameraApp, 1); app->stage = stage; - app->camera_actor = clutter_gst_aspectratio_new (); app->camera_player = clutter_gst_camera_new (); if (app->camera_player == NULL) @@ -395,6 +393,13 @@ main (int argc, char *argv[]) return EXIT_FAILURE; } + app->camera_actor = g_object_new (CLUTTER_TYPE_ACTOR, + "content", g_object_new (CLUTTER_GST_TYPE_ASPECTRATIO, + "player", app->camera_player, + NULL), + NULL); + + app->camera_devices = clutter_gst_camera_get_camera_devices (app->camera_player); if (!app->camera_devices) { @@ -429,10 +434,6 @@ main (int argc, char *argv[]) "size-change", G_CALLBACK (size_change), app); - - clutter_gst_actor_set_player (CLUTTER_GST_ACTOR (app->camera_actor), - CLUTTER_GST_PLAYER (app->camera_player)); - /* Add control UI to stage */ clutter_actor_add_child (stage, app->camera_actor); diff --git a/examples/pieces.js b/examples/pieces.js index 5642752..34606c3 100644 --- a/examples/pieces.js +++ b/examples/pieces.js @@ -131,13 +131,16 @@ for (let i = 0; i < ROWS; i++) { y1: i / ROWS, y2: (i + 1) / ROWS, }) - let actor = new ClutterGst.Crop({ width: BIT_WIDTH, - height: BIT_HEIGHT, - player: player, - x: BIT_WIDTH * j, - y: BIT_HEIGHT * i, - input_region: input, - }); + let actor = new Clutter.Actor({ + width: BIT_WIDTH, + height: BIT_HEIGHT, + x: BIT_WIDTH * j, + y: BIT_HEIGHT * i, + content: new ClutterGst.Crop({ + player: player, + input_region: input, + }), + }); stage.add_actor(actor); pieces.array[i][j] = actor; diff --git a/examples/video-flip.js b/examples/video-flip.js index f320cef..4776750 100644 --- a/examples/video-flip.js +++ b/examples/video-flip.js @@ -45,12 +45,12 @@ stage.set_background_color(new Clutter.Color({ red: 0, stage.connect('destroy', Lang.bind(this, function() { Clutter.main_quit(); })); -player1 = new ClutterGst.Playback(); +let player1 = new ClutterGst.Playback(); player1.set_filename(ARGV[0]); player1.set_audio_volume(0); player1.set_progress(0.20); -player2 = new ClutterGst.Playback(); +let player2 = new ClutterGst.Playback(); player2.set_filename(ARGV[1]); player2.set_audio_volume(0); player2.set_progress(0.20); @@ -125,30 +125,36 @@ for (let i = 0; i < ROWS; i++) { y2: (i + 1) / ROWS, }) let actor = - new ClutterGst.Crop({ reactive: true, - cull_backface: true, - pivot_point: new Clutter.Point({ x: 0.5, - y: 0.5 }), - width: 200, - height: 200, - x: -200, - y: -200, - input_region: input, - player: player1, - }); + new Clutter.Actor({ + reactive: true, + pivot_point: new Clutter.Point({ x: 0.5, + y: 0.5 }), + width: 200, + height: 200, + x: -200, + y: -200, + content: new ClutterGst.Crop({ + cull_backface: true, + input_region: input, + player: player1, + }), + }); actor._backActor = - new ClutterGst.Crop({ reactive: false, - cull_backface: true, - pivot_point: new Clutter.Point({ x: 0.5, - y: 0.5 }), - rotation_angle_y: 180, - width: 200, - height: 200, - x: -200, - y: -200, - input_region: input, - player: player2, - }); + new Clutter.Actor({ + reactive: false, + pivot_point: new Clutter.Point({ x: 0.5, + y: 0.5 }), + rotation_angle_y: 180, + width: 200, + height: 200, + x: -200, + y: -200, + content: new ClutterGst.Crop({ + cull_backface: true, + input_region: input, + player: player2, + }), + }); stage.add_child(actor); stage.add_child(actor._backActor); diff --git a/examples/video-flip2.js b/examples/video-flip2.js index 25ae4b8..98966ec 100644 --- a/examples/video-flip2.js +++ b/examples/video-flip2.js @@ -119,27 +119,27 @@ Players.prototype = { updateActorsCurrent: function(actors, back) { for (let i in actors) { if (back) - actors[i]._backActor.player = this.getCurrentPlayer(); + actors[i]._backActor.content.player = this.getCurrentPlayer(); else - actors[i].player = this.getCurrentPlayer(); + actors[i].content.player = this.getCurrentPlayer(); } }, updateActorsNext: function(actors, back) { for (let i in actors) { if (back) - actors[i]._backActor.player = this.getNextPlayer(); + actors[i]._backActor.content.player = this.getNextPlayer(); else - actors[i].player = this.getNextPlayer(); + actors[i].content.player = this.getNextPlayer(); } }, updateActorsPrevious: function(actors, back) { for (let i in actors) { if (back) - actors[i]._backActor.player = this.getPreviousPlayer(); + actors[i]._backActor.content.player = this.getPreviousPlayer(); else - actors[i].player = this.getPreviousPlayer(); + actors[i].content.player = this.getPreviousPlayer(); } }, @@ -241,22 +241,26 @@ for (let i = 0; i < ROWS; i++) { y2: (i + 1) / ROWS, }) let actor = - new ClutterGst.Crop({ cull_backface: true, - pivot_point: new Clutter.Point({ x: 0.5, - y: 0.5 }), - width: TILE_WIDTH, - height: TILE_HEIGHT, - input_region: input, - }); + new Clutter.Actor({ + pivot_point: new Clutter.Point({ x: 0.5, + y: 0.5 }), + width: TILE_WIDTH, + height: TILE_HEIGHT, + content: new ClutterGst.Crop({ cull_backface: true, + input_region: input, + }), + }); actor._backActor = - new ClutterGst.Crop({ cull_backface: true, - pivot_point: new Clutter.Point({ x: 0.5, - y: 0.5 }), - rotation_angle_y: 180, - width: TILE_WIDTH, - height: TILE_HEIGHT, - input_region: input, - }); + new Clutter.Actor({ + pivot_point: new Clutter.Point({ x: 0.5, + y: 0.5 }), + rotation_angle_y: 180, + width: TILE_WIDTH, + height: TILE_HEIGHT, + content: new ClutterGst.Crop({ cull_backface: true, + input_region: input, + }), + }); stage.add_child(actor); stage.add_child(actor._backActor); diff --git a/examples/video-player.c b/examples/video-player.c index e9435c1..b3e1317 100644 --- a/examples/video-player.c +++ b/examples/video-player.c @@ -469,11 +469,15 @@ main (int argc, char *argv[]) app = g_new0(VideoApp, 1); app->stage = stage; - app->vactor = g_object_new (CLUTTER_GST_TYPE_ASPECTRATIO, NULL); - clutter_actor_set_size (app->vactor, clutter_actor_get_width (stage), clutter_actor_get_height (stage)); app->player = clutter_gst_playback_new (); - clutter_gst_actor_set_player (CLUTTER_GST_ACTOR (app->vactor), CLUTTER_GST_PLAYER (app->player)); + app->vactor = g_object_new (CLUTTER_TYPE_ACTOR, + "width", clutter_actor_get_width (stage), + "height", clutter_actor_get_height (stage), + "content", g_object_new (CLUTTER_GST_TYPE_ASPECTRATIO, + "player", app->player, + NULL), + NULL); if (app->vactor == NULL) g_error("failed to create vactor"); diff --git a/examples/video-wall.js b/examples/video-wall.js index adb39a4..151f11c 100644 --- a/examples/video-wall.js +++ b/examples/video-wall.js @@ -45,7 +45,7 @@ stage.set_background_color(new Clutter.Color({ red: 0, stage.connect('destroy', Lang.bind(this, function() { Clutter.main_quit(); })); -player = new ClutterGst.Playback(); +let player = new ClutterGst.Playback(); player.set_filename(ARGV[0]); player.set_audio_volume(0); player.set_progress(0.20); @@ -136,11 +136,13 @@ for (let i = 0; i < ROWS; i++) { y1: i / ROWS, y2: (i + 1) / ROWS, }) - let subActor = new ClutterGst.Crop({ width: 200, - height: 200, - player: player, - input_region: input, - }); + let subActor = new Clutter.Actor({ + width: 200, + height: 200, + content: new ClutterGst.Crop({ player: player, + input_region: input, + }), + }); let actor = new Clutter.Actor(); actor.add_child(subActor); diff --git a/tests/test-alpha.c b/tests/test-alpha.c index 6faaac5..f15e0e8 100644 --- a/tests/test-alpha.c +++ b/tests/test-alpha.c @@ -32,6 +32,7 @@ #include <glib/gprintf.h> #include <clutter-gst/clutter-gst.h> +#include <cogl-gst/cogl-gst.h> static gint opt_framerate = 30; static gchar *opt_fourcc = "I420"; @@ -65,44 +66,6 @@ parse_fourcc (const gchar *fourcc) return GST_STR_FOURCC (fourcc); } -static void -size_change (ClutterGstPlayer *player, - gint width, - gint height, - ClutterActor *actor) -{ - ClutterActor *stage; - gfloat new_x, new_y, new_width, new_height; - gfloat stage_width, stage_height; - - stage = clutter_actor_get_stage (actor); - if (stage == NULL) - return; - - clutter_actor_get_size (stage, &stage_width, &stage_height); - - new_height = (height * stage_width) / width; - if (new_height <= stage_height) - { - new_width = stage_width; - - new_x = 0; - new_y = (stage_height - new_height) / 2; - } - else - { - new_width = (width * stage_height) / height; - new_height = stage_height; - - new_x = (stage_width - new_width) / 2; - new_y = 0; - } - - g_message ("resize %fx%f @ %fx%f", new_width, new_height, new_x, new_y); - clutter_actor_set_position (actor, new_x, new_y); - clutter_actor_set_size (actor, new_width, new_height); -} - int main (int argc, char *argv[]) { @@ -116,7 +79,6 @@ main (int argc, char *argv[]) ClutterActor *actor; ClutterActor *rectangle; ClutterTransition *animation; - ClutterGstPlayer *player; GstPipeline *pipeline; GstElement *src; @@ -152,9 +114,6 @@ main (int argc, char *argv[]) rectangle_geom.size.width, rectangle_geom.size.height); - actor = clutter_gst_actor_new (); - clutter_actor_set_opacity (actor, 0); - /* Set up pipeline */ pipeline = GST_PIPELINE(gst_pipeline_new (NULL)); @@ -163,6 +122,16 @@ main (int argc, char *argv[]) capsfilter = gst_element_factory_make ("capsfilter", NULL); sink = clutter_gst_create_video_sink (); + /* Video actor */ + actor = g_object_new (CLUTTER_TYPE_ACTOR, + "content", g_object_new (CLUTTER_GST_TYPE_CONTENT, + "video-sink", sink, + NULL), + "width", clutter_actor_get_width (stage), + "height", clutter_actor_get_height (stage), + NULL); + clutter_actor_set_opacity (actor, 0); + /* make videotestsrc spit the format we want */ if (g_strcmp0 (opt_fourcc, "RGB ") == 0) { @@ -192,20 +161,10 @@ main (int argc, char *argv[]) g_critical("Could not link elements"); gst_element_set_state (GST_ELEMENT(pipeline), GST_STATE_PLAYING); - player = CLUTTER_GST_PLAYER (g_object_new (CLUTTER_GST_TYPE_PIPELINE, - "video-sink", sink, NULL)); - - g_signal_connect (player, - "size-change", - G_CALLBACK (size_change), actor); - clutter_actor_add_child (stage, rectangle); clutter_actor_add_child (stage, actor); clutter_actor_show (stage); - clutter_gst_actor_set_player (CLUTTER_GST_ACTOR (actor), player); - - clutter_actor_save_easing_state (actor); clutter_actor_set_easing_mode (actor, CLUTTER_LINEAR); clutter_actor_set_easing_duration (actor, 6000); diff --git a/tests/test-rgb-upload.c b/tests/test-rgb-upload.c index eae4d5d..aa8f202 100644 --- a/tests/test-rgb-upload.c +++ b/tests/test-rgb-upload.c @@ -63,43 +63,6 @@ static GOptionEntry options[] = { NULL } }; -void -size_change (ClutterGstPlayer *player, - gint width, - gint height, - ClutterActor *actor) -{ - ClutterActor *stage; - gfloat new_x, new_y, new_width, new_height; - gfloat stage_width, stage_height; - - stage = clutter_actor_get_stage (actor); - if (stage == NULL) - return; - - clutter_actor_get_size (stage, &stage_width, &stage_height); - - new_height = (height * stage_width) / width; - if (new_height <= stage_height) - { - new_width = stage_width; - - new_x = 0; - new_y = (stage_height - new_height) / 2; - } - else - { - new_width = (width * stage_height) / height; - new_height = stage_height; - - new_x = (stage_height - new_width) / 2; - new_y = 0; - } - - clutter_actor_set_position (actor, new_x, new_y); - clutter_actor_set_size (actor, new_width, new_height); -} - int main (int argc, char *argv[]) { @@ -132,7 +95,6 @@ main (int argc, char *argv[]) stage = clutter_stage_new (); clutter_actor_set_size (CLUTTER_ACTOR (stage), 320.0f, 240.0f); - actor = clutter_gst_actor_new (); /* Set up pipeline */ pipeline = GST_PIPELINE(gst_pipeline_new (NULL)); @@ -141,6 +103,16 @@ main (int argc, char *argv[]) capsfilter = gst_element_factory_make ("capsfilter", NULL); sink = clutter_gst_create_video_sink (); + /* Video actor */ + actor = g_object_new (CLUTTER_TYPE_ACTOR, + "content", g_object_new (CLUTTER_GST_TYPE_CONTENT, + "video-sink", sink, + NULL), + "width", clutter_actor_get_width (stage), + "height", clutter_actor_get_height (stage), + NULL); + + format = gst_video_format_from_masks(opt_depth, opt_bpp, G_BIG_ENDIAN, 0xff0000, 0x00ff00, @@ -160,14 +132,6 @@ main (int argc, char *argv[]) g_critical("Could not link elements"); gst_element_set_state (GST_ELEMENT(pipeline), GST_STATE_PLAYING); - - player = CLUTTER_GST_PLAYER (g_object_new (CLUTTER_GST_TYPE_PIPELINE, - "video-sink", sink, NULL)); - clutter_gst_actor_set_player (CLUTTER_GST_ACTOR (actor), player); - g_signal_connect (player, - "size-change", - G_CALLBACK (size_change), actor); - clutter_actor_add_child (stage, actor); clutter_actor_show (stage); diff --git a/tests/test-start-stop.c b/tests/test-start-stop.c index a9efe4d..9bc1ea9 100644 --- a/tests/test-start-stop.c +++ b/tests/test-start-stop.c @@ -33,45 +33,6 @@ char *video_files[] = {NULL, NULL}; void -size_change (ClutterGstPlayer *player, - gint width, - gint height, - ClutterActor *actor) -{ - ClutterActor *stage = clutter_actor_get_stage (actor); - gfloat new_x, new_y, new_width, new_height; - gfloat stage_width, stage_height; - - g_message ("size change %ix%i", width, height); - - clutter_actor_get_size (stage, &stage_width, &stage_height); - - /* new_height = (height * stage_width) / width; */ - /* if (new_height <= stage_height) */ - /* { */ - /* new_width = stage_width; */ - - /* new_x = 0; */ - /* new_y = (stage_height - new_height) / 2; */ - /* } */ - /* else */ - /* { */ - /* new_width = (width * stage_height) / height; */ - /* new_height = stage_height; */ - - /* new_x = (stage_width - new_width) / 2; */ - /* new_y = 0; */ - /* } */ - - /* clutter_actor_set_position (actor, new_x, new_y); */ - clutter_actor_set_size (actor, stage_width, stage_height); - - g_message (" new pos/size -> x,y=%.2fx%.2f w,h=%.2fx%.2f", - new_x, new_y, stage_width, stage_height); - -} - -void on_error (ClutterGstPlayer *player) { g_print ("error\n"); @@ -151,17 +112,18 @@ main (int argc, char *argv[]) stage = clutter_stage_new (); clutter_actor_set_background_color (stage, &stage_color); - video = clutter_gst_aspectratio_new (); - player = clutter_gst_playback_new (); - clutter_gst_actor_set_player (CLUTTER_GST_ACTOR (video), CLUTTER_GST_PLAYER (player)); + + video = g_object_new (CLUTTER_TYPE_ACTOR, + "content", g_object_new (CLUTTER_GST_TYPE_ASPECTRATIO, + "player", player, + NULL), + "width", clutter_actor_get_width (stage), + "height", clutter_actor_get_height (stage), + NULL); clutter_actor_add_child (stage, video); g_signal_connect (player, - "size-change", - G_CALLBACK(size_change), - video); - g_signal_connect (player, "error", G_CALLBACK(on_error), video); diff --git a/tests/test-video-actor-new-unref-loop.c b/tests/test-video-actor-new-unref-loop.c index fd98a6a..15714e6 100644 --- a/tests/test-video-actor-new-unref-loop.c +++ b/tests/test-video-actor-new-unref-loop.c @@ -35,7 +35,7 @@ int main (int argc, char *argv[]) { - ClutterActor *vactor; + ClutterGstPlayer *player; int i; clutter_gst_init (&argc, &argv); @@ -43,9 +43,9 @@ main (int argc, char *argv[]) for (i = 0; ; i++) { g_debug("VideoActor #%d", i); - vactor = clutter_gst_actor_new (); - g_object_ref_sink (vactor); - g_object_unref (vactor); + player = CLUTTER_GST_PLAYER (clutter_gst_playback_new ()); + g_object_ref_sink (player); + g_object_unref (player); } return EXIT_SUCCESS; diff --git a/tests/test-yuv-upload.c b/tests/test-yuv-upload.c index 1a451bf..347bcd0 100644 --- a/tests/test-yuv-upload.c +++ b/tests/test-yuv-upload.c @@ -52,43 +52,6 @@ static GOptionEntry options[] = { NULL } }; -void -size_change (ClutterGstPlayer *player, - gint width, - gint height, - ClutterActor *actor) -{ - ClutterActor *stage; - gfloat new_x, new_y, new_width, new_height; - gfloat stage_width, stage_height; - - stage = clutter_actor_get_stage (actor); - if (stage == NULL) - return; - - clutter_actor_get_size (stage, &stage_width, &stage_height); - - new_height = (height * stage_width) / width; - if (new_height <= stage_height) - { - new_width = stage_width; - - new_x = 0; - new_y = (stage_height - new_height) / 2; - } - else - { - new_width = (width * stage_height) / height; - new_height = stage_height; - - new_x = (stage_width - new_width) / 2; - new_y = 0; - } - - clutter_actor_set_position (actor, new_x, new_y); - clutter_actor_set_size (actor, new_width, new_height); -} - int main (int argc, char *argv[]) { @@ -118,9 +81,8 @@ main (int argc, char *argv[]) } stage = clutter_stage_new (); - clutter_actor_set_size (CLUTTER_ACTOR(stage), 320.0f, 240.0f); + clutter_actor_set_size (CLUTTER_ACTOR (stage), 320.0f, 240.0f); - actor = g_object_new (CLUTTER_GST_TYPE_ACTOR, NULL); /* Set up pipeline */ pipeline = GST_PIPELINE(gst_pipeline_new (NULL)); @@ -129,6 +91,15 @@ main (int argc, char *argv[]) capsfilter = gst_element_factory_make ("capsfilter", NULL); sink = clutter_gst_create_video_sink (); + /* Video actor */ + actor = g_object_new (CLUTTER_TYPE_ACTOR, + "content", g_object_new (CLUTTER_GST_TYPE_CONTENT, + "video-sink", sink, + NULL), + "width", clutter_actor_get_width (stage), + "height", clutter_actor_get_height (stage), + NULL); + /* make videotestsrc spit the format we want */ caps = gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING, opt_fourcc, @@ -143,15 +114,7 @@ main (int argc, char *argv[]) g_critical("Could not link elements"); gst_element_set_state (GST_ELEMENT(pipeline), GST_STATE_PLAYING); - player = CLUTTER_GST_PLAYER (g_object_new (CLUTTER_GST_TYPE_PIPELINE, - "video-sink", sink, NULL)); - clutter_gst_actor_set_player (CLUTTER_GST_ACTOR (actor), player); - g_signal_connect (player, - "size-change", - G_CALLBACK (size_change), actor); - clutter_actor_add_child (stage, actor); - /* clutter_actor_set_opacity (texture, 0x11); */ clutter_actor_show (stage); clutter_main(); |