Initialize Tizen 2.3
[framework/multimedia/gst-plugins-ext0.10.git] / wearable / xvimagesrc / src / gstxvimagesrc.c
1 /*
2  * xvimagesrc
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Hyunil Park <hyunil46.park@samsung.com>
7  *
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)
11  * any later version.
12  *
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.
17  *
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
21  *
22  */
23 /**
24 * SECTION:element-xvimagesrc
25 *
26 * xvimagesrc captures frame buffer which includes the application data along with video layer data
27 * from the XServer and pushes the data to the downstream element.
28 *
29 *
30 * <refsect2>
31 * <title>Example launch line</title>
32 * |[
33 * gst-launch xvimagesrc ! "video/x-raw-yuv, width=720, height=1280, framerate=(fraction)30/1, format=(fourcc)ST12" ! fakesink
34 * ]| captures the frame buffer from the XServer and send the buffers to a fakesink.
35 * </refsect2>
36 */
37
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
41
42 #include "gstxvimagesrc.h"
43
44 /* headers for drm */
45 #include <sys/stat.h>
46 #include <sys/ioctl.h>
47 #include <sys/time.h>
48 #include <sys/times.h>
49 #include <fcntl.h>
50 #include <unistd.h>
51 #include <X11/Xmd.h>
52 #include <X11/Xlibint.h>
53 #include <dri2.h>
54 #include <drm.h>
55 #ifndef ENABLE_QC_SPECIFIC
56 #include <exynos_drm.h>
57 #endif
58
59 GST_DEBUG_CATEGORY_STATIC (xvimagesrc_debug);
60 #define GST_CAT_DEFAULT xvimagesrc_debug
61
62
63 #define GST_XV_IMAGE_SRC_CAPS                    \
64   "video/x-raw-rgb, "                            \
65   "bpp = (int) 32, "                             \
66   "depth = (int) 24, "                           \
67   "endianness = (int) BIG_ENDIAN, "              \
68   "red_mask = (int) 0xFF000000, "                \
69   "green_mask = (int) 0x00FF0000, "              \
70   "blue_mask = (int) 0x0000FF00, "               \
71   "width  = (int)  [ 16, 4096 ], "               \
72   "height = (int)  [ 16, 4096 ], "               \
73   "framerate = (fraction) [0/1, 2147483647/1];"  \
74   "video/x-raw-yuv,"                             \
75   "format = (fourcc) { SN12, ST12, NV12 }, "                 \
76   "width = (int) [ 1, 4096 ], "                  \
77   "height = (int) [ 1, 4096 ], "                 \
78   "framerate = (fraction) [0/1, 2147483647/1];"  \
79
80 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
81   GST_PAD_SRC,
82   GST_PAD_ALWAYS,
83   GST_STATIC_CAPS(GST_XV_IMAGE_SRC_CAPS)
84 );
85
86 enum
87 {
88   PROP_0,
89   PROP_SECURE_MODE
90 };
91
92 enum
93 {
94   VIDEO_TYPE_VIDEO_WITH_UI,
95   VIDEO_TYPE_VIDEO_ONLY,
96 };
97
98 enum
99 {
100   SIGNAL_VIDEO_WITH_UI = 0,
101   SIGNAL_VIDEO_ONLY,
102   SIGNAL_LAST
103 };
104
105 #ifndef ENABLE_QC_SPECIFIC
106 #define GEM_NAME_MAX                10
107 #else
108 #define GEM_NAME_MAX                3
109 #endif
110
111 #define SCMN_CS_YUV420              1 /* Y:U:V 4:2:0 */
112 #define SCMN_CS_I420                SCMN_CS_YUV420 /* Y:U:V */
113 #define SCMN_CS_NV12                6
114 #define SCMN_CS_NV12_T64X32         11 /* 64x32 Tiled NV12 type */
115 #define SCMN_CS_UYVY                100
116 #define SCMN_CS_YUYV                101
117 #define SCMN_CS_YUY2                SCMN_CS_YUYV
118
119 /* max channel count *********************************************************/
120 #define SCMN_IMGB_MAX_PLANE         (4)
121
122 /* image buffer definition ***************************************************
123
124     +------------------------------------------+ ---
125     |                                          |  ^
126     |     a[], p[]                             |  |
127     |     +---------------------------+ ---    |  |
128     |     |                           |  ^     |  |
129     |     |<---------- w[] ---------->|  |     |  |
130     |     |                           |  |     |  |
131     |     |                           |        |
132     |     |                           |  h[]   |  e[]
133     |     |                           |        |
134     |     |                           |  |     |  |
135     |     |                           |  |     |  |
136     |     |                           |  v     |  |
137     |     +---------------------------+ ---    |  |
138     |                                          |  v
139     +------------------------------------------+ ---
140
141     |<----------------- s[] ------------------>|
142 */
143
144 typedef struct
145 {
146   /* width of each image plane */
147   int w[SCMN_IMGB_MAX_PLANE];
148   /* height of each image plane */
149   int h[SCMN_IMGB_MAX_PLANE];
150   /* stride of each image plane */
151   int s[SCMN_IMGB_MAX_PLANE];
152   /* elevation of each image plane */
153   int e[SCMN_IMGB_MAX_PLANE];
154   /* user space address of each image plane */
155   void *a[SCMN_IMGB_MAX_PLANE];
156   /* physical address of each image plane, if needs */
157   void *p[SCMN_IMGB_MAX_PLANE];
158   /* color space type of image */
159   int cs;
160   /* left postion, if needs */
161   int x;
162   /* top position, if needs */
163   int y;
164   /* to align memory */
165   int __dummy2;
166   /* arbitrary data */
167   int data[16];
168   /* dmabuf fd */
169   gint32 fd[SCMN_IMGB_MAX_PLANE];
170   /* flag for buffer share */
171   int buf_share_method;
172   /* Y plane size in case of ST12 */
173   int y_size;
174   /* UV plane size in case of ST12 */
175   int uv_size;
176
177   /* Tizen buffer object of each image plane */
178   void *bo[SCMN_IMGB_MAX_PLANE];
179
180   /* JPEG data */
181   void *jpeg_data;
182   /* JPEG size */
183   int jpeg_size;
184
185   /* tzmem buffer */
186   int tz_enable;
187 } SCMN_IMGB;
188 #ifndef ENABLE_QC_SPECIFIC
189 typedef struct
190 {
191   void  *address[GEM_NAME_MAX];
192   int buffer_size[GEM_NAME_MAX];
193   int name[GEM_NAME_MAX];
194   gint32 fd[GEM_NAME_MAX];
195   gint32 handle[GEM_NAME_MAX];
196 } GEM_MMAP;
197 #else
198 typedef struct
199 {
200   void  *virtual_add[GEM_NAME_MAX];
201   int gem_name[GEM_NAME_MAX];
202   gint32 ion_fd[GEM_NAME_MAX];
203   void *Ybo[GEM_NAME_MAX];
204 } MSM_GEM_MMAP;
205 #endif
206 typedef enum {
207  BUF_SHARE_METHOD_PADDR = 0,
208  BUF_SHARE_METHOD_FD
209 } buf_share_method_t;
210
211 typedef struct GstXvImageOutBuffer GstXvImageOutBuffer;
212
213 struct GstXvImageOutBuffer {
214   GstBuffer buffer;
215   int fd_name;
216   int YBuf;
217   GstXVImageSrc * xvimagesrc;
218 };
219
220
221
222 #define DEFAULT_USER_AGENT           "GStreamer xvimagesrc "
223
224 static guint gst_xv_image_src_signals[SIGNAL_LAST] = { 0 };
225
226 //#define COUNT_FRAMES
227 #ifdef COUNT_FRAMES
228 gchar old_time[10] = {0, };
229 #endif
230 static gboolean error_caught = FALSE;
231
232 #define HANDLE_OUTBUF_UNREF
233
234 #ifdef HANDLE_OUTBUF_UNREF
235 #define BUFFER_COND_WAIT_TIMEOUT            1000000
236 #define GST_TYPE_GST_XV_IMAGE_OUT_BUFFER               (gst_xv_image_out_buffer_get_type())
237 #define GST_IS_GST_XV_IMAGE_OUT_BUFFER(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_GST_XV_IMAGE_OUT_BUFFER))
238 static GstBufferClass *gst_xv_image_out_buffer_parent_class = NULL;
239 static void gst_xv_image_out_buffer_class_init(gpointer g_class, gpointer class_data);
240 static void gst_xv_image_out_buffer_finalize(GstXvImageOutBuffer *buffer);
241 static GstXvImageOutBuffer *gst_xv_image_out_buffer_new(GstXVImageSrc *src);
242 #endif
243 static GstStateChangeReturn gst_xv_image_src_change_state (GstElement * element, GstStateChange transition);
244 static void gst_xv_image_src_finalize (GObject * gobject);
245
246 static void gst_xv_image_src_set_property (GObject *object, guint prop_id, const GValue * value, GParamSpec * pspec);
247 static void gst_xv_image_src_get_property (GObject *object, guint prop_id, GValue * value, GParamSpec * pspec);
248 static GstFlowReturn gst_xv_image_src_create (GstPushSrc * psrc, GstBuffer ** outbuf);
249 static gboolean gst_xv_image_src_start (GstBaseSrc * bsrc);
250 static gboolean gst_xv_image_src_stop (GstBaseSrc * bsrc);
251 static gboolean gst_xv_image_src_get_size (GstBaseSrc * bsrc, guint64 * size);
252 static gboolean gst_xv_image_src_is_seekable (GstBaseSrc * bsrc);
253 static gboolean gst_xv_image_src_query (GstBaseSrc * bsrc, GstQuery * query);
254 static gboolean gst_xv_image_src_unlock (GstBaseSrc * bsrc);
255 static gboolean gst_xv_image_src_unlock_stop (GstBaseSrc * bsrc);
256 static gboolean gst_xv_image_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps);
257
258 static tbm_bufmgr bufmgr_get (Display *dpy, Pixmap pixmap);
259 static int port_get (GstXVImageSrc * src, unsigned int id);
260 static void pixmap_update (GstXVImageSrc * src,Display *dpy, tbm_bufmgr bufmgr, Pixmap pixmap,
261                int x, int y, int width, int height);
262 static Pixmap pixmap_create (GstXVImageSrc * src, Display *dpy, int width, int height);
263
264 static void* gst_xv_image_src_update_thread (void * asrc);
265 static gboolean xvimagesrc_thread_start(GstXVImageSrc *src);
266 static void drm_init(GstXVImageSrc *src);
267 static void drm_finalize(GstXVImageSrc *src);
268 #ifndef ENABLE_QC_SPECIFIC
269 static gint32 drm_convert_gem_to_fd(int * gemname_cnt, int drm_fd, unsigned int name,  void * data, void **virtual_address);
270 #endif
271 static void gst_xv_get_image_sleep(void *asrc, long duration);
272
273 static void
274 _do_init (GType type)
275 {
276   GST_DEBUG_CATEGORY_INIT (xvimagesrc_debug, "xvimagesrc", 0, "Xv image src");
277 }
278
279 GST_BOILERPLATE_FULL (GstXVImageSrc, gst_xv_image_src, GstPushSrc, GST_TYPE_PUSH_SRC, _do_init);
280
281 #ifdef HANDLE_OUTBUF_UNREF
282 static void gst_xv_image_out_buffer_class_init(gpointer g_class, gpointer class_data)
283 {
284   GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS(g_class);
285   gst_xv_image_out_buffer_parent_class = g_type_class_peek_parent(g_class);
286   mini_object_class->finalize = (GstMiniObjectFinalizeFunction)gst_xv_image_out_buffer_finalize;
287 }
288
289 static GType gst_xv_image_out_buffer_get_type(void)
290 {
291   static GType _gst_gst_xv_image_out_buffer_type;
292
293   if (G_UNLIKELY(_gst_gst_xv_image_out_buffer_type == 0)) {
294     static const GTypeInfo gst_xv_image_out_buffer_info = {
295       sizeof (GstBufferClass),
296       NULL,
297       NULL,
298       gst_xv_image_out_buffer_class_init,
299       NULL,
300       NULL,
301       sizeof (GstXvImageOutBuffer),
302       0,
303       NULL,
304       NULL
305     };
306     _gst_gst_xv_image_out_buffer_type = g_type_register_static(GST_TYPE_BUFFER,
307                                                         "GstOmxOutBuffer",
308                                                         &gst_xv_image_out_buffer_info, 0);
309   }
310   return _gst_gst_xv_image_out_buffer_type;
311 }
312 #ifdef DEBUG_BUFFER
313  int value[5] ={0};
314  static int value_count =0;
315 #endif
316
317 static GstStateChangeReturn
318 gst_xv_image_src_change_state (GstElement * element, GstStateChange transition)
319 {
320   GstXVImageSrc *src = GST_XV_IMAGE_SRC (element);
321
322   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
323   switch (transition) {
324   case GST_STATE_CHANGE_NULL_TO_READY:
325     break;
326   case GST_STATE_CHANGE_READY_TO_PAUSED:
327     break;
328   case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
329     src->pause_cond_var = FALSE;
330     g_cond_signal(src->pause_cond);
331     break;
332   case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
333     src->pause_cond_var = TRUE;
334     break;
335   case GST_STATE_CHANGE_PAUSED_TO_READY:
336     src->thread_return = TRUE;
337     g_cond_signal(src->pause_cond);
338     g_cond_signal(src->queue_cond);
339     break;
340   case GST_STATE_CHANGE_READY_TO_NULL:
341     break;
342   default :
343     break;
344   }
345   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
346   return result;
347 }
348
349
350 static void gst_xv_image_out_buffer_finalize(GstXvImageOutBuffer *buffer)
351 {
352   Atom atom_retbuf = 0;
353   g_mutex_lock (buffer->xvimagesrc->dpy_lock);
354   atom_retbuf = XInternAtom (buffer->xvimagesrc->dpy, "_USER_WM_PORT_ATTRIBUTE_RETURN_BUFFER", False);
355   XvSetPortAttribute (buffer->xvimagesrc->dpy, buffer->xvimagesrc->p, atom_retbuf, buffer->YBuf);  //data->YBuf is gemname, refer to drm_convert_gem_to_fd
356   g_mutex_unlock (buffer->xvimagesrc->dpy_lock);
357   g_cond_signal(buffer->xvimagesrc->buffer_cond);
358   GST_INFO(" xvimagesrc = %p, gem_name =%d, fd_name =%d", buffer->xvimagesrc, buffer->YBuf, buffer->fd_name);
359 #ifdef DEBUG_BUFFER
360  int i = 0;
361  for(i=0 ; i<5; i++){
362    if (value[i] == buffer->YBuf) {
363      value[i]=0;
364      GST_ERROR("value[%d]=%d", i, value[i]);
365    }
366  }
367 #endif
368   return;
369 }
370
371
372 static GstXvImageOutBuffer *gst_xv_image_out_buffer_new(GstXVImageSrc *src)
373 {
374   GstXvImageOutBuffer *newbuf = NULL;
375   GST_LOG("gst_omx_out_buffer_new");
376
377   newbuf = (GstXvImageOutBuffer *)gst_mini_object_new(GST_TYPE_GST_XV_IMAGE_OUT_BUFFER);
378   if(!newbuf)
379   {
380     GST_ERROR("gst_omx_out_buffer_new out of memory");
381     return NULL;
382   }
383   GST_LOG("creating buffer : %p", newbuf);
384   newbuf->xvimagesrc = gst_object_ref(GST_OBJECT(src));
385   newbuf->fd_name = 0;
386   newbuf->YBuf =0;
387   return newbuf;
388 }
389 #endif
390
391 static void
392 gst_xv_image_src_base_init (gpointer g_class)
393 {
394   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
395   gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&srctemplate));
396   gst_element_class_set_details_simple (element_class, "XServer Display FB video source",
397     "Source/video",
398     "Receive frame buffer data from XServer and passes to next element",
399     "");
400 }
401
402 static void
403 gst_xv_image_src_class_init (GstXVImageSrcClass * klass)
404 {
405   GObjectClass *gobject_class;
406   GstBaseSrcClass *gstbasesrc_class;
407   GstPushSrcClass *gstpushsrc_class;
408   GstElementClass *gstelement_class;
409   gobject_class = G_OBJECT_CLASS (klass);
410   gstelement_class = (GstElementClass *) klass;
411   gstbasesrc_class = (GstBaseSrcClass *) klass;
412   gstpushsrc_class = (GstPushSrcClass *) klass;
413   gobject_class->set_property = gst_xv_image_src_set_property;
414   gobject_class->get_property = gst_xv_image_src_get_property;
415   gobject_class->finalize = gst_xv_image_src_finalize;
416
417   gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_xv_image_src_start);
418   gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_xv_image_src_stop);
419   gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_xv_image_src_unlock);
420   gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_xv_image_src_unlock_stop);
421   gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_xv_image_src_get_size);
422   gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_xv_image_src_is_seekable);
423   gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_xv_image_src_query);
424   gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_xv_image_src_setcaps);
425   gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_xv_image_src_create);
426   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_xv_image_src_change_state);
427 #ifdef ENABLE_QC_SPECIFIC
428   g_object_class_install_property (gobject_class, PROP_SECURE_MODE,
429      g_param_spec_boolean ("secure-mode",
430      "secure mode session",
431      "HDCP enabled",
432      0, G_PARAM_READWRITE));
433 #endif
434   gst_xv_image_src_signals[SIGNAL_VIDEO_WITH_UI] =
435      g_signal_new ("video-with-ui", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
436      G_STRUCT_OFFSET (GstXVImageSrcClass, video_with_ui), NULL, NULL,
437      g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
438
439   gst_xv_image_src_signals[SIGNAL_VIDEO_ONLY] =
440      g_signal_new ("video-only", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
441      G_STRUCT_OFFSET (GstXVImageSrcClass, video_only), NULL, NULL,
442      g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
443
444 }
445
446 static gboolean gst_xv_image_src_get_frame_size(int fourcc, int width, int height, unsigned int *outsize)
447 {
448   switch (fourcc) {
449 /* case GST_MAKE_FOURCC('I','4','2','0'):       // V4L2_PIX_FMT_YUV420
450     *outsize = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
451     *outsize += 2 * ((GST_ROUND_UP_8 (width) / 2) * (GST_ROUND_UP_2 (height) / 2));
452     break;*/
453   case GST_MAKE_FOURCC('N','V','1','2'):        // V4L2_PIX_FMT_NV12 non-linear
454      GST_INFO("NV12");
455     *outsize = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
456     *outsize += (GST_ROUND_UP_4 (width) * height) / 2;
457     break;
458   case GST_MAKE_FOURCC('S','N','1','2'):        // V4L2_PIX_FMT_NV12 non-linear
459      GST_INFO("SN12");
460     *outsize = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
461     *outsize += (GST_ROUND_UP_4 (width) * height) / 2;
462     break;
463   case GST_MAKE_FOURCC('S','T','1','2'):        // V4L2_PIX_FMT_NV12 tiled non-linear
464      GST_INFO("ST12");
465     *outsize = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
466     *outsize += (GST_ROUND_UP_4 (width) * height) / 2;
467     break;
468   case GST_MAKE_FOURCC('R','G','B','4'):
469     /* jpeg size can't be calculated here. */
470     *outsize = width * height * 4;
471     break;
472   default:
473     /* unkown format!! */
474     *outsize = 0;
475     return FALSE;
476   }
477   return TRUE;
478 }
479
480 static gboolean
481 gst_xv_image_src_parse_caps (const GstCaps * caps, guint32 *fourcc,
482   gint * width, gint * height, gint * rate_numerator, gint * rate_denominator, unsigned int *framesize)
483 {
484   const GstStructure *structure;
485   GstPadLinkReturn ret = TRUE;
486   const GValue *framerate;
487   const char *media_type = NULL;
488   GST_DEBUG ("parsing caps");
489   if (gst_caps_get_size (caps) < 1) return FALSE;
490   GST_INFO("xvimagesrc src caps:%"GST_PTR_FORMAT, caps);
491   structure = gst_caps_get_structure (caps, 0);
492   ret = gst_structure_get_int (structure, "width", width);
493   if(!ret) {
494     GST_ERROR ("xvimagesrc width not specified in caps");
495     goto error;
496   }
497   ret = gst_structure_get_int (structure, "height", height);
498   if(!ret) {
499     GST_ERROR ("xvimagesrc height not specified in caps");
500     goto error;
501   }
502   media_type = gst_structure_get_name (structure);
503   if(media_type == NULL) {
504     GST_ERROR ("xvimagesrc media type not specified in caps");
505     goto error;
506   }
507   framerate = gst_structure_get_value (structure, "framerate");
508   if (framerate) {
509     *rate_numerator = gst_value_get_fraction_numerator (framerate);
510     *rate_denominator = gst_value_get_fraction_denominator (framerate);
511   } else {
512     GST_ERROR ("xvimagesrc frametype not specified in caps");
513     goto error;
514   }
515   if (g_strcmp0 (media_type, "video/x-raw-rgb") == 0) {
516     gst_xv_image_src_get_frame_size(FOURCC_RGB32, *width, *height, framesize);
517     *fourcc = FOURCC_RGB32;
518     GST_DEBUG ("Caps set to RGB32");
519   } else if(g_strcmp0 (media_type, "video/x-raw-yuv") == 0) {
520
521     GST_INFO ("media_type is video/x-raw-yuv");
522     guint32 format = FOURCC_SN12;
523     ret = gst_structure_get_fourcc (structure, "format", &format);
524     if (!ret) GST_DEBUG ("xvimagesrc format not specified in caps, SN12 selected as default");
525     ret = gst_xv_image_src_get_frame_size(format, *width, *height, framesize);
526     if(!ret) {
527       GST_ERROR ("xvimagesrc unsupported format type specified in caps");
528       goto error;
529     }
530     *fourcc = format;
531   }
532   return TRUE;
533 /* ERRORS */
534 error:
535     return FALSE;
536 }
537
538 static gboolean gst_xv_image_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps)
539 {
540   gboolean res = TRUE;
541   gint width, height, rate_denominator, rate_numerator;
542   GstXVImageSrc *src;
543   src = GST_XV_IMAGE_SRC (bsrc);
544   res = gst_xv_image_src_parse_caps (caps, &src->format_id, &width, &height,
545     &rate_numerator, &rate_denominator, &src->framesize);
546   if (res) {
547     /* looks ok here */
548     src->width = width;
549     src->height = height;
550     src->rate_numerator = rate_numerator;
551     src->rate_denominator = rate_denominator;
552     GST_DEBUG_OBJECT (src, "size %dx%d, %d/%d fps",
553       src->width, src->height,
554       src->rate_numerator, src->rate_denominator);
555     if(src->rate_numerator)
556     {
557       src->sleep_base_time = (long) (((int)(1000/src->rate_numerator))*1000);
558       src->sleep_limit_time = (long) (-1*src->sleep_base_time);
559     }
560   }
561   xvimagesrc_thread_start(src);
562   return res;
563 }
564 static void
565 gst_xv_image_src_reset (GstXVImageSrc * src)
566 {
567 }
568
569 static void
570 gst_xv_image_src_init (GstXVImageSrc * src, GstXVImageSrcClass * g_class)
571 {
572   src->format_id = 0;
573   src->running_time = GST_CLOCK_TIME_NONE;
574   src->frame_duration = GST_CLOCK_TIME_NONE;
575   src->virtual = NULL;
576   src->bo = NULL;
577   src->dri2_buffers = NULL;
578   src->queue_lock = g_mutex_new ();
579   src->queue = g_queue_new ();
580   src->queue_cond = g_cond_new ();
581   src->cond_lock = g_mutex_new ();
582   src->buffer_cond = g_cond_new ();
583   src->buffer_cond_lock = g_mutex_new ();
584   src->pause_cond = g_cond_new ();
585   src->pause_cond_lock = g_mutex_new ();
586   src->dpy_lock = g_mutex_new ();
587   src->pause_cond_var = FALSE;
588   src->drm_fd = -1;
589   src->current_data_type = VIDEO_TYPE_VIDEO_WITH_UI;
590   src->new_data_type = VIDEO_TYPE_VIDEO_WITH_UI;
591   src->get_image_overtime = 0;
592   src->get_image_overtime_cnt = 0;
593   src->gemname_cnt = 0;
594   src->tz_enable = 0;
595   src->sleep_base_time = 0;
596   src->sleep_limit_time = 0;
597   drm_init(src);
598   gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
599 }
600
601 static void
602 gst_xv_image_src_finalize (GObject * gobject)
603 {
604   GstXVImageSrc *src = GST_XV_IMAGE_SRC (gobject);
605   GST_DEBUG_OBJECT (src, "finalize");
606   g_mutex_free (src->queue_lock);
607   drm_finalize(src);
608   G_OBJECT_CLASS (parent_class)->finalize (gobject);
609 }
610 static void drm_init(GstXVImageSrc *src)
611 {
612   Display *dpy;
613   int eventBase, errorBase;
614   int dri2Major, dri2Minor;
615   char *driverName, *deviceName;
616   struct drm_auth auth_arg = {0};
617
618   src->drm_fd = -1;
619   dpy = XOpenDisplay(0);
620
621   /* DRI2 */
622   if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) {
623     GST_ERROR("DRI2QueryExtension !!");
624     return;
625   }
626   if (!DRI2QueryVersion(dpy, &dri2Major, &dri2Minor)) {
627    GST_ERROR("DRI2QueryVersion !!");
628    return;
629   }
630   if (!DRI2Connect(dpy, RootWindow(dpy, DefaultScreen(dpy)), &driverName, &deviceName)) {
631     GST_ERROR("DRI2Connect !!");
632     return;
633   }
634   GST_INFO("Open drm device : %s", deviceName);
635
636   /* get the drm_fd though opening the deviceName */
637   src->drm_fd = open(deviceName, O_RDWR);
638   if (src->drm_fd < 0) {
639     GST_ERROR("cannot open drm device (%s)", deviceName);
640     return;
641   }
642
643   /* get magic from drm to authentication */
644   if (ioctl(src->drm_fd, DRM_IOCTL_GET_MAGIC, &auth_arg)) {
645     GST_ERROR("cannot get drm auth magic");
646     close(src->drm_fd);
647     src->drm_fd = -1;
648     return;
649   }
650   if (!DRI2Authenticate(dpy, RootWindow(dpy, DefaultScreen(dpy)), auth_arg.magic)) {
651     GST_ERROR("cannot get drm authentication from X");
652     close(src->drm_fd);
653     src->drm_fd = -1;
654     return;
655   }
656 }
657 static void drm_finalize(GstXVImageSrc *src)
658 {
659   if (src->drm_fd >= 0) {
660     close(src->drm_fd);
661     src->drm_fd = -1;
662   }
663 }
664 #ifndef ENABLE_QC_SPECIFIC
665 static gint32 drm_convert_gem_to_fd(int *gemname_cnt, int drm_fd, unsigned int name, void  *data, void **virtual_address)
666 {
667   g_return_val_if_fail((data != NULL),0);
668   int count=0;
669   gint32 fd = 0;
670   count = *gemname_cnt;
671   GST_DEBUG("gamname_cnt = %d", count);
672   GST_DEBUG("name = %u", name);
673
674
675   GEM_MMAP *xv_gem_mmap = NULL;
676   xv_gem_mmap = (GEM_MMAP *) data;
677   if(count >=GEM_NAME_MAX)
678     goto PASS;
679
680   if (count < GEM_NAME_MAX ) {
681     int i =0;
682     for ( i =0 ; i < GEM_NAME_MAX ; i++) {
683       if (name == xv_gem_mmap->name[i])
684         goto PASS;
685     }
686
687     struct drm_prime_handle prime;
688     struct drm_gem_open gem_open;
689     struct drm_exynos_gem_mmap gem_mmap; //for virtual address
690
691     memset (&gem_open, 0, sizeof (struct drm_gem_open));
692     gem_open.name = name;
693     if (ioctl(drm_fd, DRM_IOCTL_GEM_OPEN, &gem_open)) {
694       GST_ERROR("Gem Open failed");
695       return 0;
696     }
697     memset (&prime, 0, sizeof (struct drm_prime_handle));
698     prime.handle = gem_open.handle;
699     prime.flags = DRM_CLOEXEC;
700     /*get gem_open handle*/
701     xv_gem_mmap->handle[count] = gem_open.handle;
702     GST_DEBUG("gem_open.handle =%d, xv_gem_mmap->handle[count]=%d", gem_open.handle, xv_gem_mmap->handle[count]);
703     /*get virtual address */
704     /*set name*/
705     xv_gem_mmap->name[count] = name;
706     memset (&gem_mmap, 0, sizeof (struct drm_exynos_gem_mmap));
707     gem_mmap.handle = prime.handle;
708     gem_mmap.size = gem_open.size;
709     /*set size*/
710     xv_gem_mmap->buffer_size[count] = gem_mmap.size;
711     if (drmIoctl(drm_fd, DRM_IOCTL_EXYNOS_GEM_MMAP, &gem_mmap) !=0) {
712       GST_ERROR("Gem mmap failed [handle %d, size %d]", gem_mmap.handle, gem_mmap.size);
713       return 0;
714     }
715     /*set virtual address*/
716     xv_gem_mmap->address[count] = (void *)(gem_mmap.mapped);
717     GST_DEBUG ("%d - Virtual address[%d] = %p size=%d ", name, count, xv_gem_mmap->address[count],  xv_gem_mmap->buffer_size[count] );
718
719     /*get fd*/
720     if (ioctl(drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime) < 0) {
721       GST_ERROR("Gem Handle to Fd failed");
722       return 0;
723     }
724     xv_gem_mmap->fd[count] = prime.fd;
725     GST_DEBUG("fd = %d", xv_gem_mmap->fd[count]);
726   }
727
728   if (count < GEM_NAME_MAX) {
729     count ++;
730     *gemname_cnt = count;
731   }
732
733 PASS:
734
735   if (name == xv_gem_mmap->name[0]) {
736     *virtual_address = xv_gem_mmap->address[0];
737     fd = xv_gem_mmap->fd[0];
738   } else if (name == xv_gem_mmap->name[1]) {
739     *virtual_address = xv_gem_mmap->address[1];
740      fd = xv_gem_mmap->fd[1];
741   } else if (name == xv_gem_mmap->name[2]) {
742     *virtual_address = xv_gem_mmap->address[2];
743      fd = xv_gem_mmap->fd[2];
744   } else if ( name == xv_gem_mmap->name[3]) {
745     *virtual_address = xv_gem_mmap->address[3];
746      fd = xv_gem_mmap->fd[3];
747   } else if (name == xv_gem_mmap->name[4]) {
748     *virtual_address = xv_gem_mmap->address[4];
749      fd = xv_gem_mmap->fd[4];
750   } else if ( name == xv_gem_mmap->name[5]) {
751     *virtual_address = xv_gem_mmap->address[5];
752      fd = xv_gem_mmap->fd[5];
753   } else if (name == xv_gem_mmap->name[6]) {
754     *virtual_address = xv_gem_mmap->address[6];
755      fd = xv_gem_mmap->fd[6];
756   } else if (name == xv_gem_mmap->name[7]) {
757     *virtual_address = xv_gem_mmap->address[7];
758      fd = xv_gem_mmap->fd[7];
759   } else if ( name == xv_gem_mmap->name[8]) {
760     *virtual_address = xv_gem_mmap->address[8];
761      fd = xv_gem_mmap->fd[8];
762   } else if (name == xv_gem_mmap->name[9]) {
763     *virtual_address = xv_gem_mmap->address[9];
764      fd = xv_gem_mmap->fd[9];
765   }
766
767   GST_DEBUG("virtual_address = %p  fd = %d", *virtual_address, fd);
768   return fd;
769 }
770 #else
771 static gint32 msm_convert_gem_to_fd(GstXVImageSrc *src, int *gemname_cnt, unsigned int gem_name, void *data)
772 {
773   g_return_val_if_fail((data != NULL),0);
774   int count=0;
775   gint32 fd = 0;
776   tbm_bo_handle bo_handle;
777   count = *gemname_cnt;
778   GST_DEBUG("gamname_cnt = %d", count);
779   GST_DEBUG ("tbm_bo_import %d", gem_name);
780   MSM_GEM_MMAP *xv_gem_mmap = NULL;
781   xv_gem_mmap = (MSM_GEM_MMAP *) data;
782   if(count >=GEM_NAME_MAX)
783     goto PASS;
784
785   if (count < GEM_NAME_MAX ) {
786     int i =0;
787     for ( i =0 ; i < GEM_NAME_MAX ; i++) {
788       if (gem_name == xv_gem_mmap->gem_name[i])
789         goto PASS;
790     }
791     xv_gem_mmap->Ybo[count] = tbm_bo_import(src->bufmgr, gem_name);
792     if (!xv_gem_mmap->Ybo[count]) {
793       GST_ERROR ("[Error] : cannot import bo (key:%d)", gem_name);
794       return 0;
795     }
796     bo_handle = tbm_bo_get_handle (xv_gem_mmap->Ybo[count], TBM_DEVICE_2D);
797     if(!bo_handle.s32)
798     {
799       GST_ERROR ("[Error] : cannot get Ion FD");
800       return 0;
801     }
802     xv_gem_mmap->ion_fd[count] = bo_handle.s32;
803     src->framesize = tbm_bo_size(xv_gem_mmap->Ybo[count]);
804 #if 0 //Its no more required with Meta mode Encoder, Need to remove after meta mode verification
805     tbm_bo_handle temp_virtual;
806     temp_virtual = tbm_bo_get_handle (xv_gem_mmap->Ybo[count], TBM_DEVICE_CPU);
807     xv_gem_mmap->virtual_add[count] = temp_virtual.ptr;
808
809     if(!xv_gem_mmap->virtual_add[count])
810     {
811       GST_ERROR ("[Error] : cannot map virtual address");
812       return 0;
813     }
814 #endif
815     /*set name*/
816     xv_gem_mmap->gem_name[count] = gem_name;
817   }
818
819   if (count < GEM_NAME_MAX) {
820     count ++;
821     *gemname_cnt = count;
822   }
823 PASS:
824   if (gem_name == xv_gem_mmap->gem_name[0]) {
825     //*virtual_address = xv_gem_mmap->virtual_add[0];
826     fd = xv_gem_mmap->ion_fd[0];
827   } else if (gem_name == xv_gem_mmap->gem_name[1]) {
828     //*virtual_address = xv_gem_mmap->virtual_add[1];
829      fd = xv_gem_mmap->ion_fd[1];
830   } else if (gem_name == xv_gem_mmap->gem_name[2]) {
831     //*virtual_address = xv_gem_mmap->virtual_add[2];
832      fd = xv_gem_mmap->ion_fd[2];
833   }
834   GST_DEBUG("ion_fd = %d", fd);
835   return fd;
836 }
837 #endif
838 static void
839 gst_xv_image_src_set_property (GObject * object, guint prop_id,
840     const GValue * value, GParamSpec * pspec)
841 {
842   GstXVImageSrc *src = GST_XV_IMAGE_SRC (object);
843   GST_INFO ("set property function %x", src);
844   switch (prop_id) {
845 #ifdef ENABLE_QC_SPECIFIC
846     case PROP_SECURE_MODE:
847       src->is_secured_mode = g_value_get_boolean (value);
848       GST_DEBUG("is_secured_mode %d", src->is_secured_mode);
849     break;
850 #endif
851     default:
852       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
853     break;
854   }
855   return;
856 }
857
858 static void
859 gst_xv_image_src_get_property (GObject * object, guint prop_id,
860     GValue * value, GParamSpec * pspec)
861 {
862   GstXVImageSrc *src = GST_XV_IMAGE_SRC (object);
863   GST_INFO ("get property function %x", src);
864   switch (prop_id) {
865 #ifdef ENABLE_QC_SPECIFIC
866     case PROP_SECURE_MODE:
867       g_value_set_boolean (value, src->is_secured_mode);
868     break;
869 #endif
870     default:
871       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
872     break;
873   }
874 }
875
876 static inline GstClockTime xvimagesrc_clock (GstXVImageSrc *src)
877 {
878   struct timeval tv;
879   gettimeofday (&tv, NULL);
880   if(!src->base_time) {
881     src->base_time = GST_TIMEVAL_TO_TIME(tv);
882   }
883   return (GstClockTime)(GST_TIMEVAL_TO_TIME(tv) - src->base_time);
884 }
885
886 static gboolean gst_xv_image_src_get_timeinfo(GstXVImageSrc *src, GstBuffer *buffer)
887 {
888   int fps_nu = 0;
889   int fps_de = 0;
890   GstClockTime timestamp = GST_CLOCK_TIME_NONE;
891   GstClockTime duration = GST_CLOCK_TIME_NONE;
892   GstClock *clock;
893   if (!src || !buffer) {
894     GST_WARNING("Invalid pointer [handle:%p, buffer:%p]", src, buffer);
895     return FALSE;
896   }
897   clock = gst_element_get_clock (GST_ELEMENT (src));
898   if (clock) {
899     timestamp = gst_clock_get_time (clock);
900     timestamp -= gst_element_get_base_time (GST_ELEMENT (src));
901     gst_object_unref (clock);
902   } else {
903     /* not an error not to have a clock */
904     timestamp = GST_CLOCK_TIME_NONE;
905   }
906
907   //timestamp = xvimagesrc_clock(src);
908   /* if we have a framerate adjust timestamp for frame latency */
909   if ((int)((float)src->rate_numerator / (float)src->rate_denominator) <= 0) {
910     /*if fps is zero, auto fps mode*/
911     fps_nu = 0;
912     fps_de = 1;
913   } else {
914     fps_nu = 1;
915     fps_de = (int)((float)src->rate_numerator / (float)src->rate_denominator);
916   }
917   if (fps_nu > 0 && fps_de > 0) {
918     GstClockTime latency;
919     latency = gst_util_uint64_scale_int(GST_SECOND, fps_nu, fps_de);
920     duration = latency;
921   }
922   GST_BUFFER_TIMESTAMP(buffer) = timestamp;
923   GST_BUFFER_DURATION(buffer) = duration;
924   return TRUE;
925 }
926 #ifdef COUNT_FRAMES
927 static  int fps = 0;
928
929 static gchar *get_current_system_time()
930 {
931         gchar target[10]={0,};
932         time_t t;
933         struct tm tm;
934
935         t = time(NULL);
936         tzset();
937         /*localtimer_r : available since libc 5.2.5*/
938         if(localtime_r(&t, &tm) == NULL) {
939                 return NULL;
940         }
941         snprintf(target, sizeof(target), "%02i:%02i:%02i", tm.tm_hour, tm.tm_min, tm.tm_sec);
942         return g_strdup(target);
943 }
944 #endif
945 static void gst_xv_get_image_sleep(void *asrc, long duration)
946 {
947     GST_INFO("end_time duration=%d", duration);
948     if (duration < 0) return;
949     GstXVImageSrc *src = (GstXVImageSrc *)asrc;
950     g_return_if_fail(src != NULL);
951     long sleep_time = 0;
952     sleep_time = src->sleep_base_time - duration;
953     if (sleep_time < 0) {
954         src->get_image_overtime_cnt ++;
955         src->get_image_overtime += sleep_time;
956         if (src->get_image_overtime_cnt > 2)
957           src->get_image_overtime = 0;
958         if (src->get_image_overtime <= src->sleep_limit_time)
959           src->get_image_overtime = 0;
960     } else if (sleep_time > 0) {
961        src->get_image_overtime_cnt = 0;
962         sleep_time = sleep_time + src->get_image_overtime;
963         src->get_image_overtime = (sleep_time < 0) ? sleep_time : 0;
964         if (sleep_time >0) {
965            GST_INFO("end_time : sleep_time = %d", sleep_time);
966           usleep(sleep_time);
967         }
968     }
969 }
970 static GstFlowReturn
971 gst_xv_image_src_create (GstPushSrc * psrc, GstBuffer ** buffer)
972 {
973   GST_INFO("gst_xv_image_src_create");
974   GstXVImageSrc *src;
975   GstXvImageOutBuffer *outbuf = NULL;
976   src = GST_XV_IMAGE_SRC (psrc);
977   g_mutex_lock (src->queue_lock);
978   if(g_queue_is_empty (src->queue)) {
979     GST_INFO("g_queue_is_empty");
980     g_mutex_unlock (src->queue_lock);
981     GST_INFO("g_cond_wait");
982     g_cond_wait(src->queue_cond, src->cond_lock);
983     if(src->pause_cond_var) return GST_FLOW_WRONG_STATE;
984     g_mutex_lock (src->queue_lock);
985     outbuf = (GstXvImageOutBuffer *)g_queue_pop_head(src->queue);
986     GST_INFO("g_queue_pop_head");
987     g_mutex_unlock (src->queue_lock);
988   }
989   else {
990     GstXvImageOutBuffer *tempbuf = NULL;
991     if((tempbuf = (GstXvImageOutBuffer*)g_queue_pop_head(src->queue)) != NULL)
992     {
993       outbuf = tempbuf;    // To reduce latency, skipping the old frames and submitting only latest frames
994       g_mutex_unlock (src->queue_lock);
995     }
996     GST_INFO("g_queue_pop_head end");
997   }
998   if(outbuf == NULL) return GST_FLOW_ERROR;
999   GST_INFO("gem_name=%d, fd_name=%d, Time stamp of the buffer is %"GST_TIME_FORMAT, outbuf->YBuf, outbuf->fd_name, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(outbuf)));
1000   *buffer = GST_BUFFER_CAST(outbuf);
1001 #ifdef COUNT_FRAMES
1002     gchar *current_time = NULL;
1003     current_time =      get_current_system_time();
1004     if (strncmp(current_time, old_time, 10) == 0) {
1005         fps ++;
1006         strncpy(old_time, current_time, 10);
1007     } else {
1008        g_printf("xvimagesrc %s - fps : %d\n", old_time, fps);
1009        fps = 1;
1010         strncpy(old_time, current_time, 10);
1011     }
1012 #endif
1013   GST_INFO("return ok");
1014   return GST_FLOW_OK;
1015 }
1016
1017 static gboolean xvimagesrc_thread_start(GstXVImageSrc *src)
1018 {
1019   GError *error;
1020   if(!src->updates_thread) src->updates_thread = g_thread_create ((GThreadFunc) gst_xv_image_src_update_thread, src, TRUE, &error);
1021   else GST_LOG_OBJECT (src, "The thread function already running");
1022   return TRUE;
1023 }
1024
1025 static gboolean
1026 gst_xv_image_src_start (GstBaseSrc * bsrc)
1027 {
1028   GstXVImageSrc *src = GST_XV_IMAGE_SRC (bsrc);
1029   if(src->format_id) xvimagesrc_thread_start(src);
1030   return TRUE;
1031 }
1032
1033 gboolean signal_emit_func(void *asrc)
1034 {
1035     GstXVImageSrc *src = (GstXVImageSrc *)asrc;
1036     if (src->current_data_type == VIDEO_TYPE_VIDEO_ONLY) {
1037       g_signal_emit (src, gst_xv_image_src_signals[SIGNAL_VIDEO_ONLY] , 0, NULL);
1038    } else if (src->current_data_type == VIDEO_TYPE_VIDEO_WITH_UI) {
1039      g_signal_emit (src, gst_xv_image_src_signals[SIGNAL_VIDEO_WITH_UI] , 0, NULL);
1040    }
1041     return FALSE;
1042 }
1043
1044 static int
1045 gst_xvimagesrc_handle_xerror (Display * display, XErrorEvent * xevent)
1046 {
1047   char error_msg[1024];
1048
1049   XGetErrorText (display, xevent->error_code, error_msg, 1024);
1050   GST_DEBUG ("XError. error: %s", error_msg);
1051   error_caught = TRUE;
1052   return 0;
1053 }
1054
1055 //static gboolean first_frame=TRUE;
1056 static int framecount=0;
1057 static void* gst_xv_image_src_update_thread (void * asrc)
1058 {
1059   GstXVImageSrc *src = (GstXVImageSrc *)asrc;
1060   Atom atom_data_type = 0;
1061   Atom atom_secure = 0, atom_capture=0, atom_display=0;
1062   Atom atom_fps = 0;
1063   g_return_val_if_fail((src != NULL),NULL);
1064   int i=0;
1065 #ifdef ENABLE_QC_SPECIFIC
1066   Atom atom_rotate=0;
1067   MSM_GEM_MMAP *xv_gem_mmap = NULL;
1068   xv_gem_mmap = (MSM_GEM_MMAP *)malloc(sizeof(MSM_GEM_MMAP));
1069   g_return_val_if_fail((xv_gem_mmap != NULL),NULL);
1070
1071   memset(xv_gem_mmap, 0, sizeof(MSM_GEM_MMAP));
1072 #else
1073   struct drm_gem_close gem_close;
1074   GEM_MMAP *xv_gem_mmap = NULL;
1075   xv_gem_mmap = (GEM_MMAP *)malloc(sizeof(GEM_MMAP));
1076   g_return_val_if_fail((xv_gem_mmap != NULL),NULL);
1077
1078   memset(xv_gem_mmap, 0, sizeof(GEM_MMAP));
1079 #endif
1080   GST_LOG_OBJECT (src, "The thread function start");
1081   {
1082     int damage_err_base = 0;
1083     Atom atom_format = 0;
1084     src->dpy = XOpenDisplay (NULL);
1085     src->p = port_get (src, src->format_id);
1086     if (src->p < 0) goto finish;
1087     /*src->width and src->height is set by caps info */
1088     GST_DEBUG (" width and height of caps : %dx%d ", src->width, src->height);
1089     if (src->width == 0 || src->height == 0) goto finish;
1090     GST_DEBUG ("gst_xv_image_src_update_thread pixmap_create !!");
1091     src->pixmap = pixmap_create (src, src->dpy, src->width, src->height);
1092     GST_DEBUG ("gst_xv_image_src_update_thread pixmap_create !!");
1093     src->gc = XCreateGC (src->dpy, src->pixmap, 0, 0);
1094     GST_DEBUG ("gst_xv_image_src_update_thread XCreateGC !!");
1095     src->bufmgr = bufmgr_get (src->dpy, src->pixmap);
1096     if (!src->bufmgr) goto finish;
1097     GST_DEBUG ("gst_xv_image_src_update_thread bufmgr_get !!");
1098     if (!XDamageQueryExtension(src->dpy, &src->damage_base, &damage_err_base)) goto finish;
1099     GST_DEBUG ("gst_xv_image_src_update_thread XDamageQueryExtension !!");
1100     src->damage = XDamageCreate (src->dpy, src->pixmap, XDamageReportNonEmpty);
1101     atom_format = XInternAtom (src->dpy, "_USER_WM_PORT_ATTRIBUTE_FORMAT", False);
1102     atom_capture = XInternAtom (src->dpy, "_USER_WM_PORT_ATTRIBUTE_CAPTURE", False);
1103     atom_display = XInternAtom (src->dpy, "_USER_WM_PORT_ATTRIBUTE_DISPLAY", False);
1104 #ifdef ENABLE_QC_SPECIFIC
1105     atom_rotate = XInternAtom (src->dpy, "_USER_WM_PORT_ATTRIBUTE_ROTATE_OFF", False);
1106 #endif
1107     /*get data type*/
1108     atom_data_type = XInternAtom (src->dpy, "_USER_WM_PORT_ATTRIBUTE_DATA_TYPE", False);
1109     /* _USER_WM_PORT_ATTRIBUTE_STREAM_OFF is removed */
1110     //src->atom_stream_off = XInternAtom (src->dpy, "_USER_WM_PORT_ATTRIBUTE_STREAM_OFF", False);
1111     XvSetPortAttribute (src->dpy, src->p, atom_format, src->format_id);
1112     XvSetPortAttribute (src->dpy, src->p, atom_capture, 2);
1113     XvSetPortAttribute (src->dpy, src->p, atom_display, 1);
1114 #ifdef ENABLE_QC_SPECIFIC
1115     XvSetPortAttribute (src->dpy, src->p, atom_rotate, 0);
1116 #endif
1117
1118 #ifdef ENABLE_QC_SPECIFIC
1119     /* To be enabled for secure mode when msm is delivered */
1120     if(src->is_secured_mode) {
1121       atom_secure = XInternAtom (src->dpy, "_USER_WM_PORT_ATTRIBUTE_SECURE", False);
1122       XvSetPortAttribute (src->dpy, src->p, atom_secure, 1);
1123     }
1124 #endif
1125     XvSelectPortNotify (src->dpy, src->p, 1);
1126     XvGetPortAttribute (src->dpy, src->p, atom_data_type, &(src->new_data_type));
1127   }
1128
1129   struct timeval start_time, end_time;
1130   long duration;
1131   long starttime, endtime;
1132   GTimeVal timeout;
1133   XEvent ev;
1134   int eventcount = 0;
1135   void *virtual_address = NULL;
1136   int (*handler) (Display *, XErrorEvent *);
1137   GstXvImageOutBuffer *outbuf = NULL;
1138
1139   while(!src->thread_return) {
1140     if(src->pause_cond_var == TRUE) {
1141       g_cond_wait(src->pause_cond,src->pause_cond_lock);
1142     }
1143
1144     duration = 0;
1145     starttime =0;
1146     endtime = 0;
1147     start_time.tv_sec = 0;
1148     start_time.tv_usec = 0;
1149     end_time.tv_sec      = 0;
1150     end_time.tv_usec = 0;
1151     gettimeofday(&start_time, NULL);
1152
1153     eventcount = 0;
1154     virtual_address = NULL;
1155     duration = 0;
1156     outbuf = NULL;
1157     g_mutex_lock (src->dpy_lock);
1158     XSync(src->dpy, 0);
1159     GST_INFO ("gst_xv_image_src_update_thread XSync@@ !!");
1160     g_mutex_unlock (src->dpy_lock);
1161     error_caught = FALSE;
1162     GST_DEBUG ("gst_xv_image_src_update_thread XSetErrorHandler in !!");
1163     handler = XSetErrorHandler (gst_xvimagesrc_handle_xerror);
1164     GST_INFO ("gst_xv_image_src_update_thread XSetErrorHandler !!");
1165     GST_INFO ("gst_xv_image_src_update_thread XvPutStill in !!");
1166     g_mutex_lock (src->dpy_lock);
1167     XvPutStill (src->dpy, src->p, src->pixmap, src->gc, 0, 0, src->width, src->height, 0, 0, src->width, src->height);
1168     GST_INFO ("gst_xv_image_src_update_thread XvPutStill !!");
1169     XSync (src->dpy, 0);
1170     g_mutex_unlock (src->dpy_lock);
1171     if (error_caught) {
1172       GST_ERROR("gst_xv_image_src_update_thread error_caught is TRUE, X is out of buffers");
1173             error_caught = FALSE;
1174             XSetErrorHandler(handler);
1175       g_get_current_time(&timeout);
1176       g_time_val_add(&timeout, BUFFER_COND_WAIT_TIMEOUT);
1177       if(!g_cond_timed_wait(src->buffer_cond, src->buffer_cond_lock, &timeout)) {
1178               GST_ERROR("skip wating");
1179       } else {
1180           GST_ERROR("Signal received");
1181       }
1182       continue;
1183     }
1184     /*reset error handler*/
1185     error_caught = FALSE;
1186     XSetErrorHandler(handler);
1187
1188     GST_INFO ("gst_xv_image_src_update_thread XSync !!");
1189 next_event:
1190     g_mutex_lock (src->dpy_lock);
1191     GST_INFO("XNextEvent in");
1192     XNextEvent (src->dpy, &ev); /* wating for x event */
1193     GST_INFO("XNextEvent out");
1194     g_mutex_unlock (src->dpy_lock);
1195     GST_INFO ("gst_xv_image_src_update_thread XNextEvent !!");
1196     if (ev.type == (src->damage_base + XDamageNotify)) {
1197       XDamageNotifyEvent *damage_ev = (XDamageNotifyEvent *)&ev;
1198       GST_INFO ("gst_xv_image_src_update_thread XDamageNotifyEvent");
1199       g_mutex_lock (src->dpy_lock);
1200       if (damage_ev->drawable == src->pixmap) {
1201         pixmap_update (src, src->dpy, src->bufmgr, src->pixmap,
1202         damage_ev->area.x,
1203         damage_ev->area.y,
1204         damage_ev->area.width,
1205         damage_ev->area.height);
1206               GST_INFO("gst_xv_image_src_update_thread pixmap_update");
1207       }
1208       XDamageSubtract (src->dpy, src->damage, None, None );
1209       g_mutex_unlock (src->dpy_lock);
1210       GST_INFO ("gst_xv_image_src_update_thread XDamageSubtract");
1211     }
1212     else if (ev.type == (src->evt_base + XvPortNotify)) {
1213       XvPortNotifyEvent *notify_ev = (XvPortNotifyEvent*)&ev;
1214 #ifndef ENABLE_QC_SPECIFIC
1215       if (notify_ev->attribute == atom_secure) {
1216           GST_WARNING ("secure attr changed : %s \n", ((int)notify_ev->value)?"Secure":"Normal");
1217            src->tz_enable = (int)notify_ev->value;
1218            GST_ERROR("src->tz_enable = %d", src->tz_enable);
1219       }
1220       else 
1221 #endif
1222       if (notify_ev->attribute == atom_data_type) {
1223         /* got a port notify, data_type */
1224         src->new_data_type = (int)notify_ev->value;
1225         if (src->current_data_type != src->new_data_type) {
1226           src->current_data_type = src->new_data_type;
1227           GST_WARNING("current_data_type : %s \n", (src->current_data_type)?"Video":"UI+Video");
1228           g_timeout_add(1, signal_emit_func, src);
1229         }
1230       }
1231       goto next_event;
1232     }
1233
1234     if(!src->virtual) continue;
1235     if(src->format_id == FOURCC_RGB32) {
1236       outbuf = (GstXvImageOutBuffer*)gst_buffer_new_and_alloc (src->framesize);
1237       gst_buffer_set_caps (GST_BUFFER_CAST(outbuf), GST_PAD_CAPS (GST_BASE_SRC_PAD (src)));
1238       memcpy(GST_BUFFER_DATA (outbuf), src->virtual, src->framesize);
1239     } else if ((src->format_id == FOURCC_SN12) || (src->format_id == FOURCC_NV12)) {
1240       XV_DATA_PTR data = (XV_DATA_PTR)src->virtual;
1241       int error = XV_VALIDATE_DATA (data);
1242       outbuf = gst_xv_image_out_buffer_new(src);
1243       if(!outbuf)
1244       {
1245         GST_ERROR("Out of memory");
1246         continue;
1247       }
1248       gst_buffer_set_caps (GST_BUFFER_CAST(outbuf), GST_PAD_CAPS (GST_BASE_SRC_PAD (src)));
1249       if (error == XV_HEADER_ERROR)
1250         GST_ERROR ("XV_HEADER_ERROR\n");
1251       else if (error == XV_VERSION_MISMATCH)
1252         GST_ERROR ("XV_VERSION_MISMATCH\n");
1253       else
1254       {
1255         SCMN_IMGB *psimgb = NULL;
1256         psimgb = (SCMN_IMGB *)malloc(sizeof(SCMN_IMGB));
1257         if (psimgb == NULL) {
1258           GST_ERROR_OBJECT(src, "failed to alloc SCMN_IMGB");
1259           return NULL;
1260         }
1261         memset(psimgb, 0x00, sizeof(SCMN_IMGB));
1262         if (data->BufType == XV_BUF_TYPE_LEGACY) {
1263           psimgb->p[0] = (void *)data->YBuf;
1264           psimgb->p[1] = (void *)data->CbBuf;
1265           psimgb->buf_share_method = BUF_SHARE_METHOD_PADDR;
1266           psimgb->a[0] = NULL;
1267           psimgb->a[1] = NULL;
1268         } else if (data->BufType == XV_BUF_TYPE_DMABUF)
1269         {
1270 #ifdef ENABLE_QC_SPECIFIC
1271           psimgb->fd[0] = msm_convert_gem_to_fd(src, &src->gemname_cnt, data->YBuf, xv_gem_mmap);
1272           GST_DEBUG("YBuf gem=%d to fd[0]=%d", data->YBuf, psimgb->fd[0]);
1273                           psimgb->buf_share_method = 1;//BUF_SHARE_METHOD_FD;
1274 #else
1275           psimgb->fd[0] = drm_convert_gem_to_fd(&src->gemname_cnt, src->drm_fd, (void *)data->YBuf, xv_gem_mmap, &virtual_address);
1276           if(!virtual_address) continue;
1277           psimgb->a[0] = virtual_address;
1278           GST_DEBUG("YBuf gem to fd[0]=%d virtual_address = %p", psimgb->fd[0], psimgb->a[0]);
1279           psimgb->fd[1] = drm_convert_gem_to_fd(&src->gemname_cnt, src->drm_fd, (void *)data->CbBuf, xv_gem_mmap, &virtual_address);
1280           if(!virtual_address) continue;
1281           psimgb->a[1] = virtual_address;
1282           GST_DEBUG("CbBuf gem to fd[1]=%d  virtual_address = %p", psimgb->fd[1], psimgb->a[1]);
1283           psimgb->buf_share_method = BUF_SHARE_METHOD_FD;
1284           psimgb->w[1] = src->width;
1285           psimgb->h[1] = src->height >> 1;
1286           psimgb->s[1] = GST_ROUND_UP_16(psimgb->w[1]);
1287           psimgb->e[1] = GST_ROUND_UP_16(psimgb->h[1]);
1288           psimgb->cs   = SCMN_CS_NV12;
1289           psimgb->tz_enable = 0;
1290 #endif
1291         }
1292         psimgb->w[0] = src->width;
1293         psimgb->h[0] = src->height;
1294         psimgb->s[0] = GST_ROUND_UP_16(psimgb->w[0]);
1295         psimgb->e[0] = GST_ROUND_UP_16(psimgb->h[0]);
1296         outbuf->fd_name = psimgb->fd[0];
1297         GST_BUFFER_MALLOCDATA(outbuf) = (unsigned char*)psimgb;
1298         GST_BUFFER_DATA(outbuf) = src->virtual;
1299         outbuf->YBuf = data->YBuf;
1300             outbuf->fd_name = psimgb->fd[0];
1301 #ifdef DEBUG_BUFFER
1302         for ( i=0; i<5 ; i++) {
1303          if(value[value_count] == outbuf->YBuf ) {
1304             GST_ERROR("ERROR: value[%d](%d)==YBUf(%d)", value_count, value[value_count], outbuf->YBuf);
1305          }
1306         }
1307         value[value_count] = outbuf->YBuf ;
1308             GST_ERROR("value[%d]=%d", value_count, value[value_count]);
1309             if( value_count < 4){
1310               value_count ++;
1311             } else {
1312               value_count = 0;
1313             }
1314 #endif
1315       }
1316     }
1317   if(!outbuf) continue;
1318         GST_BUFFER_SIZE (outbuf) = src->framesize;
1319     gst_xv_image_src_get_timeinfo(src, GST_BUFFER_CAST(outbuf));
1320     src->running_time = GST_BUFFER_TIMESTAMP(outbuf);
1321     src->frame_duration = GST_BUFFER_DURATION(outbuf);
1322     //first_frame = FALSE;
1323     g_mutex_lock (src->queue_lock);
1324     g_queue_push_tail(src->queue, outbuf);
1325     GST_INFO("g_queue_push_tail");
1326     g_mutex_unlock (src->queue_lock);
1327     g_cond_signal(src->queue_cond);
1328     GST_INFO("g_cond_signal");
1329
1330     update_done:
1331       if (src->virtual) tbm_bo_unmap(src->bo);
1332       src->virtual = NULL;
1333       GST_INFO("g_cond_signal");
1334       if (src->bo) tbm_bo_unref(src->bo);
1335       src->bo = NULL;
1336       if (src->dri2_buffers) free(src->dri2_buffers);
1337       src->dri2_buffers = NULL;
1338       gettimeofday(&end_time, NULL);
1339       starttime = start_time.tv_usec;
1340       endtime =  end_time.tv_usec;
1341       GST_INFO("star_time: %d, end_time:%d", starttime, endtime);
1342       if (endtime > starttime) {
1343         GST_INFO("end_time > start_time");
1344         duration = endtime - starttime;
1345          } else {
1346          GST_INFO("end_time.tv_usec < start_time.tv_usec");
1347          endtime=endtime+1000000;
1348          GST_INFO("end_time =%d", endtime);
1349         duration = endtime -starttime;
1350       }
1351       GST_INFO("end_time duration = %d", duration);
1352       if (src->sleep_base_time > duration)
1353         gst_xv_get_image_sleep (src, duration);
1354       GST_INFO("gst_xv_image_src_update_thread cleanup !!");
1355   }
1356 #ifndef ENABLE_QC_SPECIFIC
1357   for ( i=0 ; i < GEM_NAME_MAX ; i++) {
1358     /*gem munmap*/
1359     if (xv_gem_mmap->address[i]) {
1360       if (-1 == munmap(xv_gem_mmap->address[i],xv_gem_mmap->buffer_size[i])) {
1361         GST_ERROR ("munmap failed");
1362          return NULL;
1363       }
1364     }
1365     if (xv_gem_mmap->handle[i]) {
1366         gem_close.handle = xv_gem_mmap->handle[i];
1367         if (ioctl(src->drm_fd, DRM_IOCTL_GEM_CLOSE, &gem_close)) {
1368           GST_ERROR("Gem Close failed");
1369         }
1370     }
1371     if (xv_gem_mmap->fd[i]) {
1372       close(xv_gem_mmap->fd[i]);
1373     }
1374   }
1375   if (xv_gem_mmap) {
1376     free(xv_gem_mmap);
1377     xv_gem_mmap = NULL;
1378   }
1379 #else
1380   for ( i=0 ; i < GEM_NAME_MAX ; i++) {
1381     if (xv_gem_mmap->Ybo[i]) {
1382       tbm_bo_unref(xv_gem_mmap->Ybo[i]);
1383       xv_gem_mmap->Ybo[i] = NULL;
1384     }
1385   }
1386   if (xv_gem_mmap) {
1387     free(xv_gem_mmap);
1388     xv_gem_mmap = NULL;
1389   }
1390 #endif
1391   GST_LOG_OBJECT (src, "The thread function cleanup");
1392
1393   XvStopVideo(src->dpy, src->p, src->pixmap);
1394
1395   if (src->bufmgr) {
1396     tbm_bufmgr_deinit (src->bufmgr);
1397     src->bufmgr = NULL;
1398   }
1399   if (src->p > 0) {
1400     XvUngrabPort (src->dpy, src->p, 0);
1401     src->p = 0;
1402   }
1403   if (src->gc) {
1404     XFreeGC (src->dpy, src->gc);
1405     src->gc = NULL;
1406   }
1407   if (src->pixmap > 0) {
1408     XFreePixmap (src->dpy, src->pixmap);
1409     src->pixmap = 0;
1410   }
1411   if (src->dpy) {
1412     XCloseDisplay (src->dpy);
1413     src->dpy = NULL;
1414   }
1415   GST_LOG_OBJECT (src, "The thread function stop");
1416   return NULL;
1417 finish:
1418   GST_LOG_OBJECT (src, "The thread function Error cleanup");
1419
1420   XvStopVideo(src->dpy, src->p, src->pixmap);
1421
1422   if (src->bufmgr) tbm_bufmgr_deinit (src->bufmgr);
1423   src->bufmgr = NULL;
1424   if (src->p > 0) XvUngrabPort (src->dpy, src->p, 0);
1425   src->p = 0;
1426   if (src->gc) XFreeGC (src->dpy, src->gc);
1427   src->gc = NULL;
1428   if (src->pixmap > 0) XFreePixmap (src->dpy, src->pixmap);
1429   src->pixmap = 0;
1430   if (src->dpy) XCloseDisplay (src->dpy);
1431   src->dpy = NULL;
1432   GST_LOG_OBJECT (src, "The thread function Error stop");
1433   return NULL;
1434 }
1435
1436 static tbm_bufmgr bufmgr_get (Display *dpy, Pixmap pixmap)
1437 {
1438   int screen;
1439   int drm_fd;
1440   tbm_bufmgr bufmgr;
1441   int eventBase, errorBase;
1442   int dri2Major, dri2Minor;
1443   char *driverName, *deviceName;
1444   drm_magic_t magic;
1445
1446   screen = DefaultScreen(dpy);
1447   if (!DRI2QueryExtension (dpy, &eventBase, &errorBase)) {
1448     GST_ERROR ("!!Error : DRI2QueryExtension !!");
1449     return NULL;
1450   }
1451   if (!DRI2QueryVersion (dpy, &dri2Major, &dri2Minor)) {
1452     GST_ERROR ("!!Error : DRI2QueryVersion !!");
1453     return NULL;
1454   }
1455   if (!DRI2Connect (dpy, RootWindow(dpy, screen), &driverName, &deviceName)) {
1456     GST_ERROR ( "!!Error : DRI2Connect !!");
1457     if(driverName) Xfree(driverName);
1458     if(deviceName) Xfree(deviceName);
1459     return NULL;
1460   }
1461   if(driverName) Xfree(driverName);
1462   if(!deviceName) return NULL;
1463
1464   GST_DEBUG("Open drm device : %s", deviceName);
1465   // get the drm_fd though opening the deviceName
1466   drm_fd = open (deviceName, O_RDWR);
1467   if (drm_fd < 0) {
1468     GST_ERROR ("!!Error : cannot open drm device (%s)", deviceName);
1469     if(deviceName) Xfree(deviceName);
1470     return NULL;
1471   }
1472   if(deviceName) Xfree(deviceName);
1473   /* get the drm magic */
1474   drmGetMagic(drm_fd, &magic);
1475   fprintf(stderr, ">>> drm magic=%d \n", magic);
1476   if (!DRI2Authenticate(dpy, RootWindow(dpy, screen), magic))
1477   {
1478     fprintf(stderr, "!!Error : DRI2Authenticate !!\n");
1479     close (drm_fd);
1480     return NULL;
1481   }
1482   // drm slp buffer manager init
1483   bufmgr = tbm_bufmgr_init (drm_fd);
1484   if (!bufmgr) {
1485     GST_ERROR ("!!Error : fail to init buffer manager ");
1486     close (drm_fd);
1487     return NULL;
1488   }
1489   DRI2CreateDrawable (dpy, pixmap);
1490   return bufmgr;
1491 }
1492
1493 static int port_get (GstXVImageSrc * src, unsigned int id)
1494 {
1495   unsigned int ver, rev, req_base, err_base;
1496   unsigned int adaptors;
1497   XvAdaptorInfo *ai = NULL;
1498   XvAttribute *at = NULL;
1499   XvImageFormatValues *fo = NULL;
1500   int attributes, formats;
1501   int i, j, p;
1502
1503   if (XvQueryExtension (src->dpy, &ver, &rev, &req_base, &src->evt_base, &err_base) != Success) return -1;
1504   if (XvQueryAdaptors (src->dpy, DefaultRootWindow (src->dpy), &adaptors, &ai) != Success) return -1;
1505   if (!ai) return -1;
1506   for (i = 0; i < adaptors; i++) {
1507     int support_format = False;
1508     if (!(ai[i].type & XvInputMask) || !(ai[i].type & XvStillMask)) continue;
1509     GST_LOG ("===========================================");
1510     GST_LOG (" name:        %s"
1511                 " first port:  %ld"
1512                 " ports:       %ld",
1513                 ai[i].name,
1514                 ai[i].base_id,
1515                 ai[i].num_ports);
1516     p = ai[i].base_id;
1517     GST_LOG (" attribute list:");
1518     at = XvQueryPortAttributes (src->dpy, p, &attributes);
1519     for (j = 0; j < attributes; j++) GST_LOG ("\t-  name: %s\n"
1520                     "\t\t  flags:     %s%s\n"
1521                     "\t\t  min_value:  %i\n"
1522                     "\t\t  max_value:  %i\n",
1523                     at[j].name,
1524                     (at[j].flags & XvGettable) ? " get" : "",
1525                     (at[j].flags & XvSettable) ? " set" : "",
1526                     at[j].min_value, at[j].max_value);
1527     if (at) XFree (at);
1528     GST_LOG (" image format list:");
1529     fo = XvListImageFormats (src->dpy, p, &formats);
1530     for (j = 0; j < formats; j++) {
1531       GST_LOG ("\t-  0x%x (%4.4s) %s", fo[j].id, (char *)&fo[j].id, (fo[j].format == XvPacked) ? "packed" : "planar");
1532       if (fo[j].id == (int)id) support_format = True;
1533     }
1534     if (fo) XFree (fo);
1535     if (!support_format) continue;
1536     for (; p < ai[i].base_id + ai[i].num_ports; p++) {
1537       if (XvGrabPort (src->dpy, p, 0) == Success) {
1538         GST_LOG ("========================================");
1539         GST_DEBUG ("XvGrabPort success : %d", p);
1540         GST_LOG ("========================================");
1541         XvFreeAdaptorInfo (ai);
1542         return p;
1543       }
1544     }
1545   }
1546   XvFreeAdaptorInfo (ai);
1547   return -1;
1548 }
1549
1550 static void pixmap_update (GstXVImageSrc * src, Display *dpy, tbm_bufmgr bufmgr, Pixmap pixmap,
1551                int x, int y, int width, int height)
1552 {
1553   unsigned int attachments[1];
1554   int dri2_count, dri2_out_count;
1555   int dri2_width, dri2_height, dri2_stride;
1556   int opt;
1557   tbm_bo_handle temp_virtual;
1558   attachments[0] = DRI2BufferFrontLeft;
1559   dri2_count = 1;
1560   GST_DEBUG ("DRI2GetBuffers");
1561   src->dri2_buffers = DRI2GetBuffers (dpy, pixmap, &dri2_width, &dri2_height, attachments, dri2_count, &dri2_out_count);
1562   if (!src->dri2_buffers) {
1563     GST_ERROR ("[Error] : fail to get buffers");
1564     goto update_done;
1565   }
1566   if (!src->dri2_buffers[0].name) {
1567     GST_ERROR ("[Error] : a handle of the dri2 buffer is null  ");
1568     goto update_done;
1569   }
1570   GST_DEBUG ("tbm_bo_import");
1571   src->bo = tbm_bo_import(bufmgr, src->dri2_buffers[0].name);
1572   if (!src->bo) {
1573     GST_ERROR ("[Error] : cannot import bo (key:%d)", src->dri2_buffers[0].name);
1574     goto update_done;
1575   }
1576   dri2_stride = src->dri2_buffers[0].pitch;
1577   opt = TBM_OPTION_READ|TBM_OPTION_WRITE;
1578   GST_DEBUG ("tbm_bo_map");
1579   temp_virtual = tbm_bo_map (src->bo, TBM_DEVICE_CPU, opt);
1580   src->virtual = temp_virtual.ptr;
1581   if (!src->virtual) {
1582     GST_ERROR ("[Error] : fail to map ");
1583     goto update_done;
1584   }
1585   return;
1586 update_done:
1587   if (src->virtual) tbm_bo_unmap(src->bo);
1588   src->virtual = NULL;
1589   if (src->bo) tbm_bo_unref(src->bo);
1590   src->bo = NULL;
1591   if (src->dri2_buffers) free(src->dri2_buffers);
1592   src->dri2_buffers = NULL;
1593   return;
1594 }
1595
1596 static Pixmap pixmap_create (GstXVImageSrc * src, Display *dpy, int width, int height)
1597 {
1598   src->pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy), width, height, DefaultDepth(dpy, DefaultScreen(dpy)));
1599   src->gc = XCreateGC (dpy, src->pixmap, 0, 0);
1600   XSetForeground (dpy, src->gc, 0xFFFF0000);
1601   XFillRectangle (dpy, src->pixmap, src->gc, 0, 0, width, height);
1602   XSync(dpy, 0);
1603   XFreeGC (dpy, src->gc);
1604   return src->pixmap;
1605 }
1606
1607 static gboolean
1608 gst_xv_image_src_stop (GstBaseSrc * bsrc)
1609 {
1610   GstXVImageSrc *src = GST_XV_IMAGE_SRC (bsrc);
1611   GST_DEBUG_OBJECT (src, "stop()");
1612
1613   if(src->updates_thread) {
1614     src->thread_return = TRUE;
1615     g_thread_join ( src->updates_thread);
1616     src->updates_thread = NULL;
1617   }
1618   GST_DEBUG_OBJECT (src, "stop end ");
1619   return TRUE;
1620 }
1621
1622 /* Interrupt a blocking request. */
1623 static gboolean
1624 gst_xv_image_src_unlock (GstBaseSrc * bsrc)
1625 {
1626   GstXVImageSrc *src = GST_XV_IMAGE_SRC (bsrc);
1627   GST_DEBUG_OBJECT (src, "unlock()");
1628   g_cond_signal(src->queue_cond);
1629   return TRUE;
1630 }
1631
1632 /* Interrupt interrupt. */
1633 static gboolean
1634 gst_xv_image_src_unlock_stop (GstBaseSrc * bsrc)
1635 {
1636   GstXVImageSrc *src = GST_XV_IMAGE_SRC (bsrc);
1637   GST_DEBUG_OBJECT (src, "unlock_stop()");
1638   return TRUE;
1639 }
1640
1641 static gboolean
1642 gst_xv_image_src_get_size (GstBaseSrc * bsrc, guint64 * size)
1643 {
1644   GstXVImageSrc *src = GST_XV_IMAGE_SRC (bsrc);
1645   GST_INFO ("Get size %x", src);
1646   return FALSE;
1647 }
1648
1649 static gboolean
1650 gst_xv_image_src_is_seekable (GstBaseSrc * bsrc)
1651 {
1652   GstXVImageSrc *src = GST_XV_IMAGE_SRC (bsrc);
1653   GST_INFO ("Is seekable %x", src);
1654   return FALSE;
1655 }
1656
1657 static gboolean
1658 gst_xv_image_src_query (GstBaseSrc * bsrc, GstQuery * query)
1659 {
1660   GstXVImageSrc *src = GST_XV_IMAGE_SRC (bsrc);
1661   gboolean ret;
1662   GST_INFO ("src query %x", src);
1663   switch (GST_QUERY_TYPE (query)) {
1664     case GST_QUERY_URI:
1665       ret = TRUE;
1666     break;
1667     default:
1668       ret = FALSE;
1669     break;
1670   }
1671
1672   if (!ret)
1673     ret = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
1674
1675   return ret;
1676 }
1677
1678 static gboolean
1679 plugin_init (GstPlugin * plugin)
1680 {
1681   GST_DEBUG_CATEGORY_INIT (xvimagesrc_debug, "xvimagesrc", 0, "XServer display FB video capture Source");
1682   return gst_element_register (plugin, "xvimagesrc", GST_RANK_PRIMARY, GST_TYPE_XV_IMAGE_SRC);
1683 }
1684
1685 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1686   GST_VERSION_MINOR,
1687   "xvimage",
1688   "XServer display video src",
1689   plugin_init, VERSION, "LGPL", "Samsung Electronics Co", "http://www.samsung.com")