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