4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Sangchul Lee <sc11.lee@samsung.com>
8 * This library is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU Lesser General Public License as published by the
10 * Free Software Foundation; either version 2.1 of the License, or (at your option)
13 * This library is distributed in the hope that it will be useful, but WITHOUT ANY
14 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 * License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this library; if not, write to the Free Software Foundation, Inc., 51
20 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 * SECTION:element-evasimagesink
26 * Gstreamer Evas Video Sink - draw video on the given Evas Image Object
33 #include <sys/types.h>
35 #include <gst/video/video.h>
36 #include <gst/video/gstvideosink.h>
41 #include "gstevasimagesink.h"
43 #define CAP_WIDTH "width"
44 #define CAP_HEIGHT "height"
46 GST_DEBUG_CATEGORY_STATIC (gst_evas_image_sink_debug);
47 #define GST_CAT_DEFAULT gst_evas_image_sink_debug
60 PROP_EVAS_OBJECT_SHOW,
64 #define GL_X11_ENGINE "gl_x11"
66 static inline gboolean
67 is_evas_image_object (Evas_Object *obj)
73 type = evas_object_type_get (obj);
77 if (strcmp (type, "image") == 0) {
83 /* the capabilities of the inputs.
87 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
90 GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx));
92 GST_BOILERPLATE (GstEvasImageSink, gst_evas_image_sink, GstVideoSink, GST_TYPE_VIDEO_SINK);
94 static void gst_evas_image_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
95 static void gst_evas_image_sink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
96 static gboolean gst_evas_image_sink_set_caps (GstBaseSink * base_sink, GstCaps * caps);
97 static GstFlowReturn gst_evas_image_sink_show_frame (GstVideoSink * video_sink, GstBuffer * buf);
100 gst_evas_image_sink_base_init (gpointer gclass)
102 GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
104 gst_element_class_set_details_simple (element_class,
107 "Video sink element for evas image object",
108 "Wonguk Jeong <wonguk.jeong@samsung.com>");
110 gst_element_class_add_pad_template (element_class,
111 gst_static_pad_template_get (&sink_factory));
115 gst_evas_image_sink_class_init (GstEvasImageSinkClass * klass)
117 GObjectClass *gobject_class;
118 GstBaseSinkClass *gstbasesink_class;
119 GstVideoSinkClass *gstvideosink_class;
121 gobject_class = (GObjectClass *) klass;
122 gstbasesink_class = GST_BASE_SINK_CLASS (klass);
123 gstvideosink_class = GST_VIDEO_SINK_CLASS (klass);
125 gobject_class->set_property = gst_evas_image_sink_set_property;
126 gobject_class->get_property = gst_evas_image_sink_get_property;
128 g_object_class_install_property (gobject_class, PROP_EVAS_OBJECT,
129 g_param_spec_pointer ("evas-object", "Destination Evas Object", "Destination evas image object", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
130 g_object_class_install_property (gobject_class, PROP_EVAS_OBJECT_SHOW,
131 g_param_spec_boolean ("visible", "Show Evas Object", "When disabled, evas object does not show", TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
133 gstvideosink_class->show_frame = gst_evas_image_sink_show_frame;
134 gstbasesink_class->set_caps = gst_evas_image_sink_set_caps;
138 gst_evas_image_sink_fini (gpointer data, GObject *obj)
140 GstEvasImageSink *esink = GST_EVASIMAGESINK (obj);
145 ecore_pipe_del (esink->epipe);
148 gst_buffer_unref (esink->oldbuf);
153 evas_image_sink_cb_pipe (void *data, void *buffer, unsigned int nbyte)
156 GstEvasImageSink *esink = data;
159 if (!data || !buffer) {
162 if (nbyte != sizeof (GstBuffer *)) {
169 memcpy (&buf, buffer, sizeof (GstBuffer *));
171 GST_ERROR ("There is no buffer\n");
175 if (esink->gl_zerocopy) {
176 img_data = evas_object_image_data_get (esink->eo, EINA_TRUE);
177 if (!img_data || !GST_BUFFER_DATA(buf)) {
178 GST_WARNING ("Cannot get image data from evas object or cannot get gstbuffer data\n");
179 evas_object_image_data_set(esink->eo, img_data);
181 GST_DEBUG ("img_data(%x), GST_BUFFER_DATA(buf):%x, esink->w(%d),esink->h(%d)",img_data,GST_BUFFER_DATA(buf),esink->w,esink->h);
182 memcpy (img_data, GST_BUFFER_DATA (buf), esink->w * esink->h * COLOR_DEPTH);
183 evas_object_image_pixels_dirty_set (esink->eo, 1);
184 evas_object_image_data_set(esink->eo, img_data);
186 gst_buffer_unref (buf);
188 evas_object_image_data_set (esink->eo, GST_BUFFER_DATA (buf));
189 evas_object_image_pixels_dirty_set (esink->eo, 1);
191 gst_buffer_unref(esink->oldbuf);
198 gst_evas_image_sink_init (GstEvasImageSink * esink, GstEvasImageSinkClass * gclass)
201 g_object_weak_ref (G_OBJECT (esink), gst_evas_image_sink_fini, NULL);
205 evas_image_sink_cb_del_eo (void *data, Evas *e, Evas_Object *obj, void *event_info)
207 GstEvasImageSink *esink = data;
212 gst_buffer_unref (esink->oldbuf);
213 esink->oldbuf = NULL;
216 ecore_pipe_del (esink->epipe);
221 evas_image_sink_get_size_from_caps (GstCaps *caps, int *w, int *h)
227 if (!caps || !w || !h) {
230 s = gst_caps_get_structure (caps, 0);
235 r = gst_structure_get_int (s, CAP_WIDTH, &width);
240 r = gst_structure_get_int (s, CAP_HEIGHT, &height);
251 is_zerocopy_supported (Evas *e)
253 Eina_List *engines, *l;
262 engines = evas_render_method_list ();
267 cur_id = evas_output_method_get (e);
269 EINA_LIST_FOREACH (engines, l, name) {
270 id = evas_render_method_lookup (name);
271 if (name && id == cur_id) {
272 if (!strcmp (name, GL_X11_ENGINE)) {
282 gst_evas_image_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
284 GstEvasImageSink *esink = GST_EVASIMAGESINK (object);
288 case PROP_EVAS_OBJECT:
289 eo = g_value_get_pointer (value);
290 if (is_evas_image_object (eo)) {
292 evas_object_event_callback_add (esink->eo, EVAS_CALLBACK_DEL, evas_image_sink_cb_del_eo, esink);
293 if (esink->w > 0 && esink->h >0) {
294 evas_object_image_size_set (esink->eo, esink->w, esink->h);
296 esink->gl_zerocopy = is_zerocopy_supported (evas_object_evas_get (eo));
297 if (esink->gl_zerocopy) {
298 evas_object_image_content_hint_set (esink->eo, EVAS_IMAGE_CONTENT_HINT_DYNAMIC);
299 GST_DEBUG("Enable gl zerocopy");
302 esink->epipe = ecore_pipe_add (evas_image_sink_cb_pipe, esink);
305 GST_ERROR ("Cannot set evas-object property: pipe create failed");
307 GST_DEBUG("property set, Evas Object is set");
308 evas_object_show(esink->eo);
309 esink->object_show = TRUE;
310 GST_INFO ("object show..");
312 GST_ERROR ("Cannot set evas-object property: value is not an evas image object");
316 case PROP_EVAS_OBJECT_SHOW:
317 esink->object_show = g_value_get_boolean (value);
318 if( !is_evas_image_object(esink->eo) ) {
319 GST_WARNING ("Cannot apply visible(show-object) property: cannot get an evas object\n");
322 if(!esink->object_show) {
323 evas_object_hide(esink->eo);
324 GST_INFO ("object hide..");
326 evas_object_show(esink->eo);
327 GST_INFO ("object show..");
332 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
338 gst_evas_image_sink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
340 GstEvasImageSink *esink = GST_EVASIMAGESINK (object);
343 case PROP_EVAS_OBJECT:
344 g_value_set_pointer (value, esink->eo);
346 case PROP_EVAS_OBJECT_SHOW:
347 g_value_set_boolean (value, esink->object_show);
350 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
356 gst_evas_image_sink_set_caps (GstBaseSink * base_sink, GstCaps * caps)
360 GstEvasImageSink *esink = GST_EVASIMAGESINK (base_sink);
362 r = evas_image_sink_get_size_from_caps (caps, &w, &h);
365 evas_object_image_size_set (esink->eo, w, h);
366 GST_DEBUG ("evas_object_image_size_set: w(%d) h(%d)", w, h);
375 gst_evas_image_sink_show_frame (GstVideoSink * video_sink, GstBuffer * buf)
377 GstEvasImageSink *esink = GST_EVASIMAGESINK (video_sink);
379 if (esink->epipe && esink->object_show) {
380 gst_buffer_ref (buf);
381 r = ecore_pipe_write (esink->epipe, &buf, sizeof (GstBuffer *));
382 if (r == EINA_FALSE) {
383 gst_buffer_unref (buf);
385 GST_DEBUG ("after ecore_pipe_write()");
391 evas_image_sink_init (GstPlugin * evasimagesink)
393 GST_DEBUG_CATEGORY_INIT (gst_evas_image_sink_debug, "evasimagesink", 0, "Evas image object based videosink");
395 return gst_element_register (evasimagesink, "evasimagesink", GST_RANK_NONE, GST_TYPE_EVASIMAGESINK);
399 #define PACKAGE "gstevasimagesink-plugin-package"
406 "Evas image object based videosink",
407 evas_image_sink_init,
410 "Samsung Electronics Co",
411 "http://www.samsung.com/"