tizencamerasrc: Remove duplicated log
[platform/upstream/gst-plugins-tizen.git] / tizencamerasrc / src / gsttizencamerasrc.c
1 /*
2  * gsttizencamerasrc.c
3  *
4  * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jeongmo Yang <jm80.yang@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 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <inttypes.h>
29 #include <string.h>
30 #include <gst/gst.h>
31 #include <gst/gstutils.h>
32 #include <gst/video/video-info.h>
33 #include <glib-object.h>
34 #include <unistd.h>
35 #include <sys/time.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39
40 #include "gsttizencamerasrc.h"
41 #include "gsttizencamerasrccontrol.h"
42 #include "gsttizencamerasrccolorbalance.h"
43
44
45 /******************************************************************************
46  * Definitions
47  *******************************************************************************/
48 GST_DEBUG_CATEGORY (tizencamerasrc_debug);
49 #define GST_CAT_DEFAULT tizencamerasrc_debug
50
51
52 #define CAMERASRC_ALIGN(addr,size)              (((addr)+((size)-1))&(~((size)-1)))
53
54 #if !defined (CLEAR)
55   #define CLEAR(x)                              memset(&(x), 0, sizeof(x))
56 #endif
57
58 /* Local definitions */
59 #define _DEFAULT_FPS                            15
60 #define _DEFAULT_HIGH_SPEED_FPS                 0
61 #define _DEFAULT_FPS_AUTO                       FALSE
62 #define _DEFAULT_EXTRA_PREVIEW                  FALSE
63 #define _DEFAULT_PIX_FORMAT                     CAMERA_PIXEL_FORMAT_NV12
64 #define _DEFAULT_PIX_FORMAT_NAME                "NV12"
65 #define _DEFAULT_CAPTURE_FORMAT_NAME            "JPEG"
66 #define _DEFAULT_CAMERA_ID                      0
67
68 #define _CAMERA_ID_MIN                          0
69 #define _CAMERA_ID_MAX                          1
70
71 #define _DEFAULT_CAP_QUALITY                    95
72 #define _DEFAULT_CAP_WIDTH                      640
73 #define _DEFAULT_CAP_HEIGHT                     480
74 #define _DEFAULT_CAP_COUNT                      1
75 #define _DEFAULT_CAP_INTERVAL                   0
76 #define _DEFAULT_CAP_PROVIDE_EXIF               FALSE
77 #define _DEFAULT_BITRATE                        (1024 * 1024)   /* bps, 1 Mbps */
78 #define _DEFAULT_GOP_INTERVAL                   1000            /* msec, 1 second */
79 #define _DEFAULT_LIVE_BUFFER_MAX                32
80 #define _DEFAULT_LIVE_BUFFER_MAX_RAW            16
81 #define _BUFFER_WAIT_TIMEOUT                    1000000         /* usec */
82 #define _DEFAULT_EMPTY_BUFFER_TIMEOUT           5000            /* msec */
83 #define _DEFAULT_BUFFER_QUARK                   0
84
85 enum {
86   CAMERA_COLOR_BALANCE_BRIGHTNESS = 0,
87   CAMERA_COLOR_BALANCE_CONTRAST,
88   CAMERA_COLOR_BALANCE_WHITE_BALANCE,
89   CAMERA_COLOR_BALANCE_COLOR_TONE,
90   CAMERA_COLOR_BALANCE_SATURATION,
91   CAMERA_COLOR_BALANCE_HUE,
92   CAMERA_COLOR_BALANCE_SHARPNESS,
93   CAMERA_COLOR_BALANCE_NUM
94 };
95
96 enum {
97   CAMERA_CONTROL_PTZ_TYPE = 0,
98   CAMERA_CONTROL_PAN,
99   CAMERA_CONTROL_TILT,
100   CAMERA_CONTROL_NUM
101 };
102
103 #define SAFE_FREE_GQUEUE(gqueue) \
104   if (gqueue) { \
105     g_queue_free(gqueue); \
106     gqueue = NULL; \
107   }
108
109 #define MAKE_FOURCC_FROM_STRING(string) ((guint32)(string[0] | (string[1] << 8) | (string[2] << 16) | (string[3] << 24)))
110
111
112 /* Enumerations */
113 enum {
114   /*signal*/
115   SIGNAL_STILL_CAPTURE,
116   SIGNAL_VIDEO_STREAM_CB,
117   SIGNAL_EXTRA_PREVIEW_STREAM_CB,
118
119   /*SIGNAL_REGISTER_TROUBLE,*/
120   LAST_SIGNAL
121 };
122
123 enum {
124   ARG_0,
125   /* device */
126   ARG_CAMERA_ID,
127   ARG_DEVICE_NAME,
128   ARG_DEVICE_BUS,
129   ARG_DEVICE_PORT,
130   ARG_HAL_NAME,
131
132   /* preview */
133   ARG_VFLIP,
134   ARG_HFLIP,
135   ARG_HIGH_SPEED_FPS,
136   ARG_AUTO_FPS,
137   ARG_EXTRA_PREVIEW,
138   ARG_LIVE_BUFFER_MAX,
139   ARG_LIVE_BUFFER_MAX_RAW,
140   ARG_EMPTY_BUFFER_TIMEOUT,
141   ARG_BUFFER_QUARK,
142
143   /* capture */
144   ARG_CAPTURE_FOURCC,
145   ARG_CAPTURE_WIDTH,
146   ARG_CAPTURE_HEIGHT,
147   ARG_CAPTURE_INTERVAL,
148   ARG_CAPTURE_COUNT,
149   ARG_CAPTURE_QUALITY,
150   ARG_CAPTURE_PROVIDE_EXIF,
151
152   /* video */
153   ARG_VIDEO_WIDTH,
154   ARG_VIDEO_HEIGHT,
155   ARG_VIDEO_FPS,
156   ARG_RECORDING_HINT,
157
158   /* encoded format */
159   ARG_BITRATE,
160   ARG_GOP_INTERVAL,
161
162   ARG_NUM
163 };
164
165 enum {
166   VIDEO_IN_MODE_NONE,
167   VIDEO_IN_MODE_PREVIEW,
168   VIDEO_IN_MODE_VIDEO,
169   VIDEO_IN_MODE_CAPTURE,
170 };
171
172 typedef struct _GstTizenCameraSrcCommand {
173   const char *label;
174   uint64_t cmd;
175 } GstTizenCameraSrcCommand;
176
177
178 static void gst_tizencamerasrc_uri_handler_init (gpointer g_iface, gpointer iface_data);
179
180 static guint gst_tizencamerasrc_signals[LAST_SIGNAL] = { 0 };
181
182 /* Element template variables */
183 static GstStaticPadTemplate src_factory =
184   GST_STATIC_PAD_TEMPLATE("src",
185                           GST_PAD_SRC,
186                           GST_PAD_ALWAYS,
187                           GST_STATIC_CAPS("video/x-raw,"
188                                           "format = (string) { NV12, SN12, NV21, SN21, I420, S420, YV12, YUY2, SUYV, UYVY, SYVY }, "
189                                           "width = (int) [ 1, 8192 ], "
190                                           "height = (int) [ 1, 8192 ]; "
191                                           "video/x-h264,"
192                                           "stream-format = (string) { byte-stream, avc }, "
193                                           "alignment = (string) au; "
194                                           "video/x-vp8,"
195                                           "width = (int) [ 1, 8192 ], "
196                                           "height = (int) [ 1, 8192 ]; "
197                                           "video/x-vp9,"
198                                           "width = (int) [ 1, 8192 ], "
199                                           "height = (int) [ 1, 8192 ]; "
200                                           "image/jpeg,"
201                                           "width = (int) [ 1, 8192 ], "
202                                           "height = (int) [ 1, 8192 ]; "
203                                           "video/x-jpeg,"
204                                           "width = (int) [ 1, 8192 ], "
205                                           "height = (int) [ 1, 8192 ]; "
206                                           ));
207
208 /* Local static functions */
209 static void gst_tizencamerasrc_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
210 static void gst_tizencamerasrc_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
211 static gboolean gst_tizencamerasrc_negotiate(GstBaseSrc *basesrc);
212 static gboolean gst_tizencamerasrc_src_start(GstBaseSrc *src);
213 static gboolean gst_tizencamerasrc_src_stop(GstBaseSrc *src);
214 static gboolean gst_tizencamerasrc_start(GstTizenCameraSrc *camerasrc);
215 static GstFlowReturn gst_tizencamerasrc_src_create(GstPushSrc *src, GstBuffer **buffer);
216 static GstFlowReturn gst_tizencamerasrc_read_preview(GstTizenCameraSrc *camerasrc, GstBuffer **buffer);
217 static GstStateChangeReturn gst_tizencamerasrc_change_state(GstElement *element, GstStateChange transition);
218 static GstCaps *gst_tizencamerasrc_get_caps(GstBaseSrc *src, GstCaps *filter);
219 static gboolean gst_tizencamerasrc_set_caps(GstBaseSrc *src, GstCaps *caps);
220 static gboolean gst_tizencamerasrc_get_caps_info(GstTizenCameraSrc *camerasrc, GstCaps *caps, guint *size);
221 static gboolean gst_tizencamerasrc_fill_ctrl_list(GstTizenCameraSrc *camerasrc);
222 static gboolean gst_tizencamerasrc_empty_ctrl_list(GstTizenCameraSrc *camerasrc);
223 static void gst_tizencamerasrc_finalize(GObject *object);
224 static gboolean gst_tizencamerasrc_get_timeinfo(GstTizenCameraSrc *camerasrc, GstBuffer *buffer);
225 static gboolean gst_tizencamerasrc_capture_start(GstTizenCameraSrc *camerasrc);
226 static gboolean gst_tizencamerasrc_capture_stop(GstTizenCameraSrc *camerasrc);
227 static void gst_tizencamerasrc_error_handler(GstTizenCameraSrc *camerasrc, int ret);
228 static GstBuffer *gst_tizencamerasrc_buffer_new(GstTizenCameraSrc *camerasrc, camera_buffer_s *buffer,
229   camera_metadata_s *meta, GstTizenCameraBufferType type, BufferControl *control, int stream_id);
230 static void gst_tizencamerasrc_buffer_finalize(GstTizenCameraBuffer *buffer);
231 static void gst_tizencamerasrc_set_video_format(GstTizenCameraSrc *camerasrc);
232 static void gst_tizencamerasrc_set_capture_format(GstTizenCameraSrc *camerasrc);
233
234 /* callbacks */
235 static int __camera_preview_frame_cb(camera_buffer_s *buffer, camera_metadata_s *meta, void *user_data);
236 static int __camera_extra_preview_frame_cb(camera_buffer_s *buffer, camera_metadata_s *meta, int stream_id, void *user_data);
237 static int __camera_video_frame_cb(camera_buffer_s *buffer, camera_metadata_s *meta, void *user_data);
238 static int __camera_hal_message_callback(camera_message_s *message, void *user_data);
239
240 /* Util functions */
241 static gboolean __gst_tizencamerasrc_get_frame_size(int fourcc, int width, int height, unsigned int *outsize);
242 static gboolean __gst_tizencamerasrc_get_raw_pixel_info(int fourcc, camera_pixel_format_e *pix_format);
243 static gboolean __gst_tizencamerasrc_get_tbm_format(int pix_format, guint32 *tbm_format);
244 static GstCaps *__gst_tizencamerasrc_get_caps_from_buffer(camera_buffer_s *buffer);
245 static void __gst_tizencamerasrc_post_message_int(GstTizenCameraSrc *camerasrc, const char *msg_name, const char *field_name, int value);
246 static int __gst_tizencamerasrc_release_buffer(GstTizenCameraSrc *camerasrc, GstTizenCameraBufferType type, int index, int stream_id);
247
248 GST_IMPLEMENT_TIZENCAMERASRC_COLOR_BALANCE_METHODS(GstTizenCameraSrc, gst_tizencamera_src);
249 GST_IMPLEMENT_TIZENCAMERASRC_CONTROL_METHODS(GstTizenCameraSrc, gst_tizencamera_src);
250
251
252 /******************************************************************************
253  * Implementations
254  *******************************************************************************/
255 static GstBuffer *gst_tizencamerasrc_buffer_new(GstTizenCameraSrc *camerasrc, camera_buffer_s *buffer,
256   camera_metadata_s *meta, GstTizenCameraBufferType type, BufferControl *control, int stream_id)
257 {
258   int ret = CAMERA_ERROR_NONE;
259   gsize maxsize = 0;
260   gboolean is_tbm_used = FALSE;
261   gboolean is_delta_frame = FALSE;
262
263   GstTizenCameraBuffer *new_buffer = NULL;
264   GstMemory *memory = NULL;
265   GstStructure *structure_metadata = NULL;
266
267   if (!camerasrc || !buffer) {
268     GST_ERROR("NULL pointer %p %p", camerasrc, buffer);
269     return NULL;
270   }
271
272   if (!buffer->total_size) {
273     GST_ERROR_OBJECT(camerasrc, "requested buffer size is incorrect");
274     return NULL;
275   }
276
277   if (buffer->num_bos > 0)
278     is_tbm_used = TRUE;
279
280   GST_DEBUG_OBJECT(camerasrc, "index[%d] is_tbm[%d], is_delta[%d]",
281     buffer->index, is_tbm_used, is_delta_frame);
282
283   /* allocate new buffer */
284   new_buffer = g_new0(GstTizenCameraBuffer, 1);
285
286   new_buffer->type = type;
287   new_buffer->index = buffer->index;
288   new_buffer->stream_id = stream_id;
289   new_buffer->control = control;
290   new_buffer->buffer = gst_buffer_new();
291   if (!new_buffer->buffer) {
292     GST_ERROR_OBJECT(camerasrc, "new GstBuffer failed");
293     goto _BUFFER_NEW_FAILED;
294   }
295
296   if (meta) {
297     GST_DEBUG_OBJECT(camerasrc, "meta: is_delta[%d]", meta->is_delta_frame);
298     GST_DEBUG_OBJECT(camerasrc, "meta: focus_state[%d]", meta->focus_state);
299     GST_DEBUG_OBJECT(camerasrc, "meta: facing_direction[%d]", meta->facing_direction);
300     GST_DEBUG_OBJECT(camerasrc, "meta: flip[%d]", meta->flip);
301     GST_DEBUG_OBJECT(camerasrc, "meta: rotation[%d]", meta->rotation);
302     GST_DEBUG_OBJECT(camerasrc, "meta: status_ae[%d]", meta->status_ae);
303     GST_DEBUG_OBJECT(camerasrc, "meta: status_awb[%d]", meta->status_awb);
304
305     is_delta_frame = (gboolean)meta->is_delta_frame;
306
307     if (camerasrc->buffer_quark != _DEFAULT_BUFFER_QUARK) {
308       structure_metadata = gst_structure_new("metadata",
309         "focus-state", G_TYPE_INT, meta->focus_state,
310         "facing-direction", G_TYPE_INT, meta->facing_direction,
311         "flip", G_TYPE_INT, meta->flip,
312         "rotation", G_TYPE_INT, meta->rotation,
313         "status-ae", G_TYPE_INT, meta->status_ae,
314         "status-awb", G_TYPE_INT, meta->status_awb,
315         NULL);
316       if (structure_metadata) {
317         GST_LOG_OBJECT(camerasrc, "new structure [%p]", structure_metadata);
318         gst_mini_object_set_qdata(GST_MINI_OBJECT_CAST(new_buffer->buffer),
319           camerasrc->buffer_quark, structure_metadata, (GDestroyNotify)gst_structure_free);
320       } else {
321         GST_WARNING_OBJECT(camerasrc, "failed to create structure for metadata");
322       }
323     }
324   }
325
326   if (is_delta_frame)
327     GST_BUFFER_FLAG_SET(new_buffer->buffer, GST_BUFFER_FLAG_DELTA_UNIT);
328   else
329     GST_BUFFER_FLAG_UNSET(new_buffer->buffer, GST_BUFFER_FLAG_DELTA_UNIT);
330
331   /* set timestamp info */
332   gst_tizencamerasrc_get_timeinfo(camerasrc, new_buffer->buffer);
333
334   if (is_tbm_used) {
335     GST_DEBUG_OBJECT(camerasrc, "TBM -> Tizen allocator");
336
337     if (camerasrc->is_encoded_format) {
338       /* create tizen memory for gst buffer with tbm bo */
339       memory = gst_tizen_allocator_alloc_bo(camerasrc->allocator,
340         &camerasrc->video_info,
341         buffer->bos[0],
342         (buffer->planes[0].bytesused > 0 ? buffer->planes[0].bytesused : buffer->planes[0].size),
343         (gpointer)new_buffer,
344         (GDestroyNotify)gst_tizencamerasrc_buffer_finalize);
345     } else {
346       /* create tbm surface from buffer */
347       new_buffer->t_surface = tbm_surface_internal_create_with_bos(&camerasrc->ts_info,
348         (tbm_bo *)buffer->bos, buffer->num_bos);
349       if (!new_buffer->t_surface) {
350         GST_ERROR_OBJECT(camerasrc, "tbm surface create failed");
351         goto _BUFFER_NEW_FAILED;
352       }
353
354       /* create tizen memory for gst buffer with tbm surface */
355       memory = gst_tizen_allocator_alloc_surface(camerasrc->allocator,
356         &camerasrc->video_info,
357         new_buffer->t_surface,
358         (gpointer)new_buffer,
359         (GDestroyNotify)gst_tizencamerasrc_buffer_finalize);
360     }
361   } else {
362     GST_DEBUG_OBJECT(camerasrc, "NOT TBM - size %u", buffer->total_size);
363
364     if (camerasrc->pix_format == CAMERA_PIXEL_FORMAT_H264 ||
365         camerasrc->pix_format == CAMERA_PIXEL_FORMAT_MJPEG ||
366         camerasrc->pix_format == CAMERA_PIXEL_FORMAT_VP8 ||
367         camerasrc->pix_format == CAMERA_PIXEL_FORMAT_VP9) {
368       /* memory copy for h264/mjpeg/vp8/vp9 stream */
369       int i = 0;
370       uint32_t total_size = 0;
371       new_buffer->copied_data = g_malloc(buffer->total_size);
372       for (i = 0 ; i < buffer->num_planes ; i++) {
373         memcpy(new_buffer->copied_data + total_size, buffer->planes[i].data, buffer->planes[i].size);
374         total_size += buffer->planes[i].size;
375       }
376     } else {
377       new_buffer->copied_data = g_memdup2(buffer->planes[0].data, buffer->total_size);
378     }
379
380     ret = __gst_tizencamerasrc_release_buffer(camerasrc, type, buffer->index, stream_id);
381     if (ret != CAMERA_ERROR_NONE) {
382       GST_ERROR_OBJECT(camerasrc, "release buffer failed[0x%x]", ret);
383       goto _BUFFER_NEW_FAILED;
384     }
385
386     memory = gst_memory_new_wrapped(0,
387       new_buffer->copied_data,
388       buffer->total_size,
389       0,
390       buffer->total_size,
391       (gpointer)new_buffer,
392       (GDestroyNotify)gst_tizencamerasrc_buffer_finalize);
393   }
394
395   if (!memory) {
396     GST_ERROR_OBJECT(camerasrc, "GstMemory failed");
397     goto _BUFFER_NEW_FAILED;
398   }
399
400   new_buffer->camerasrc = gst_object_ref(GST_OBJECT(camerasrc));
401   gst_buffer_append_memory(new_buffer->buffer, memory);
402
403   GST_DEBUG_OBJECT(camerasrc, "memory[%p][%"G_GSIZE_FORMAT"], buffer[%p,%p][%"G_GSIZE_FORMAT"], buffer max[%"G_GSIZE_FORMAT"]",
404     memory, gst_memory_get_sizes(memory, NULL, NULL),
405     new_buffer, new_buffer->buffer,
406     gst_buffer_get_sizes(new_buffer->buffer, NULL, &maxsize),
407     maxsize);
408
409   return new_buffer->buffer;
410
411 _BUFFER_NEW_FAILED:
412   if (new_buffer) {
413     if (new_buffer->t_surface)
414       tbm_surface_destroy(new_buffer->t_surface);
415     if (new_buffer->buffer)
416       gst_buffer_unref(new_buffer->buffer);
417     g_free(new_buffer);
418   }
419
420   return NULL;
421 }
422
423
424 static void gst_tizencamerasrc_buffer_finalize(GstTizenCameraBuffer *buffer)
425 {
426   int ret = CAMERA_ERROR_NONE;
427   GstTizenCameraSrc *camerasrc = NULL;
428
429   if (!buffer) {
430     GST_ERROR("NULL buffer");
431     return;
432   }
433
434   GST_DEBUG("type[%d], index[%d], stream_id[%d], copied_data[%p]",
435     buffer->type, buffer->index, buffer->stream_id, buffer->copied_data);
436
437   camerasrc = buffer->camerasrc;
438
439   /* "copied_data != NULL" means that TBM is not used for buffer
440      and no need to call function to release buffer to HAL. */
441   if (buffer->copied_data) {
442     g_free(buffer->copied_data);
443     buffer->copied_data = NULL;
444   } else {
445     ret = __gst_tizencamerasrc_release_buffer(camerasrc, buffer->type, buffer->index, buffer->stream_id);
446     if (ret != CAMERA_ERROR_NONE)
447       GST_WARNING_OBJECT(camerasrc, "release buffer failed[0x%x]", ret);
448   }
449
450   g_mutex_lock(&buffer->control->lock);
451
452   buffer->control->live_buffers--;
453   GST_LOG_OBJECT(camerasrc, "type[%d] live buffers %d", buffer->type, buffer->control->live_buffers);
454   g_cond_broadcast(&buffer->control->cond);
455
456   g_mutex_unlock(&buffer->control->lock);
457
458   if (buffer->t_surface) {
459     tbm_surface_destroy(buffer->t_surface);
460     buffer->t_surface = NULL;
461   }
462
463   gst_object_unref(camerasrc);
464   g_free(buffer);
465
466   GST_DEBUG("done");
467
468   return;
469 }
470
471
472 static void gst_tizencamerasrc_set_video_format(GstTizenCameraSrc *camerasrc)
473 {
474   int ret = CAMERA_ERROR_NONE;
475   camera_format_s set_format;
476
477   if (!camerasrc) {
478     GST_ERROR("NULL handle");
479     return;
480   }
481
482   CLEAR(set_format);
483
484   set_format.stream_format = camerasrc->pix_format;
485   set_format.stream_resolution.width = camerasrc->video_width;
486   set_format.stream_resolution.height = camerasrc->video_height;
487   set_format.stream_fps = camerasrc->video_fps;
488
489   switch (camerasrc->rotate) {
490   case 90:
491     set_format.stream_rotation = CAMERA_ROTATION_90;
492     break;
493   case 180:
494     set_format.stream_rotation = CAMERA_ROTATION_180;
495     break;
496   case 270:
497     set_format.stream_rotation = CAMERA_ROTATION_270;
498     break;
499   case 0:
500   default:
501     set_format.stream_rotation = CAMERA_ROTATION_0;
502     break;
503   }
504
505   if (!__gst_tizencamerasrc_get_raw_pixel_info(camerasrc->cap_fourcc, &set_format.capture_format)) {
506     GST_WARNING_OBJECT(camerasrc, "__gst_tizencamerasrc_get_raw_pixel_info failed, set default JPEG");
507     set_format.capture_format = CAMERA_PIXEL_FORMAT_JPEG;
508   }
509   set_format.capture_resolution.width = camerasrc->cap_width;
510   set_format.capture_resolution.height = camerasrc->cap_height;
511   set_format.capture_quality = (uint32_t)camerasrc->cap_quality;
512
513   GST_INFO_OBJECT(camerasrc, "video resolution %dx%d, fps %d, format %d, rotation %d",
514     set_format.stream_resolution.width, set_format.stream_resolution.height,
515     set_format.stream_fps, set_format.stream_format, set_format.stream_rotation);
516
517   ret = hal_camera_set_video_stream_format(camerasrc->hal_handle, &set_format);
518   if (ret != CAMERA_ERROR_NONE)
519     GST_ERROR_OBJECT(camerasrc, "set video stream failed 0x%x", ret);
520
521   GST_INFO_OBJECT(camerasrc, "done");
522
523   return;
524 }
525
526
527 static void gst_tizencamerasrc_set_capture_format(GstTizenCameraSrc *camerasrc)
528 {
529   int ret = CAMERA_ERROR_NONE;
530   GstState state = GST_STATE_NULL;
531   GstStateChangeReturn gst_ret;
532   camera_format_s stream_format;
533
534   if (!camerasrc) {
535     GST_ERROR("NULL handle");
536     return;
537   }
538
539   gst_ret = gst_element_get_state((GstElement *)camerasrc, &state, NULL, GST_CLOCK_TIME_NONE);
540   if (gst_ret == GST_STATE_CHANGE_FAILURE || gst_ret == GST_STATE_CHANGE_ASYNC) {
541     GST_WARNING_OBJECT(camerasrc, "failed to get state : %d", gst_ret);
542     return;
543   }
544
545   GST_INFO_OBJECT(camerasrc, "Set capture resolution %dx%d - state %d",
546     camerasrc->cap_width_tmp, camerasrc->cap_height_tmp, state);
547
548   /* check state */
549   if (state <= GST_STATE_READY) {
550     GST_INFO_OBJECT(camerasrc, "[state %d] it will be set later", state);
551     goto _SET_DONE;
552   }
553
554   /* preview capture resolution */
555   ret = hal_camera_get_preview_stream_format(camerasrc->hal_handle, &stream_format);
556   if (ret != CAMERA_ERROR_NONE) {
557     GST_ERROR_OBJECT(camerasrc, "failed to get stream format for preview");
558     return;
559   }
560
561   if (!__gst_tizencamerasrc_get_raw_pixel_info(camerasrc->cap_fourcc, &stream_format.capture_format)) {
562     GST_WARNING_OBJECT(camerasrc, "_gst_tizencamerasrc_get_raw_pixel_info failed, set default JPEG");
563     stream_format.capture_format = CAMERA_PIXEL_FORMAT_JPEG;
564   }
565   stream_format.capture_resolution.width = camerasrc->cap_width_tmp;
566   stream_format.capture_resolution.height = camerasrc->cap_height_tmp;
567
568   ret = hal_camera_set_preview_stream_format(camerasrc->hal_handle, &stream_format);
569   if (ret != CAMERA_ERROR_NONE) {
570     GST_ERROR_OBJECT(camerasrc, "failed to set stream format for preview 0x%x", ret);
571     return;
572   }
573
574   /* video capture resolution */
575   if (camerasrc->recording_hint) {
576     ret = hal_camera_get_video_stream_format(camerasrc->hal_handle, &stream_format);
577     if (ret != CAMERA_ERROR_NONE) {
578       GST_ERROR_OBJECT(camerasrc, "failed to get stream format for video");
579       return;
580     }
581
582     stream_format.capture_resolution.width = camerasrc->cap_width_tmp;
583     stream_format.capture_resolution.height = camerasrc->cap_height_tmp;
584
585     ret = hal_camera_set_video_stream_format(camerasrc->hal_handle, &stream_format);
586     if (ret != CAMERA_ERROR_NONE) {
587       GST_ERROR_OBJECT(camerasrc, "failed to set stream format for video 0x%x", ret);
588       return;
589     }
590   }
591
592 _SET_DONE:
593   if (ret == CAMERA_ERROR_NONE) {
594     camerasrc->cap_width = camerasrc->cap_width_tmp;
595     camerasrc->cap_height = camerasrc->cap_height_tmp;
596   }
597
598   GST_INFO_OBJECT(camerasrc, "done");
599
600   return;
601 }
602
603
604 static void gst_tizencamerasrc_error_handler(GstTizenCameraSrc *camerasrc, int ret)
605 {
606   if (!camerasrc) {
607     GST_ERROR_OBJECT(camerasrc, "NULL camerasrc");
608     return;
609   }
610
611   switch (ret) {
612   case CAMERA_ERROR_NONE:
613     GST_WARNING_OBJECT(camerasrc, "NO ERROR");
614     break;
615   case CAMERA_ERROR_INTERNAL:
616     GST_ELEMENT_ERROR(camerasrc, RESOURCE, FAILED, ("IO control error"), GST_ERROR_SYSTEM);
617     break;
618   case CAMERA_ERROR_DEVICE_OPEN:
619     GST_ELEMENT_ERROR(camerasrc, RESOURCE, OPEN_READ_WRITE, ("camera open failed"), GST_ERROR_SYSTEM);
620     break;
621   case CAMERA_ERROR_DEVICE_BUSY:
622     GST_ELEMENT_ERROR(camerasrc, RESOURCE, BUSY, ("camera device busy"), GST_ERROR_SYSTEM);
623     break;
624   case CAMERA_ERROR_DEVICE_NOT_FOUND:
625     GST_ELEMENT_ERROR(camerasrc, RESOURCE, NOT_FOUND, ("camera device not found"), GST_ERROR_SYSTEM);
626     break;
627   case CAMERA_ERROR_DEVICE_UNAVAILABLE:
628     GST_ELEMENT_ERROR(camerasrc, RESOURCE, OPEN_READ, ("camera device unavailable"), GST_ERROR_SYSTEM);
629     break;
630   case CAMERA_ERROR_DEVICE_TIME_OUT:
631     GST_ELEMENT_ERROR(camerasrc, RESOURCE, TOO_LAZY, ("Time Out"), GST_ERROR_SYSTEM);
632     break;
633   case CAMERA_ERROR_DEVICE_NOT_SUPPORTED:
634     GST_ELEMENT_ERROR(camerasrc, RESOURCE, SETTINGS, ("Not supported"), GST_ERROR_SYSTEM);
635     break;
636   case CAMERA_ERROR_OUT_OF_MEMORY:
637     GST_ELEMENT_ERROR(camerasrc, RESOURCE, SETTINGS, ("memory allocation failed"), GST_ERROR_SYSTEM);
638     break;
639   case CAMERA_ERROR_PERMISSION_DENIED:
640     GST_ELEMENT_ERROR(camerasrc, RESOURCE, FAILED, ("Security service failed"), GST_ERROR_SYSTEM);
641     break;
642   case CAMERA_ERROR_DEVICE_READ:
643     GST_ELEMENT_ERROR(camerasrc, RESOURCE, READ, ("camera read failed"), GST_ERROR_SYSTEM);
644     break;
645   case CAMERA_ERROR_DEVICE_WRITE:
646     GST_ELEMENT_ERROR(camerasrc, RESOURCE, WRITE, ("camera write failed"), GST_ERROR_SYSTEM);
647     break;
648   default:
649     GST_ELEMENT_ERROR(camerasrc, RESOURCE, SEEK, (("General video device error[ret=%x]"), ret), GST_ERROR_SYSTEM);
650     break;
651   }
652
653   return;
654 }
655
656
657 /* VOID:OBJECT,OBJECT,OBJECT (generated by 'glib-genmarshal') */
658 #define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
659 static void
660 gst_tizencamerasrc_VOID__OBJECT_OBJECT_OBJECT(GClosure *closure,
661   GValue *return_value G_GNUC_UNUSED,
662   guint n_param_values,
663   const GValue *param_values,
664   gpointer invocation_hint G_GNUC_UNUSED,
665   gpointer marshal_data)
666 {
667   typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT_OBJECT)(gpointer data1,
668     gpointer arg_1,
669     gpointer arg_2,
670     gpointer arg_3,
671     gpointer data2);
672
673   register GMarshalFunc_VOID__OBJECT_OBJECT_OBJECT callback;
674   register GCClosure *cc = (GCClosure *)closure;
675   register gpointer data1;
676   register gpointer data2;
677
678   g_return_if_fail(n_param_values == 4);
679
680   if (G_CCLOSURE_SWAP_DATA(closure)) {
681     data1 = closure->data;
682     data2 = g_value_peek_pointer(param_values + 0);
683   } else {
684     data1 = g_value_peek_pointer(param_values + 0);
685     data2 = closure->data;
686   }
687
688   callback = (GMarshalFunc_VOID__OBJECT_OBJECT_OBJECT)(marshal_data ? marshal_data : cc->callback);
689
690   callback(data1,
691     g_marshal_value_peek_object(param_values + 1),
692     g_marshal_value_peek_object(param_values + 2),
693     g_marshal_value_peek_object(param_values + 3),
694     data2);
695
696   return;
697 }
698
699 static void
700 gst_tizencamerasrc_VOID__OBJECT_VIDEO_STREAM(GClosure *closure,
701   GValue *return_value,
702   guint n_param_values,
703   const GValue *param_values,
704   gpointer invocation_hint,
705   gpointer marshal_data)
706 {
707   typedef void (*GMarshalFunc_VOID__OBJECT_VIDEO_STREAM)(gpointer data1,
708     gpointer arg,
709     gpointer data2);
710   register GMarshalFunc_VOID__OBJECT_VIDEO_STREAM callback;
711   register GCClosure *cc = (GCClosure *) closure;
712   register gpointer data1, data2;
713
714   g_return_if_fail (n_param_values == 2);
715
716   if (G_CCLOSURE_SWAP_DATA(closure)) {
717     data1 = closure->data;
718     data2 = g_value_peek_pointer(param_values + 0);
719   } else {
720     data1 = g_value_peek_pointer(param_values + 0);
721     data2 = closure->data;
722   }
723
724   callback = (GMarshalFunc_VOID__OBJECT_VIDEO_STREAM)(marshal_data ? marshal_data : cc->callback);
725
726   callback(data1,
727     g_marshal_value_peek_object(param_values + 1),
728     data2);
729 }
730
731 static void
732 gst_tizencamerasrc_VOID__OBJECT_EXTRA_PREVIEW_STREAM(GClosure *closure,
733   GValue *return_value G_GNUC_UNUSED,
734   guint n_param_values,
735   const GValue *param_values,
736   gpointer invocation_hint G_GNUC_UNUSED,
737   gpointer marshal_data)
738 {
739   typedef void (*GMarshalFunc_VOID__OBJECT_EXTRA_PREVIEW_STREAM)(gpointer data1,
740     gpointer arg_1,
741     gpointer arg_2,
742     gpointer data2);
743
744   register GMarshalFunc_VOID__OBJECT_EXTRA_PREVIEW_STREAM callback;
745   register GCClosure *cc = (GCClosure *)closure;
746   register gpointer data1;
747   register gpointer data2;
748
749   g_return_if_fail(n_param_values == 3);
750
751   if (G_CCLOSURE_SWAP_DATA(closure)) {
752     data1 = closure->data;
753     data2 = g_value_peek_pointer(param_values + 0);
754   } else {
755     data1 = g_value_peek_pointer(param_values + 0);
756     data2 = closure->data;
757   }
758
759   callback = (GMarshalFunc_VOID__OBJECT_EXTRA_PREVIEW_STREAM)(marshal_data ? marshal_data : cc->callback);
760
761   callback(data1,
762     g_marshal_value_peek_object(param_values + 1),
763     g_marshal_value_peek_object(param_values + 2),
764     data2);
765
766   return;
767 }
768
769 /* use following BOILERPLATE MACRO as _get_type entry */
770 G_DEFINE_TYPE_WITH_CODE(GstTizenCameraSrc, gst_tizencamerasrc, GST_TYPE_PUSH_SRC,
771   G_IMPLEMENT_INTERFACE(GST_TYPE_URI_HANDLER, gst_tizencamerasrc_uri_handler_init)
772   G_IMPLEMENT_INTERFACE(GST_TYPE_CAMERA_CONTROL, gst_tizencamera_src_control_interface_init)
773   G_IMPLEMENT_INTERFACE(GST_TYPE_COLOR_BALANCE, gst_tizencamera_src_color_balance_interface_init));
774
775 static int __camera_hal_message_callback(camera_message_s *message, void *user_data)
776 {
777   GstTizenCameraSrc *camerasrc = NULL;
778
779   if (message == NULL || user_data == NULL) {
780     GST_ERROR("message callback error %p %p", message, user_data);
781     return FALSE;
782   }
783
784   camerasrc = (GstTizenCameraSrc *)user_data;
785
786   switch (message->type) {
787   case CAMERA_MESSAGE_TYPE_FOCUS_CHANGED:
788     GST_INFO_OBJECT(camerasrc, "focus state %d", message->focus_state);
789     __gst_tizencamerasrc_post_message_int(camerasrc, "camerasrc-AF", "focus-state", message->focus_state);
790     break;
791   case CAMERA_MESSAGE_TYPE_CAPTURED:
792     GST_INFO_OBJECT(camerasrc, "CAPTURED");
793     break;
794   case CAMERA_MESSAGE_TYPE_HDR_PROGRESS:
795     GST_INFO_OBJECT(camerasrc, "HDR progress %d", message->hdr_progress);
796     break;
797   case CAMERA_MESSAGE_TYPE_ERROR:
798     GST_ERROR_OBJECT(camerasrc, "error from camera HAL 0x%x", message->error_code);
799     camerasrc->hal_error_code = message->error_code;
800     gst_tizencamerasrc_error_handler(camerasrc, camerasrc->hal_error_code);
801     g_cond_broadcast(&camerasrc->preview_control.cond);
802     break;
803   default:
804     GST_ERROR_OBJECT(camerasrc, "unknown type message %d", message->type);
805     return FALSE;
806   }
807
808   return TRUE;
809 }
810
811
812 static int __camera_preview_frame_cb(camera_buffer_s *buffer, camera_metadata_s *meta, void *user_data)
813 {
814   GstTizenCameraSrc *camerasrc = NULL;
815   GstBuffer *gst_buffer = NULL;
816
817   if (!buffer || !user_data) {
818     GST_ERROR("preview callback error %p %p", buffer, user_data);
819     return FALSE;
820   }
821
822   camerasrc = (GstTizenCameraSrc *)user_data;
823
824   g_mutex_lock(&camerasrc->preview_control.lock);
825
826   if (camerasrc->preview_control.running == FALSE ||
827     camerasrc->live_buffer_check < camerasrc->preview_control.live_buffers) {
828     hal_camera_release_preview_buffer(camerasrc->hal_handle, buffer->index);
829     GST_WARNING_OBJECT(camerasrc, "Skip buffer[%d] running %d, Live buffer[%d/%d]",
830       buffer->index, camerasrc->preview_control.running,
831       camerasrc->preview_control.live_buffers, camerasrc->live_buffer_check);
832     goto _PREVIEW_FRAME_CB_DONE;
833   }
834
835   /* create new buffer */
836   gst_buffer = gst_tizencamerasrc_buffer_new(camerasrc, buffer, meta,
837     BUFFER_TYPE_PREVIEW, &camerasrc->preview_control, -1);
838   if (!gst_buffer) {
839     GST_ERROR_OBJECT(camerasrc, "new buffer allocation failed. size %u", buffer->total_size);
840     hal_camera_release_preview_buffer(camerasrc->hal_handle, buffer->index);
841     goto _PREVIEW_FRAME_CB_DONE;
842   }
843
844   if (camerasrc->preview_control.is_first_frame) {
845     camerasrc->preview_control.is_first_frame = FALSE;
846     camerasrc->preview_control.is_tbm_used = (buffer->num_bos > 0);
847     GST_WARNING_OBJECT(camerasrc, "TBM in buffer[%d] (num_bos[%u])",
848       camerasrc->preview_control.is_tbm_used, buffer->num_bos);
849   }
850
851   camerasrc->preview_control.live_buffers++;
852   GST_DEBUG_OBJECT(camerasrc, "%p [size %u][preview_live_buffers %d]",
853     gst_buffer, buffer->total_size, camerasrc->preview_control.live_buffers);
854
855   /* add new buffer to preview buffer list */
856   g_queue_push_tail(camerasrc->preview_buffer_list, gst_buffer);
857   g_cond_broadcast(&camerasrc->preview_control.cond);
858
859 _PREVIEW_FRAME_CB_DONE:
860   g_mutex_unlock(&camerasrc->preview_control.lock);
861
862   GST_DEBUG_OBJECT(camerasrc, "done");
863
864   return TRUE;
865 }
866
867
868 static int __camera_extra_preview_frame_cb(camera_buffer_s *buffer, camera_metadata_s *meta, int stream_id, void *user_data)
869 {
870   GstTizenCameraSrc *camerasrc = NULL;
871   GstSample *gst_sample = NULL;
872   GstBuffer *gst_buffer = NULL;
873
874   if (!buffer || !user_data || stream_id < 0 || stream_id >= EXTRA_PREVIEW_STREAM_MAX) {
875     GST_ERROR("invalid param[%p,%p,%d]", buffer, user_data, stream_id);
876     return FALSE;
877   }
878
879   camerasrc = (GstTizenCameraSrc *)user_data;
880
881   g_mutex_lock(&camerasrc->extra_preview_control.lock);
882
883   if (camerasrc->preview_control.running == FALSE) {
884     GST_WARNING("Skip buffer[stream_id:%d,i:%d]", stream_id, buffer->index);
885     goto _EXTRA_PREVIEW_FRAME_CB_DONE;
886   }
887
888   if (!camerasrc->extra_caps[stream_id])
889     camerasrc->extra_caps[stream_id] = __gst_tizencamerasrc_get_caps_from_buffer(buffer);
890
891   if (!camerasrc->extra_caps[stream_id]) {
892     GST_ERROR("extra caps failed for stream id[%d]", stream_id);
893     goto _EXTRA_PREVIEW_FRAME_CB_DONE;
894   }
895
896   /* create new buffer and sample */
897   gst_buffer = gst_tizencamerasrc_buffer_new(camerasrc, buffer, meta,
898     BUFFER_TYPE_EXTRA_PREVIEW, &camerasrc->extra_preview_control, stream_id);
899   if (!gst_buffer) {
900     GST_ERROR("new buffer allocation failed. size %u", buffer->total_size);
901     goto _EXTRA_PREVIEW_FRAME_CB_DONE;
902   }
903
904   gst_sample = gst_sample_new(gst_buffer, camerasrc->extra_caps[stream_id], NULL, NULL);
905   if (!gst_sample) {
906     GST_ERROR("new sample failed for stream_id[%d]", stream_id);
907     goto _EXTRA_PREVIEW_FRAME_CB_DONE;
908   }
909
910   camerasrc->extra_preview_control.live_buffers++;
911
912 _EXTRA_PREVIEW_FRAME_CB_DONE:
913   g_mutex_unlock(&camerasrc->extra_preview_control.lock);
914
915   if (gst_sample) {
916     g_signal_emit(G_OBJECT(camerasrc),
917       gst_tizencamerasrc_signals[SIGNAL_EXTRA_PREVIEW_STREAM_CB],
918       0,
919       stream_id,
920       gst_sample);
921   } else {
922     hal_camera_release_extra_preview_buffer(camerasrc->hal_handle, stream_id, buffer->index);
923   }
924
925   if (gst_buffer)
926     gst_buffer_unref(gst_buffer);
927
928   GST_DEBUG("done");
929
930   return TRUE;
931 }
932
933
934 static int __camera_video_frame_cb(camera_buffer_s *buffer, camera_metadata_s *meta, void *user_data)
935 {
936   GstTizenCameraSrc *camerasrc = NULL;
937   GstBuffer *gst_buffer = NULL;
938   GstSample *gst_sample = NULL;
939
940   if (!buffer || !user_data) {
941     GST_ERROR("video callback error %p %p", buffer, user_data);
942     return FALSE;
943   }
944
945   camerasrc = (GstTizenCameraSrc *)user_data;
946
947   g_mutex_lock(&camerasrc->video_control.lock);
948
949   if (camerasrc->video_control.running == FALSE ||
950     camerasrc->live_buffer_check < camerasrc->video_control.live_buffers) {
951     GST_WARNING("Skip buffer[%d] running %d, Live buffer[%d/%d]",
952       buffer->index, camerasrc->video_control.running,
953       camerasrc->video_control.live_buffers, camerasrc->live_buffer_check);
954     goto _VIDEO_FRAME_CB_DONE;
955   }
956
957   /* create new buffer and sample */
958   gst_buffer = gst_tizencamerasrc_buffer_new(camerasrc, buffer, meta,
959     BUFFER_TYPE_VIDEO, &camerasrc->video_control, -1);
960   if (!gst_buffer) {
961     GST_ERROR("new buffer allocation failed. size %u", buffer->total_size);
962     goto _VIDEO_FRAME_CB_DONE;
963   }
964
965   if (!camerasrc->video_caps)
966     camerasrc->video_caps = __gst_tizencamerasrc_get_caps_from_buffer(buffer);
967
968   if (!camerasrc->video_caps) {
969     GST_ERROR("video caps failed");
970     goto _VIDEO_FRAME_CB_DONE;
971   }
972
973   gst_sample = gst_sample_new(gst_buffer, camerasrc->video_caps, NULL, NULL);
974   if (!gst_sample) {
975     GST_ERROR("new sample failed for buffer index[%d]", buffer->index);
976     goto _VIDEO_FRAME_CB_DONE;
977   }
978
979   camerasrc->video_control.live_buffers++;
980
981   GST_DEBUG_OBJECT(camerasrc, "index %d, %p, %p [size total %u][video_live_buffers %d]",
982     buffer->index, gst_sample, gst_buffer, buffer->total_size, camerasrc->video_control.live_buffers);
983
984 _VIDEO_FRAME_CB_DONE:
985   g_mutex_unlock(&camerasrc->video_control.lock);
986
987   if (gst_sample) {
988     g_signal_emit(G_OBJECT(camerasrc),
989       gst_tizencamerasrc_signals[SIGNAL_VIDEO_STREAM_CB],
990       0,
991       gst_sample);
992   } else {
993     hal_camera_release_video_buffer(camerasrc->hal_handle, buffer->index);
994   }
995
996   if (gst_buffer)
997     gst_buffer_unref(gst_buffer);
998
999   GST_DEBUG_OBJECT(camerasrc, "done");
1000
1001   return TRUE;
1002 }
1003
1004
1005 static GstVideoFormat __get_gst_video_format(camera_pixel_format_e pixel_format)
1006 {
1007   switch (pixel_format) {
1008   case CAMERA_PIXEL_FORMAT_NV12:
1009     return GST_VIDEO_FORMAT_NV12;
1010   case CAMERA_PIXEL_FORMAT_NV21:
1011     return GST_VIDEO_FORMAT_NV21;
1012   case CAMERA_PIXEL_FORMAT_I420:
1013     return GST_VIDEO_FORMAT_I420;
1014   case CAMERA_PIXEL_FORMAT_YV12:
1015     return GST_VIDEO_FORMAT_YV12;
1016   case CAMERA_PIXEL_FORMAT_YUYV:
1017     return GST_VIDEO_FORMAT_YUY2;
1018   case CAMERA_PIXEL_FORMAT_UYVY:
1019     return GST_VIDEO_FORMAT_UYVY;
1020   case CAMERA_PIXEL_FORMAT_H264:
1021     /* fall through */
1022   case CAMERA_PIXEL_FORMAT_MJPEG:
1023     /* fall through */
1024   case CAMERA_PIXEL_FORMAT_VP8:
1025     /* fall through */
1026   case CAMERA_PIXEL_FORMAT_VP9:
1027     return GST_VIDEO_FORMAT_ENCODED;
1028   default:
1029     GST_ERROR("unknown pixel format %d", pixel_format);
1030     return -1;
1031   }
1032 }
1033
1034 static GstSample *__create_buffer_sample(GstTizenCameraSrc *camerasrc, camera_buffer_s *cam_buffer)
1035 {
1036   GstBuffer *gst_buffer = NULL;
1037   GstCaps *caps = NULL;
1038   GstSample *sample = NULL;
1039   const gchar *string_fourcc = NULL;
1040   const gchar *media_type = NULL;
1041
1042   if (!camerasrc) {
1043     GST_ERROR("NULL handle");
1044     return NULL;
1045   }
1046
1047   if (!cam_buffer) {
1048     GST_ERROR_OBJECT(camerasrc, "NULL buffer");
1049     return NULL;
1050   }
1051
1052   gst_buffer = gst_buffer_new_wrapped_full(0,
1053     cam_buffer->planes[0].data,
1054     cam_buffer->planes[0].size,
1055     0,
1056     cam_buffer->planes[0].bytesused,
1057     NULL, NULL);
1058   if (!gst_buffer) {
1059     GST_ERROR_OBJECT(camerasrc, "failed to allocate gst buffer for %p", cam_buffer);
1060     return NULL;
1061   }
1062
1063   switch (cam_buffer->format) {
1064   case CAMERA_PIXEL_FORMAT_JPEG:
1065     /* fall through */
1066   case CAMERA_PIXEL_FORMAT_MJPEG:
1067     media_type = "image/jpeg";
1068     break;
1069   case CAMERA_PIXEL_FORMAT_H264:
1070     media_type = "video/x-h264";
1071     break;
1072   case CAMERA_PIXEL_FORMAT_VP8:
1073     media_type = "video/x-vp8";
1074     break;
1075   case CAMERA_PIXEL_FORMAT_VP9:
1076     media_type = "video/x-vp9";
1077     break;
1078   default:
1079     media_type = "video/x-raw";
1080     string_fourcc = gst_video_format_to_string(__get_gst_video_format(cam_buffer->format));
1081     if (!string_fourcc) {
1082       GST_WARNING_OBJECT(camerasrc, "failed to get string_fourcc[%d]", cam_buffer->format);
1083       goto _CREATE_BUFFER_SAMPLE_DONE;
1084     }
1085     break;
1086   }
1087
1088   caps = gst_caps_new_simple(media_type,
1089     "width", G_TYPE_INT, cam_buffer->resolution.width,
1090     "height", G_TYPE_INT, cam_buffer->resolution.height,
1091     NULL);
1092   if (!caps) {
1093     GST_ERROR_OBJECT(camerasrc, "sample caps creation failed for[%s]", media_type);
1094     goto _CREATE_BUFFER_SAMPLE_DONE;
1095   }
1096
1097   if (string_fourcc) {
1098     gst_caps_set_simple(caps,
1099       "format", G_TYPE_STRING, string_fourcc,
1100       NULL);
1101   }
1102
1103   sample = gst_sample_new(gst_buffer, caps, NULL, NULL);
1104   if (!sample) {
1105     GST_ERROR_OBJECT(camerasrc, "buffer sample1 creation failed");
1106     goto _CREATE_BUFFER_SAMPLE_DONE;
1107   }
1108
1109 _CREATE_BUFFER_SAMPLE_DONE:
1110   if (gst_buffer)
1111     gst_buffer_unref(gst_buffer);
1112   if (caps)
1113     gst_caps_unref(caps);
1114
1115   GST_INFO_OBJECT(camerasrc, "sample %p - format %d, %dx%d",
1116     sample, cam_buffer->format, cam_buffer->resolution.width, cam_buffer->resolution.height);
1117
1118   return sample;
1119 }
1120
1121
1122 static int _camera_capture_cb(camera_buffer_s *main, camera_buffer_s *postview, camera_buffer_s *thumbnail, void *user_data)
1123 {
1124   GstTizenCameraSrc *camerasrc = NULL;
1125   GstSample *buf_sample1 = NULL;
1126   GstSample *buf_sample2 = NULL;
1127   GstSample *buf_sample3 = NULL;
1128
1129   if (!main || !user_data) {
1130     GST_ERROR("capture callback error %p %p", main, user_data);
1131     return FALSE;
1132   }
1133
1134   camerasrc = (GstTizenCameraSrc *)user_data;
1135
1136   buf_sample1 = __create_buffer_sample(camerasrc, main);
1137   if (!buf_sample1) {
1138     GST_ERROR_OBJECT(camerasrc, "buffer sample1 creation failed");
1139     return FALSE;
1140   }
1141
1142   buf_sample2 = __create_buffer_sample(camerasrc, postview);
1143   if (!buf_sample2)
1144     GST_WARNING_OBJECT(camerasrc, "No sample for postview");
1145
1146   buf_sample3 = __create_buffer_sample(camerasrc, thumbnail);
1147   if (!buf_sample3)
1148     GST_WARNING_OBJECT(camerasrc, "No sample for thumbnail");
1149
1150   GST_INFO_OBJECT(camerasrc, "CALL: capture callback");
1151
1152   g_signal_emit(G_OBJECT(camerasrc),
1153     gst_tizencamerasrc_signals[SIGNAL_STILL_CAPTURE],
1154     0,
1155     buf_sample1,
1156     buf_sample2,
1157     buf_sample3);
1158
1159   GST_INFO_OBJECT(camerasrc, "RETURN: capture callback");
1160
1161   return TRUE;
1162 }
1163
1164
1165 static gboolean gst_tizencamerasrc_create(GstTizenCameraSrc *camerasrc)
1166 {
1167   int ret = 0;
1168
1169   if (!camerasrc->hal_handle) {
1170     GST_ERROR_OBJECT(camerasrc, "no camera HAL interface handle");
1171     gst_tizencamerasrc_error_handler(camerasrc, CAMERA_ERROR_DEVICE_NOT_FOUND);
1172     return FALSE;
1173   }
1174
1175   if (camerasrc->device_name) {
1176     GST_INFO_OBJECT(camerasrc, "open device - device name [%s]", camerasrc->device_name);
1177     ret = hal_camera_open_device_ext(camerasrc->hal_handle, camerasrc->device_name);
1178   } else {
1179     GST_INFO_OBJECT(camerasrc, "open device - camera id [%d]", camerasrc->camera_id);
1180     ret = hal_camera_open_device(camerasrc->hal_handle, camerasrc->camera_id);
1181   }
1182
1183   if (ret != CAMERA_ERROR_NONE) {
1184     GST_ERROR_OBJECT(camerasrc, "device open failed 0x%08X", ret);
1185     gst_tizencamerasrc_error_handler(camerasrc, ret);
1186     return FALSE;
1187   }
1188
1189   if (!gst_tizencamerasrc_fill_ctrl_list(camerasrc))
1190     GST_WARNING_OBJECT(camerasrc, "Can't fill v4l2 control list.");
1191
1192   GST_INFO_OBJECT(camerasrc, "DONE");
1193
1194   return TRUE;
1195 }
1196
1197
1198 static gboolean gst_tizencamerasrc_destroy(GstTizenCameraSrc *camerasrc)
1199 {
1200   int ret = CAMERA_ERROR_NONE;
1201
1202   GST_INFO_OBJECT(camerasrc, "ENTERED");
1203
1204   if (camerasrc->hal_handle == NULL) {
1205     GST_ERROR_OBJECT(camerasrc, "not initialized");
1206     return FALSE;
1207   }
1208
1209   /* camera hal interface close device */
1210   GST_INFO_OBJECT(camerasrc, "ENTERED");
1211
1212   ret = hal_camera_close_device(camerasrc->hal_handle);
1213   if (ret != CAMERA_ERROR_NONE) {
1214     GST_ERROR_OBJECT(camerasrc, "hal_camera_close_device failed 0x%x", ret);
1215     return FALSE;
1216   }
1217
1218   /* Empty control list */
1219   gst_tizencamerasrc_empty_ctrl_list(camerasrc);
1220
1221   GST_INFO_OBJECT(camerasrc, "LEAVE");
1222
1223   return TRUE;
1224 }
1225
1226
1227 static gboolean gst_tizencamerasrc_fill_ctrl_list(GstTizenCameraSrc *camerasrc)
1228 {
1229   int n = 0;
1230   GstTizenCameraSrcCommand color_balance[] = {
1231     {"brightness",    CAMERA_COMMAND_BRIGHTNESS},
1232     {"contrast",      CAMERA_COMMAND_CONTRAST},
1233     {"white balance", CAMERA_COMMAND_WHITE_BALANCE},
1234     {"color tone",    CAMERA_COMMAND_EFFECT},
1235     {"saturation",    CAMERA_COMMAND_SATURATION},
1236     {"hue",           CAMERA_COMMAND_HUE},
1237     {"sharpness",     CAMERA_COMMAND_SHARPNESS}
1238   };
1239   GstTizenCameraSrcCommand camera_control[] = {
1240     {"ptz_type",         CAMERA_COMMAND_PTZ_TYPE},
1241     {"pan",              CAMERA_COMMAND_PAN},
1242     {"tilt",             CAMERA_COMMAND_TILT}
1243   };
1244
1245   g_return_val_if_fail(camerasrc, FALSE);
1246
1247   GST_DEBUG_OBJECT(camerasrc, "ENTERED");
1248
1249   for (n = 0 ; n < G_N_ELEMENTS(color_balance) ; n++) {
1250     GstTizenCameraSrcColorBalanceChannel *camerasrc_color_channel = NULL;
1251     GstColorBalanceChannel *color_channel = NULL;
1252
1253     camerasrc_color_channel = g_object_new(GST_TYPE_TIZENCAMERASRC_COLOR_BALANCE_CHANNEL, NULL);
1254     color_channel = GST_COLOR_BALANCE_CHANNEL(camerasrc_color_channel);
1255
1256     color_channel->label = g_strdup(color_balance[n].label);
1257     camerasrc_color_channel->id = color_balance[n].cmd;
1258     color_channel->min_value = 0;
1259     color_channel->max_value = 0;
1260
1261     camerasrc->colors = g_list_append(camerasrc->colors, (gpointer)color_channel);
1262     GST_INFO_OBJECT(camerasrc, "Adding Color Balance Channel %s [%"PRIx64"]",
1263                                color_channel->label, camerasrc_color_channel->id);
1264   }
1265
1266   for (n = 0 ; n < G_N_ELEMENTS(camera_control) ; n++) {
1267     GstTizenCamerasrcControlChannel *camerasrc_control_channel = NULL;
1268     GstCameraControlChannel *control_channel = NULL;
1269
1270     camerasrc_control_channel = g_object_new(GST_TYPE_TIZENCAMERASRC_CONTROL_CHANNEL, NULL);
1271     control_channel = GST_CAMERA_CONTROL_CHANNEL(camerasrc_control_channel);
1272
1273     control_channel->label = g_strdup(camera_control[n].label);
1274     camerasrc_control_channel->id = camera_control[n].cmd;
1275     control_channel->min_value = 0;
1276     control_channel->max_value = 0;
1277
1278     camerasrc->camera_controls = g_list_append(camerasrc->camera_controls, (gpointer)control_channel);
1279     GST_INFO_OBJECT(camerasrc, "Adding Camera Control Channel %s  [%"PRIx64"]",
1280                                control_channel->label, camerasrc_control_channel->id);
1281   }
1282
1283   GST_DEBUG_OBJECT(camerasrc, "LEAVE");
1284
1285   return TRUE;
1286 }
1287
1288
1289 static gboolean gst_tizencamerasrc_empty_ctrl_list(GstTizenCameraSrc *camerasrc)
1290 {
1291   g_return_val_if_fail(camerasrc, FALSE);
1292
1293   GST_DEBUG_OBJECT (camerasrc, "ENTERED");
1294
1295   g_list_foreach(camerasrc->colors, (GFunc)g_object_unref, NULL);
1296   g_list_free(camerasrc->colors);
1297   camerasrc->colors = NULL;
1298
1299   g_list_foreach(camerasrc->camera_controls, (GFunc)g_object_unref, NULL);
1300   g_list_free(camerasrc->camera_controls);
1301   camerasrc->camera_controls = NULL;
1302
1303   GST_DEBUG_OBJECT(camerasrc, "LEAVE");
1304
1305   return TRUE;
1306 }
1307
1308
1309 static gboolean gst_tizencamerasrc_start(GstTizenCameraSrc *camerasrc)
1310 {
1311   int i = 0;
1312   int ret = 0;
1313
1314   camera_flip_e set_flip;
1315   camera_format_s set_format;
1316
1317   GST_DEBUG_OBJECT(camerasrc, "ENTERED");
1318
1319   CLEAR(set_format);
1320
1321   /* set preview stream format */
1322   set_format.stream_format = camerasrc->pix_format;
1323   set_format.stream_resolution.width = camerasrc->width;
1324   set_format.stream_resolution.height = camerasrc->height;
1325   switch (camerasrc->rotate) {
1326   case 90:
1327     set_format.stream_rotation = CAMERA_ROTATION_90;
1328     break;
1329   case 180:
1330     set_format.stream_rotation = CAMERA_ROTATION_180;
1331     break;
1332   case 270:
1333     set_format.stream_rotation = CAMERA_ROTATION_270;
1334     break;
1335   case 0:
1336   default:
1337     set_format.stream_rotation = CAMERA_ROTATION_0;
1338     break;
1339   }
1340   if (camerasrc->fps_auto) {
1341     /*if fps is zero, auto fps mode*/
1342     set_format.stream_fps = 0;
1343
1344     GST_INFO_OBJECT (camerasrc, "AUTO FPS mode");
1345   } else if (camerasrc->high_speed_fps <= 0) {
1346     if (camerasrc->fps <= 0) {
1347       /*if fps is zero, auto fps mode*/
1348       set_format.stream_fps = 0;
1349     } else {
1350       set_format.stream_fps = camerasrc->fps;
1351     }
1352   } else {
1353     GST_INFO_OBJECT(camerasrc, "high speed fps %d", camerasrc->high_speed_fps);
1354     set_format.stream_fps = camerasrc->high_speed_fps;
1355   }
1356
1357   if (!__gst_tizencamerasrc_get_raw_pixel_info(camerasrc->cap_fourcc, &set_format.capture_format)) {
1358     GST_WARNING_OBJECT(camerasrc, "_gst_tizencamerasrc_get_raw_pixel_info failed, set default JPEG");
1359     set_format.capture_format = CAMERA_PIXEL_FORMAT_JPEG;
1360   }
1361   set_format.capture_resolution.width = camerasrc->cap_width;
1362   set_format.capture_resolution.height = camerasrc->cap_height;
1363   set_format.capture_quality = (uint32_t)camerasrc->cap_quality;
1364
1365   GST_WARNING_OBJECT(camerasrc, "resolution[%dx%d] fps[%d], format[%d], rotation[%d]",
1366     camerasrc->width, camerasrc->height, set_format.stream_fps,
1367     camerasrc->pix_format, camerasrc->rotate);
1368
1369   ret = hal_camera_set_preview_stream_format(camerasrc->hal_handle, &set_format);
1370   if (ret != CAMERA_ERROR_NONE) {
1371     GST_ERROR_OBJECT(camerasrc, "hal_camera_set_preview_stream_format() failed 0x%x", ret);
1372     goto _ERROR;
1373   }
1374
1375   /* set flip */
1376   if (camerasrc->vflip) {
1377     if (camerasrc->hflip)
1378       set_flip = CAMERA_FLIP_BOTH;
1379     else
1380       set_flip = CAMERA_FLIP_VERTICAL;
1381   } else {
1382     if (camerasrc->hflip)
1383       set_flip = CAMERA_FLIP_HORIZONTAL;
1384     else
1385       set_flip = CAMERA_FLIP_NONE;
1386   }
1387
1388   for (i = 0 ; i < EXTRA_PREVIEW_STREAM_MAX ; i++) {
1389     if (camerasrc->extra_caps[i]) {
1390       gst_caps_unref(camerasrc->extra_caps[i]);
1391       camerasrc->extra_caps[i] = NULL;
1392     }
1393   }
1394
1395   ret = hal_camera_set_command(camerasrc->hal_handle, CAMERA_COMMAND_FLIP, (void *)&set_flip);
1396   if (ret != CAMERA_ERROR_NONE) {
1397     GST_ERROR_OBJECT(camerasrc, "hal_camera_set_command() failed 0x%x", ret);
1398     goto _ERROR;
1399   }
1400
1401   GST_INFO_OBJECT(camerasrc, "VFLIP : %d, HFLIP : %d", camerasrc->vflip, camerasrc->hflip);
1402
1403   if (camerasrc->preview_control.live_buffers != 0)
1404     GST_WARNING_OBJECT(camerasrc, "CURRENT LIVE BUFFER COUNT[%d]", camerasrc->preview_control.live_buffers);
1405
1406   camerasrc->preview_control.live_buffers = 0;
1407   camerasrc->preview_control.is_first_frame = TRUE;
1408   camerasrc->extra_preview_control.live_buffers = 0;
1409   camerasrc->extra_preview_control.is_first_frame = TRUE;
1410
1411   if (!camerasrc->is_encoded_format && camerasrc->live_buffer_max_raw > 0)
1412     camerasrc->live_buffer_check = camerasrc->live_buffer_max_raw;
1413   else
1414     camerasrc->live_buffer_check = camerasrc->live_buffer_max;
1415
1416   GST_WARNING_OBJECT(camerasrc, "live buffer check[%d], max[%d,%d]",
1417     camerasrc->live_buffer_check, camerasrc->live_buffer_max, camerasrc->live_buffer_max_raw);
1418
1419   /* start preview stream */
1420   ret = hal_camera_start_preview(camerasrc->hal_handle, __camera_preview_frame_cb, camerasrc);
1421   if (ret != CAMERA_ERROR_NONE) {
1422     GST_ERROR_OBJECT(camerasrc, "hal_camera_start_preview() failed 0x%x", ret);
1423     camerasrc->preview_control.running = FALSE;
1424     goto _ERROR;
1425   }
1426
1427   GST_INFO_OBJECT(camerasrc, "camerasrc_start_preview_stream() done");
1428
1429   camerasrc->mode = VIDEO_IN_MODE_PREVIEW;
1430   camerasrc->preview_control.running = TRUE;
1431   camerasrc->hal_error_code = CAMERA_ERROR_NONE;
1432
1433   GST_INFO_OBJECT(camerasrc, "LEAVE");
1434
1435   return TRUE;
1436
1437 _ERROR:
1438   gst_tizencamerasrc_error_handler(camerasrc, ret);
1439   GST_ERROR_OBJECT(camerasrc, "LEAVE 0x%x", ret);
1440
1441   return FALSE;
1442 }
1443
1444
1445 static gboolean gst_tizencamerasrc_stop(GstTizenCameraSrc *camerasrc)
1446 {
1447   int ret = CAMERA_ERROR_NONE;
1448   gint64 end_time;
1449   GstBuffer *buffer = NULL;
1450
1451   GST_INFO_OBJECT (camerasrc, "ENTERED");
1452
1453   if (camerasrc->hal_handle) {
1454     g_mutex_lock(&camerasrc->preview_control.lock);
1455
1456     if (camerasrc->preview_control.running) {
1457       camerasrc->preview_control.running = FALSE;
1458     } else {
1459       GST_ERROR_OBJECT(camerasrc, "buffer NOT running");
1460       g_mutex_unlock(&camerasrc->preview_control.lock);
1461       return FALSE;
1462     }
1463
1464     g_mutex_unlock(&camerasrc->preview_control.lock);
1465
1466     /* remove all cached buffers */
1467     while (!g_queue_is_empty(camerasrc->preview_buffer_list)) {
1468       buffer = g_queue_pop_head(camerasrc->preview_buffer_list);
1469       GST_INFO_OBJECT(camerasrc, "unref queued buffer %p", buffer);
1470       gst_buffer_unref(buffer);
1471     }
1472
1473     g_mutex_lock(&camerasrc->preview_control.lock);
1474
1475     GST_INFO_OBJECT(camerasrc, "live buffer count %d", camerasrc->preview_control.live_buffers);
1476
1477       /* wait until all buffers are returned */
1478     while (camerasrc->preview_control.live_buffers > 0) {
1479       end_time = g_get_monotonic_time() + 1 * G_TIME_SPAN_SECOND;
1480       if (!g_cond_wait_until(&camerasrc->preview_control.cond, &camerasrc->preview_control.lock, end_time)) {
1481         GST_ERROR_OBJECT(camerasrc, "buffer wait failed");
1482         break;
1483       } else {
1484         GST_INFO_OBJECT(camerasrc, "signal received. check again [num %d]", camerasrc->preview_control.live_buffers);
1485       }
1486     }
1487
1488     g_mutex_unlock(&camerasrc->preview_control.lock);
1489
1490     GST_INFO_OBJECT(camerasrc, "stop preview stream");
1491
1492     /* stop preview stream */
1493     ret = hal_camera_stop_preview(camerasrc->hal_handle);
1494     if (ret != CAMERA_ERROR_NONE) {
1495       GST_ERROR_OBJECT(camerasrc, "hal_camera_stop_preview failed 0x%x", ret);
1496       camerasrc->preview_control.running = TRUE;
1497       return FALSE;
1498     }
1499
1500     camerasrc->mode = VIDEO_IN_MODE_NONE;
1501   }
1502
1503   GST_INFO_OBJECT(camerasrc, "LEAVE");
1504
1505   return TRUE;
1506 }
1507
1508
1509 static gboolean gst_tizencamerasrc_capture_start(GstTizenCameraSrc *camerasrc)
1510 {
1511   int ret = CAMERA_ERROR_NONE;
1512
1513   GST_INFO_OBJECT(camerasrc, "ENTERED - mode %d", camerasrc->mode);
1514
1515   if (camerasrc->mode != VIDEO_IN_MODE_PREVIEW) {
1516     GST_WARNING_OBJECT(camerasrc, "Wrong state[%d]!", camerasrc->mode);
1517     return FALSE;
1518   }
1519
1520   GST_INFO_OBJECT(camerasrc, "start capture - count %d, interval %d",
1521     camerasrc->cap_count, camerasrc->cap_interval);
1522
1523   ret = hal_camera_set_command(camerasrc->hal_handle,
1524     CAMERA_COMMAND_CAPTURE_COUNT, (void *)&camerasrc->cap_count);
1525   if (ret != CAMERA_ERROR_NONE)
1526     GST_WARNING_OBJECT(camerasrc, "set capture count failed 0x%x", ret);
1527
1528   if (camerasrc->cap_count > 1) {
1529     ret = hal_camera_set_command(camerasrc->hal_handle,
1530       CAMERA_COMMAND_CAPTURE_INTERVAL, (void *)&camerasrc->cap_interval);
1531     if (ret != CAMERA_ERROR_NONE)
1532       GST_WARNING_OBJECT(camerasrc, "set capture interval failed 0x%x", ret);
1533   }
1534
1535   ret = hal_camera_start_capture(camerasrc->hal_handle, _camera_capture_cb, camerasrc);
1536   if (ret != CAMERA_ERROR_NONE) {
1537     GST_ERROR_OBJECT(camerasrc, "start capture failed 0x%x", ret);
1538     return FALSE;
1539   }
1540
1541   camerasrc->mode = VIDEO_IN_MODE_CAPTURE;
1542
1543   GST_INFO_OBJECT(camerasrc, "CAPTURE STARTED!");
1544
1545   return TRUE;
1546 }
1547
1548
1549 static gboolean gst_tizencamerasrc_capture_stop(GstTizenCameraSrc *camerasrc)
1550 {
1551   int ret = CAMERA_ERROR_NONE;
1552
1553   GST_INFO_OBJECT(camerasrc, "ENTERED - mode %d", camerasrc->mode);
1554
1555   if (camerasrc->mode == VIDEO_IN_MODE_CAPTURE) {
1556     ret = hal_camera_stop_capture(camerasrc->hal_handle);
1557     if (ret != CAMERA_ERROR_NONE) {
1558       GST_ERROR_OBJECT(camerasrc, "hal_camera_stop_capture failed 0x%x", ret);
1559       return FALSE;
1560     }
1561
1562     g_mutex_lock(&camerasrc->preview_control.lock);
1563     camerasrc->mode = VIDEO_IN_MODE_PREVIEW;
1564     g_cond_signal(&camerasrc->preview_control.cond);
1565     g_mutex_unlock(&camerasrc->preview_control.lock);
1566
1567     GST_INFO_OBJECT(camerasrc, "CAPTURE STOPPED!");
1568
1569     return TRUE;
1570   } else {
1571     GST_WARNING_OBJECT(camerasrc, "Wrong state[%d]!", camerasrc->mode);
1572     return FALSE;
1573   }
1574 }
1575
1576
1577 static GstFlowReturn gst_tizencamerasrc_read_preview(GstTizenCameraSrc *camerasrc, GstBuffer **buffer)
1578 {
1579   int preview_check_count = 0;
1580   gint64 end_time;
1581   BufferControl *control = &camerasrc->preview_control;
1582
1583   GST_DEBUG_OBJECT(camerasrc, "check preview buffer list");
1584
1585   g_mutex_lock(&control->lock);
1586
1587   while (g_queue_is_empty(camerasrc->preview_buffer_list)) {
1588     GST_DEBUG_OBJECT(camerasrc, "buffer list is empty. waiting...");
1589
1590     end_time = g_get_monotonic_time () + _BUFFER_WAIT_TIMEOUT;
1591     if (g_cond_wait_until(&control->cond, &control->lock, end_time)) {
1592       GST_DEBUG_OBJECT(camerasrc, "Signal received. Retry...");
1593       continue;
1594     }
1595
1596     if (camerasrc->hal_error_code != CAMERA_ERROR_NONE) {
1597       GST_WARNING_OBJECT(camerasrc, "buffer timeout and error[0x%x]", camerasrc->hal_error_code);
1598       break;
1599     }
1600
1601     if (camerasrc->is_flushing) {
1602       g_mutex_unlock(&control->lock);
1603       GST_WARNING_OBJECT(camerasrc, "FLUSHING now");
1604       goto _FLUSHING;
1605     }
1606
1607     if (camerasrc->mode == VIDEO_IN_MODE_CAPTURE)
1608       GST_WARNING_OBJECT(camerasrc, "capture mode now.");
1609     else
1610       preview_check_count++;
1611
1612     if (camerasrc->empty_buffer_timeout > 0 &&
1613         preview_check_count * _BUFFER_WAIT_TIMEOUT >= camerasrc->empty_buffer_timeout * 1000) {
1614       GST_ERROR_OBJECT(camerasrc, "wait buffer failed for [%d]ms", camerasrc->empty_buffer_timeout);
1615       break;
1616     }
1617
1618     GST_WARNING_OBJECT(camerasrc, "preview buffer timeout[%d]usec, retry[%d]",
1619       _BUFFER_WAIT_TIMEOUT, preview_check_count);
1620   }
1621
1622   *buffer = g_queue_pop_head(camerasrc->preview_buffer_list);
1623
1624   g_mutex_unlock(&control->lock);
1625
1626   if (*buffer == NULL) {
1627     GST_ERROR_OBJECT(camerasrc, "buffer is NULL (HAL error 0x%x)", camerasrc->hal_error_code);
1628
1629     if (camerasrc->hal_error_code == CAMERA_ERROR_NONE)
1630       gst_tizencamerasrc_error_handler(camerasrc, CAMERA_ERROR_DEVICE_READ);
1631
1632     return GST_FLOW_ERROR;
1633   }
1634
1635   if (camerasrc->is_flushing)
1636     goto _FLUSHING;
1637
1638   if (camerasrc->firsttime)
1639     camerasrc->firsttime = FALSE;
1640
1641   GST_DEBUG_OBJECT(camerasrc, "preview buffer %p", *buffer);
1642
1643   return GST_FLOW_OK;
1644
1645 _FLUSHING:
1646   if (*buffer) {
1647     gst_buffer_unref(*buffer);
1648     *buffer = NULL;
1649   }
1650
1651   GST_WARNING_OBJECT(camerasrc, "return GST_FLOW_FLUSHING");
1652
1653   return GST_FLOW_FLUSHING;
1654 }
1655
1656
1657 static GstFlowReturn gst_tizencamerasrc_read(GstTizenCameraSrc *camerasrc, GstBuffer **buffer)
1658 {
1659   GstFlowReturn ret = GST_FLOW_OK;
1660
1661   switch (camerasrc->mode) {
1662   case VIDEO_IN_MODE_PREVIEW:
1663   case VIDEO_IN_MODE_CAPTURE:
1664   case VIDEO_IN_MODE_VIDEO:
1665     GST_DEBUG_OBJECT(camerasrc, "gst_tizencamerasrc_read_preview");
1666     ret = gst_tizencamerasrc_read_preview(camerasrc, buffer);
1667     break;
1668   case VIDEO_IN_MODE_NONE:
1669   default:
1670     ret = GST_FLOW_ERROR;
1671     GST_ERROR_OBJECT (camerasrc, "can't reach statement.[camerasrc->mode=%d]", camerasrc->mode);
1672     break;
1673   }
1674
1675   if (buffer && (!(*buffer) || !GST_IS_BUFFER(*buffer))) {
1676     /* To avoid seg fault, make dummy buffer. */
1677     GST_WARNING_OBJECT (camerasrc, "Make a dummy buffer");
1678     *buffer = gst_buffer_new();
1679   }
1680
1681   return ret;
1682 }
1683
1684
1685 static gboolean gst_tizencamerasrc_get_timeinfo(GstTizenCameraSrc *camerasrc, GstBuffer *buffer)
1686 {
1687   int fps_nu = 0;
1688   int fps_de = 0;
1689   GstClock *clock = NULL;
1690   GstClockTime timestamp = GST_CLOCK_TIME_NONE;
1691   GstClockTime duration = GST_CLOCK_TIME_NONE;
1692
1693   if (!camerasrc || !buffer) {
1694     GST_WARNING_OBJECT (camerasrc, "Invalid pointer [hadle:%p, buffer:%p]", camerasrc, buffer);
1695     return FALSE;
1696   }
1697
1698   /* timestamps, LOCK to get clock and base time. */
1699   clock = GST_ELEMENT_CLOCK(camerasrc);
1700   if (clock) {
1701     /* the time now is the time of the clock minus the base time */
1702     gst_object_ref(clock);
1703     timestamp = gst_clock_get_time(clock) - GST_ELEMENT(camerasrc)->base_time;
1704     gst_object_unref(clock);
1705
1706     /* if we have a framerate adjust timestamp for frame latency */
1707     if (camerasrc->fps_auto) {
1708       /* auto fps mode */
1709       duration = GST_CLOCK_TIME_NONE;
1710     } else {
1711       if (camerasrc->fps <= 0) {
1712         /*if fps is zero, auto fps mode*/
1713         fps_nu = 0;
1714         fps_de = 1;
1715       } else {
1716         fps_nu = 1;
1717         fps_de = camerasrc->fps;
1718       }
1719
1720       if (fps_nu > 0 && fps_de > 0) {
1721         duration = gst_util_uint64_scale_int(GST_SECOND, fps_nu, fps_de);
1722       }
1723     }
1724
1725     /* set default duration if duration is NONE : 30 fps */
1726     if (duration == GST_CLOCK_TIME_NONE) {
1727       duration = gst_util_uint64_scale_int(GST_SECOND, 1, 30);
1728     }
1729   } else {
1730     /* no clock, can't set timestamps */
1731     timestamp = GST_CLOCK_TIME_NONE;
1732   }
1733
1734   GST_BUFFER_TIMESTAMP(buffer) = timestamp;
1735   GST_BUFFER_DURATION(buffer) = duration;
1736
1737   GST_LOG_OBJECT(camerasrc, "timestamp [%"GST_TIME_FORMAT" dur %" GST_TIME_FORMAT "]",
1738     GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)),
1739     GST_TIME_ARGS(GST_BUFFER_DURATION(buffer)));
1740
1741   return TRUE;
1742 }
1743
1744
1745 /* Gstreamer general functions */
1746 static gboolean gst_tizencamerasrc_src_start(GstBaseSrc *src)
1747 {
1748   int ret = TRUE;
1749   GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC (src);
1750
1751   GST_DEBUG_OBJECT(camerasrc, "ENTERED");
1752
1753   camerasrc->firsttime = TRUE;
1754   /* 'gst_tizencamerasrc_set_caps' will call gst_tizencamerasrc_start(). So skip to call it. */
1755   /*ret = gst_tizencamerasrc_start(camerasrc);*/
1756
1757   GST_DEBUG_OBJECT(camerasrc, "LEAVE");
1758
1759   return ret;
1760 }
1761
1762
1763 static gboolean gst_tizencamerasrc_src_stop(GstBaseSrc *src)
1764 {
1765   int ret = 0;
1766   GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC(src);
1767
1768   GST_DEBUG_OBJECT (camerasrc, "ENTERED");
1769
1770   ret = gst_tizencamerasrc_stop(camerasrc);
1771
1772   GST_DEBUG_OBJECT(camerasrc, "LEAVE");
1773
1774   return ret;
1775 }
1776
1777
1778 static GstFlowReturn gst_tizencamerasrc_src_create(GstPushSrc *src, GstBuffer **buffer)
1779 {
1780   GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC (src);
1781   GstFlowReturn ret;
1782
1783   GST_LOG_OBJECT(camerasrc, "ENTERED");
1784
1785   ret = gst_tizencamerasrc_read(camerasrc, buffer);
1786
1787   GST_LOG_OBJECT (camerasrc, "LEAVE");
1788
1789   return ret;
1790 }
1791
1792
1793 static void gst_tizencamerasrc_set_property(GObject *object, guint prop_id,
1794                                        const GValue *value, GParamSpec *pspec)
1795 {
1796   int ret = 0;
1797   int tmp = 0;
1798   GstTizenCameraSrc *camerasrc = NULL;
1799
1800   g_return_if_fail(GST_IS_TIZENCAMERA_SRC(object));
1801   camerasrc = GST_TIZENCAMERA_SRC(object);
1802
1803   switch (prop_id) {
1804   case ARG_CAMERA_ID:
1805     camerasrc->camera_id = g_value_get_int(value);
1806     break;
1807   case ARG_DEVICE_NAME:
1808     g_free(camerasrc->device_name);
1809     camerasrc->device_name = g_value_dup_string(value);
1810     GST_INFO_OBJECT(camerasrc, "Set device name: %s", camerasrc->device_name);
1811     break;
1812   case ARG_DEVICE_BUS:
1813     camerasrc->device_bus = g_value_get_int(value);
1814     GST_INFO_OBJECT(camerasrc, "Set device bus: %d", camerasrc->device_bus);
1815     ret = hal_camera_set_command(camerasrc->hal_handle, CAMERA_COMMAND_DEVICE_BUS, (void *)&camerasrc->device_bus);
1816     break;
1817   case ARG_DEVICE_PORT:
1818     g_free(camerasrc->device_port);
1819     camerasrc->device_port = g_value_dup_string(value);
1820     GST_INFO_OBJECT(camerasrc, "Set device port: %s", camerasrc->device_port);
1821     ret = hal_camera_set_command(camerasrc->hal_handle, CAMERA_COMMAND_DEVICE_PORT, (void *)camerasrc->device_port);
1822     break;
1823   case ARG_HAL_NAME:
1824     g_free(camerasrc->hal_name);
1825     camerasrc->hal_name = g_value_dup_string(value);
1826
1827     /* reset camera hal interface handle */
1828     if (camerasrc->hal_handle) {
1829       GST_INFO_OBJECT(camerasrc, "Reset HAL intf: %p", camerasrc->hal_handle);
1830       hal_camera_deinit(camerasrc->hal_handle);
1831       camerasrc->hal_handle = NULL;
1832     }
1833
1834     if (camerasrc->hal_name && strlen(camerasrc->hal_name) == 0) {
1835       GST_WARNING_OBJECT(camerasrc, "The empty string for HAL name");
1836       g_free(camerasrc->hal_name);
1837       camerasrc->hal_name = NULL;
1838     }
1839
1840     GST_WARNING_OBJECT(camerasrc, "Set HAL name: %s", camerasrc->hal_name);
1841
1842     ret = hal_camera_init(camerasrc->hal_name, &camerasrc->hal_handle);
1843     if (ret == CAMERA_ERROR_NONE) {
1844       ret = hal_camera_get_device_info_list(camerasrc->hal_handle, camerasrc->device_info);
1845       GST_WARNING_OBJECT(camerasrc, "HAL device info: 0x%x, count: %d", ret, camerasrc->device_info->count);
1846
1847       ret = hal_camera_add_message_callback(camerasrc->hal_handle, __camera_hal_message_callback, camerasrc, &camerasrc->msg_cb_id);
1848       GST_WARNING_OBJECT(camerasrc, "HAL message cb: 0x%x, id: %d", ret, camerasrc->msg_cb_id);
1849     } else {
1850       GST_ERROR_OBJECT(camerasrc, "hal_camera_init failed: 0x%x", ret);
1851     }
1852     break;
1853   case ARG_VFLIP:
1854     camerasrc->vflip = g_value_get_boolean(value);
1855     GST_INFO_OBJECT(camerasrc, "Set VFLIP : %d", camerasrc->vflip);
1856     break;
1857   case ARG_HFLIP:
1858     camerasrc->hflip = g_value_get_boolean(value);
1859     GST_INFO_OBJECT(camerasrc, "Set HFLIP : %d", camerasrc->hflip);
1860     break;
1861   case ARG_HIGH_SPEED_FPS:
1862     camerasrc->high_speed_fps = g_value_get_int(value);
1863     GST_INFO_OBJECT(camerasrc, "Set HIGH SPEED FPS: %d", camerasrc->high_speed_fps);
1864     break;
1865   case ARG_AUTO_FPS:
1866     camerasrc->fps_auto = g_value_get_boolean(value);
1867     GST_INFO_OBJECT(camerasrc, "Set AUTO_FPS: %d", camerasrc->fps_auto);
1868     break;
1869   case ARG_EXTRA_PREVIEW:
1870     camerasrc->extra_preview = g_value_get_boolean(value);
1871     GST_INFO_OBJECT(camerasrc, "Enable extra preview: %d", camerasrc->extra_preview);
1872     if (camerasrc->extra_preview)
1873       ret = hal_camera_set_extra_preview_frame_cb(camerasrc->hal_handle, __camera_extra_preview_frame_cb, camerasrc);
1874     else
1875       ret = hal_camera_unset_extra_preview_frame_cb(camerasrc->hal_handle);
1876     GST_INFO_OBJECT(camerasrc, "extra preview %s result: 0x%x",
1877       camerasrc->extra_preview ? "set" : "unset", ret);
1878     break;
1879   case ARG_LIVE_BUFFER_MAX:
1880     camerasrc->live_buffer_max = g_value_get_int(value);
1881     GST_WARNING_OBJECT(camerasrc, "live buffer max %d", camerasrc->live_buffer_max);
1882     break;
1883   case ARG_LIVE_BUFFER_MAX_RAW:
1884     camerasrc->live_buffer_max_raw = g_value_get_int(value);
1885     GST_WARNING_OBJECT(camerasrc, "live buffer max for raw format %d", camerasrc->live_buffer_max_raw);
1886     break;
1887   case ARG_EMPTY_BUFFER_TIMEOUT:
1888     camerasrc->empty_buffer_timeout = g_value_get_int(value);
1889     GST_INFO_OBJECT(camerasrc, "empty buffer timeout %dms", camerasrc->empty_buffer_timeout);
1890     break;
1891   case ARG_CAPTURE_FOURCC:
1892     camerasrc->cap_fourcc = g_value_get_uint(value);
1893     gst_tizencamerasrc_set_capture_format(camerasrc);
1894     break;
1895   case ARG_CAPTURE_WIDTH:
1896     camerasrc->cap_width_tmp = g_value_get_int(value);
1897     break;
1898   case ARG_CAPTURE_HEIGHT:
1899     camerasrc->cap_height_tmp = g_value_get_int(value);
1900     gst_tizencamerasrc_set_capture_format(camerasrc);
1901     break;
1902   case ARG_CAPTURE_INTERVAL:
1903     camerasrc->cap_interval = g_value_get_int(value);
1904     GST_INFO_OBJECT(camerasrc, "Set capture interval: %d", camerasrc->cap_interval);
1905     break;
1906   case ARG_CAPTURE_COUNT:
1907     tmp = g_value_get_int(value);
1908     camerasrc->cap_count = tmp;
1909     camerasrc->cap_count_reverse = tmp;
1910     GST_INFO_OBJECT(camerasrc, "Set capture count: %d", camerasrc->cap_count_reverse);
1911     break;
1912   case ARG_CAPTURE_QUALITY:
1913     camerasrc->cap_quality = g_value_get_int(value);
1914     GST_INFO_OBJECT(camerasrc, "Set capture quality : %d", camerasrc->cap_quality);
1915     break;
1916   case ARG_VIDEO_WIDTH:
1917     camerasrc->video_width = g_value_get_int(value);
1918     GST_INFO_OBJECT(camerasrc, "video width %d", camerasrc->video_width);
1919     break;
1920   case ARG_VIDEO_HEIGHT:
1921     camerasrc->video_height = g_value_get_int(value);
1922     GST_INFO_OBJECT(camerasrc, "video height %d", camerasrc->video_height);
1923     break;
1924   case ARG_VIDEO_FPS:
1925     camerasrc->video_fps = g_value_get_int(value);
1926     GST_INFO_OBJECT(camerasrc, "video fps %d", camerasrc->video_fps);
1927     break;
1928   case ARG_RECORDING_HINT:
1929     camerasrc->recording_hint = g_value_get_boolean(value);
1930
1931     GST_INFO_OBJECT(camerasrc, "recording-hint %d", camerasrc->recording_hint);
1932
1933     if (camerasrc->recording_hint)
1934       gst_tizencamerasrc_set_video_format(camerasrc);
1935     break;
1936   case ARG_BITRATE:
1937     camerasrc->bitrate = g_value_get_int(value);
1938     ret = hal_camera_set_command(camerasrc->hal_handle, CAMERA_COMMAND_BITRATE, (void *)&camerasrc->bitrate);
1939     GST_INFO_OBJECT(camerasrc, "Set bitrate : %d, ret 0x%x", camerasrc->bitrate, ret);
1940     break;
1941   case ARG_GOP_INTERVAL:
1942     camerasrc->gop_interval = g_value_get_int(value);
1943     ret = hal_camera_set_command(camerasrc->hal_handle, CAMERA_COMMAND_GOP_INTERVAL, (void *)&camerasrc->gop_interval);
1944     GST_INFO_OBJECT(camerasrc, "Set GOP interval : %d, ret 0x%x", camerasrc->gop_interval, ret);
1945     break;
1946   default:
1947     G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
1948     break;
1949   }
1950
1951   return;
1952 }
1953
1954
1955 static void gst_tizencamerasrc_get_property(GObject *object, guint prop_id,
1956                                        GValue *value, GParamSpec *pspec)
1957 {
1958   GstTizenCameraSrc *camerasrc;
1959
1960   g_return_if_fail(GST_IS_TIZENCAMERA_SRC(object));
1961   camerasrc = GST_TIZENCAMERA_SRC(object);
1962
1963   switch (prop_id) {
1964   case ARG_CAMERA_ID:
1965     g_value_set_int(value, camerasrc->camera_id);
1966     break;
1967   case ARG_DEVICE_NAME:
1968     g_value_set_string(value, camerasrc->device_name);
1969     break;
1970   case ARG_DEVICE_BUS:
1971     g_value_set_int(value, camerasrc->device_bus);
1972     break;
1973   case ARG_DEVICE_PORT:
1974     g_value_set_string(value, camerasrc->device_port);
1975     break;
1976   case ARG_HAL_NAME:
1977     g_value_set_string(value, camerasrc->hal_name);
1978     break;
1979   case ARG_VFLIP:
1980     g_value_set_boolean(value, camerasrc->vflip);
1981     break;
1982   case ARG_HFLIP:
1983     g_value_set_boolean(value, camerasrc->hflip);
1984     break;
1985   case ARG_HIGH_SPEED_FPS:
1986     g_value_set_int(value, camerasrc->high_speed_fps);
1987     break;
1988   case ARG_AUTO_FPS:
1989     g_value_set_boolean(value, camerasrc->fps_auto);
1990     break;
1991   case ARG_EXTRA_PREVIEW:
1992     g_value_set_boolean(value, camerasrc->extra_preview);
1993     break;
1994   case ARG_LIVE_BUFFER_MAX:
1995     g_value_set_int(value, camerasrc->live_buffer_max);
1996     break;
1997   case ARG_LIVE_BUFFER_MAX_RAW:
1998     g_value_set_int(value, camerasrc->live_buffer_max_raw);
1999     break;
2000   case ARG_EMPTY_BUFFER_TIMEOUT:
2001     g_value_set_int(value, camerasrc->empty_buffer_timeout);
2002     break;
2003   case ARG_BUFFER_QUARK:
2004     if (camerasrc->buffer_quark == _DEFAULT_BUFFER_QUARK) {
2005       camerasrc->buffer_quark = g_quark_from_static_string("tizencamerabuffer");
2006       GST_INFO_OBJECT(camerasrc, "quark for buffer [%u]", camerasrc->buffer_quark);
2007     }
2008     g_value_set_uint(value, camerasrc->buffer_quark);
2009     break;
2010   case ARG_CAPTURE_FOURCC:
2011     g_value_set_uint(value, camerasrc->cap_fourcc);
2012     break;
2013   case ARG_CAPTURE_WIDTH:
2014     g_value_set_int(value, camerasrc->cap_width);
2015     break;
2016   case ARG_CAPTURE_HEIGHT:
2017     g_value_set_int(value, camerasrc->cap_height);
2018     break;
2019   case ARG_CAPTURE_INTERVAL:
2020     g_value_set_int(value, camerasrc->cap_interval);
2021     break;
2022   case ARG_CAPTURE_COUNT:
2023     g_value_set_int(value, camerasrc->cap_count);
2024     break;
2025   case ARG_CAPTURE_QUALITY:
2026     g_value_set_int(value, camerasrc->cap_quality);
2027     GST_INFO("GET capture quality : %d", camerasrc->cap_quality);
2028     break;
2029   case ARG_CAPTURE_PROVIDE_EXIF:
2030     g_value_set_boolean(value, camerasrc->cap_provide_exif);
2031     GST_INFO("Is Exif provided? : %d", camerasrc->cap_provide_exif);
2032     break;
2033   case ARG_VIDEO_WIDTH:
2034     g_value_set_int(value, camerasrc->video_width);
2035     break;
2036   case ARG_VIDEO_HEIGHT:
2037     g_value_set_int(value, camerasrc->video_height);
2038     break;
2039   case ARG_VIDEO_FPS:
2040     g_value_set_int(value, camerasrc->video_fps);
2041     break;
2042   case ARG_RECORDING_HINT:
2043     g_value_set_boolean(value, camerasrc->recording_hint);
2044     break;
2045   case ARG_BITRATE:
2046     g_value_set_int(value, camerasrc->bitrate);
2047     break;
2048   case ARG_GOP_INTERVAL:
2049     g_value_set_int(value, camerasrc->gop_interval);
2050     break;
2051   default:
2052     G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
2053     break;
2054   }
2055
2056   return;
2057 }
2058
2059
2060 static GstStateChangeReturn gst_tizencamerasrc_change_state(GstElement *element, GstStateChange transition)
2061 {
2062   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
2063   GstTizenCameraSrc *camerasrc;
2064   camerasrc = GST_TIZENCAMERA_SRC (element);
2065
2066   switch (transition) {
2067   case GST_STATE_CHANGE_NULL_TO_READY:
2068     GST_INFO_OBJECT(camerasrc, "GST CAMERA SRC: NULL -> READY");
2069     GST_INFO("    gst_tizencamerasrc_create");
2070     if (!gst_tizencamerasrc_create(camerasrc)){
2071       goto statechange_failed;
2072     }
2073     break;
2074   case GST_STATE_CHANGE_READY_TO_PAUSED:
2075     GST_INFO_OBJECT(camerasrc, "GST CAMERA SRC: READY -> PAUSED");
2076     ret = GST_STATE_CHANGE_NO_PREROLL;
2077     break;
2078   case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
2079     GST_INFO_OBJECT(camerasrc, "GST CAMERA SRC: PAUSED -> PLAYING");
2080     break;
2081   default:
2082     break;
2083   }
2084
2085   ret = GST_ELEMENT_CLASS(gst_tizencamerasrc_parent_class)->change_state(element, transition);
2086   if (ret == GST_STATE_CHANGE_FAILURE){
2087     return ret;
2088   }
2089
2090   switch (transition) {
2091   case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
2092     GST_INFO_OBJECT(camerasrc, "GST CAMERA SRC: PLAYING -> PAUSED");
2093     ret = GST_STATE_CHANGE_NO_PREROLL;
2094     break;
2095   case GST_STATE_CHANGE_PAUSED_TO_READY:
2096     GST_INFO_OBJECT(camerasrc, "GST CAMERA SRC: PAUSED -> READY");
2097     break;
2098   case GST_STATE_CHANGE_READY_TO_NULL:
2099     GST_INFO_OBJECT(camerasrc, "GST CAMERA SRC: READY -> NULL");
2100     GST_INFO("    gst_tizencamerasrc_destroy");
2101     if (!gst_tizencamerasrc_destroy(camerasrc)){
2102       goto statechange_failed;
2103     }
2104     break;
2105   default:
2106     break;
2107   }
2108
2109   return ret;
2110
2111  statechange_failed:
2112   /* subclass must post a meaningful error message */
2113   GST_ERROR_OBJECT(camerasrc, "state change failed");
2114
2115   return GST_STATE_CHANGE_FAILURE;
2116 }
2117
2118
2119 static void gst_tizencamerasrc_finalize(GObject *object)
2120 {
2121   int i = 0;
2122   int ret = 0;
2123   GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC(object);
2124
2125   GST_INFO_OBJECT(camerasrc, "ENTERED");
2126
2127   ret = hal_camera_deinit(camerasrc->hal_handle);
2128   if (ret != CAMERA_ERROR_NONE)
2129     GST_ERROR_OBJECT(camerasrc, "hal_camera_deinit failed 0x%x", ret);
2130
2131   camerasrc->hal_handle = NULL;
2132
2133   g_cond_clear(&camerasrc->preview_control.cond);
2134   g_mutex_clear(&camerasrc->preview_control.lock);
2135   g_cond_clear(&camerasrc->extra_preview_control.cond);
2136   g_mutex_clear(&camerasrc->extra_preview_control.lock);
2137   SAFE_FREE_GQUEUE(camerasrc->preview_buffer_list);
2138   g_cond_clear(&camerasrc->video_control.cond);
2139   g_mutex_clear(&camerasrc->video_control.lock);
2140
2141   if (camerasrc->allocator) {
2142     gst_object_unref(camerasrc->allocator);
2143     camerasrc->allocator = NULL;
2144   }
2145
2146   if (camerasrc->video_caps) {
2147     gst_caps_unref(camerasrc->video_caps);
2148     camerasrc->video_caps = NULL;
2149   }
2150
2151   for (i = 0 ; i < EXTRA_PREVIEW_STREAM_MAX ; i++) {
2152     if (camerasrc->extra_caps[i]) {
2153       gst_caps_unref(camerasrc->extra_caps[i]);
2154       camerasrc->extra_caps[i] = NULL;
2155     }
2156   }
2157
2158   g_free(camerasrc->hal_name);
2159   g_free(camerasrc->device_info);
2160   g_free(camerasrc->device_name);
2161   g_free(camerasrc->device_port);
2162
2163   GST_INFO_OBJECT(camerasrc, "LEAVE");
2164
2165   if (G_OBJECT_CLASS (gst_tizencamerasrc_parent_class)->finalize)
2166     G_OBJECT_CLASS(gst_tizencamerasrc_parent_class)->finalize(object);
2167
2168   return;
2169 }
2170
2171
2172 void gst_tizencamerasrc_set_capture_command(GstTizenCameraSrc *camerasrc, GstCameraControlCaptureCommand cmd)
2173 {
2174   if (camerasrc == NULL) {
2175     GST_ERROR_OBJECT(camerasrc, "camerasrc is NULL");
2176     return;
2177   }
2178
2179   GST_INFO_OBJECT(camerasrc, "ENTERED");
2180
2181   if (cmd == GST_CAMERA_CONTROL_CAPTURE_COMMAND_START)
2182     gst_tizencamerasrc_capture_start(camerasrc);
2183   else if (cmd == GST_CAMERA_CONTROL_CAPTURE_COMMAND_STOP)
2184     gst_tizencamerasrc_capture_stop(camerasrc);
2185   else
2186     GST_WARNING_OBJECT(camerasrc, "not supported command %d", cmd);
2187
2188   GST_INFO_OBJECT(camerasrc, "LEAVE");
2189
2190   return;
2191 }
2192
2193
2194 void gst_tizencamerasrc_set_record_command(GstTizenCameraSrc *camerasrc, GstCameraControlRecordCommand cmd)
2195 {
2196   int ret = CAMERA_ERROR_NONE;
2197
2198   if (camerasrc == NULL) {
2199     GST_ERROR_OBJECT(camerasrc, "camerasrc is NULL");
2200     return;
2201   }
2202
2203   GST_INFO_OBJECT(camerasrc, "ENTERED - cmd %d", cmd);
2204
2205   if (cmd == GST_CAMERA_CONTROL_RECORD_COMMAND_START) {
2206     camerasrc->video_control.live_buffers = 0;
2207     camerasrc->video_control.is_first_frame = TRUE;
2208     if (camerasrc->video_caps) {
2209       gst_caps_unref(camerasrc->video_caps);
2210       camerasrc->video_caps = NULL;
2211     }
2212     ret = hal_camera_start_record(camerasrc->hal_handle, __camera_video_frame_cb, camerasrc);
2213   } else if (cmd == GST_CAMERA_CONTROL_RECORD_COMMAND_STOP) {
2214     ret = hal_camera_stop_record(camerasrc->hal_handle);
2215   } else {
2216     GST_WARNING_OBJECT(camerasrc, "not supported command %d", cmd);
2217   }
2218
2219   GST_INFO_OBJECT(camerasrc, "LEAVE - ret[0x%x]", ret);
2220
2221   return;
2222 }
2223
2224
2225 gboolean gst_tizencamerasrc_set_user_buffer_fd(GstTizenCameraSrc *camerasrc, int *fds, int number)
2226 {
2227   int ret = CAMERA_ERROR_NONE;
2228
2229   if (camerasrc == NULL) {
2230     GST_ERROR_OBJECT(camerasrc, "camerasrc is NULL");
2231     return FALSE;
2232   }
2233
2234   GST_INFO_OBJECT(camerasrc, "ENTERED - number %d", number);
2235
2236   ret = hal_camera_set_user_buffer_fd(camerasrc->hal_handle, fds, number);
2237
2238   GST_INFO_OBJECT(camerasrc, "LEAVE - ret 0x%x", ret);
2239
2240   return (ret == CAMERA_ERROR_NONE ? TRUE : FALSE);
2241 }
2242
2243
2244 static gboolean
2245 gst_tizencamerasrc_negotiate (GstBaseSrc * basesrc)
2246 {
2247   GstCaps *thiscaps;
2248   GstCaps *caps = NULL;
2249   GstCaps *peercaps = NULL;
2250   gboolean result = FALSE;
2251   GstStructure *s;
2252   GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC(basesrc);
2253
2254   GST_INFO_OBJECT(camerasrc, "ENTERED");
2255   /* first see what is possible on our source pad */
2256   thiscaps = gst_pad_query_caps (GST_BASE_SRC_PAD (basesrc), NULL);
2257   GST_DEBUG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
2258
2259   /* nothing or anything is allowed, we're done */
2260   if (thiscaps == NULL || gst_caps_is_any (thiscaps))
2261     goto no_nego_needed;
2262
2263   /* get the peer caps */
2264   peercaps = gst_pad_peer_query_caps (GST_BASE_SRC_PAD (basesrc), NULL);
2265   GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
2266   //LOG_CAPS (basesrc, peercaps);
2267   if (peercaps && !gst_caps_is_any (peercaps)) {
2268     GstCaps *icaps = NULL;
2269     int i;
2270
2271     /* Prefer the first caps we are compatible with that the peer proposed */
2272     for (i = 0; i < gst_caps_get_size (peercaps); i++) {
2273       /* get intersection */
2274       GstCaps *ipcaps = gst_caps_copy_nth (peercaps, i);
2275
2276       GST_DEBUG_OBJECT (basesrc, "peer: %" GST_PTR_FORMAT, ipcaps);
2277       icaps = gst_caps_intersect (thiscaps, ipcaps);
2278       gst_caps_unref (ipcaps);
2279
2280       /*s = gst_caps_get_structure (icaps, 0);
2281       gst_structure_get_fourcc(s, "format", &camerasrc->fourcc);
2282       if ((camerasrc->fourcc == GST_MAKE_FOURCC('S','N','1','2')) ||
2283         (camerasrc->fourcc == GST_MAKE_FOURCC('S','T','1','2'))) {
2284         break;
2285       }*/
2286       if (!gst_caps_is_empty (icaps))
2287         break;
2288
2289       gst_caps_unref (icaps);
2290       icaps = NULL;
2291     }
2292
2293     GST_DEBUG_OBJECT (basesrc, "intersect: %" GST_PTR_FORMAT, icaps);
2294     if (icaps) {
2295       /* If there are multiple intersections pick the one with the smallest
2296       * resolution strictly bigger then the first peer caps */
2297       if (gst_caps_get_size (icaps) > 1) {
2298         s = gst_caps_get_structure (peercaps, 0);
2299         int best = 0;
2300         int twidth, theight;
2301         int width = G_MAXINT, height = G_MAXINT;
2302
2303         if (gst_structure_get_int (s, "width", &twidth)
2304           && gst_structure_get_int (s, "height", &theight)) {
2305
2306           /* Walk the structure backwards to get the first entry of the
2307           * smallest resolution bigger (or equal to) the preferred resolution)
2308           */
2309           for (i = gst_caps_get_size (icaps) - 1; i >= 0; i--) {
2310             GstStructure *is = gst_caps_get_structure (icaps, i);
2311             int w, h;
2312
2313             if (gst_structure_get_int (is, "width", &w)
2314               && gst_structure_get_int (is, "height", &h)) {
2315               if (w >= twidth && w <= width && h >= theight && h <= height) {
2316                 width = w;
2317                 height = h;
2318                 best = i;
2319               }
2320             }
2321           }
2322         }
2323
2324         caps = gst_caps_copy_nth (icaps, best);
2325         gst_caps_unref (icaps);
2326       } else {
2327         caps = icaps;
2328       }
2329     }
2330     gst_caps_unref (thiscaps);
2331     gst_caps_unref (peercaps);
2332   } else {
2333     /* no peer or peer have ANY caps, work with our own caps then */
2334     caps = thiscaps;
2335   }
2336   if (caps) {
2337         caps = gst_caps_fixate(caps);
2338
2339     /* now fixate */
2340     if (!gst_caps_is_empty (caps)) {
2341       GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps);
2342
2343       if (gst_caps_is_any (caps)) {
2344         /* hmm, still anything, so element can do anything and
2345         * nego is not needed */
2346         result = TRUE;
2347       } else if (gst_caps_is_fixed (caps)) {
2348         /* yay, fixed caps, use those then */
2349           result = gst_tizencamerasrc_set_caps(basesrc, caps);
2350       }
2351     }
2352     gst_caps_unref (caps);
2353   }
2354   return result;
2355
2356 no_nego_needed:
2357   {
2358     GST_DEBUG_OBJECT (basesrc, "no negotiation needed");
2359     if (thiscaps)
2360       gst_caps_unref (thiscaps);
2361     return TRUE;
2362   }
2363 }
2364
2365
2366 static GstCaps *gst_tizencamerasrc_get_caps(GstBaseSrc *src, GstCaps *filter)
2367 {
2368   GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC(src);
2369   GstCaps *ret = NULL;
2370
2371   GST_DEBUG_OBJECT(camerasrc, "ENTERED");
2372
2373   if (camerasrc->mode == VIDEO_IN_MODE_NONE) {
2374     GST_INFO_OBJECT(camerasrc, "Just return template caps.");
2375     GST_DEBUG_OBJECT(camerasrc, "LEAVE");
2376
2377     ret = gst_pad_get_pad_template_caps(GST_BASE_SRC_PAD(camerasrc));
2378     return filter ? gst_caps_intersect(ret, filter) : gst_caps_copy(ret);
2379   }
2380
2381   /*FIXME: Using "VIDIOC_ENUM_FMT".*/
2382   ret = gst_caps_copy(gst_pad_get_pad_template_caps(GST_BASE_SRC_PAD(camerasrc)));
2383
2384   if (filter != NULL) {
2385       gst_caps_take(&ret, gst_caps_intersect(ret, filter));
2386   }
2387
2388   GST_INFO_OBJECT(camerasrc, "probed caps: %p", ret);
2389   GST_DEBUG_OBJECT(camerasrc, "LEAVE");
2390
2391   return ret;
2392 }
2393
2394
2395 static gboolean __gst_tizencamerasrc_get_raw_pixel_info(int fourcc, camera_pixel_format_e *pix_format)
2396 {
2397   if (pix_format == NULL) {
2398     GST_ERROR("NULL pointer");
2399     return FALSE;
2400   }
2401
2402   switch (fourcc) {
2403   case GST_MAKE_FOURCC('I','4','2','0'):
2404   case GST_MAKE_FOURCC('S','4','2','0'):
2405     *pix_format = CAMERA_PIXEL_FORMAT_I420;;
2406     break;
2407   case GST_MAKE_FOURCC('Y','V','1','2'):
2408     *pix_format = CAMERA_PIXEL_FORMAT_YV12;
2409     break;
2410   case GST_MAKE_FOURCC('Y','U','Y','V'):
2411   case GST_MAKE_FOURCC('Y','U','Y','2'):
2412   case GST_MAKE_FOURCC('S','U','Y','V'):
2413   case GST_MAKE_FOURCC('S','U','Y','2'):
2414     *pix_format = CAMERA_PIXEL_FORMAT_YUYV;
2415     break;
2416   case GST_MAKE_FOURCC('U','Y','V','Y'):
2417   case GST_MAKE_FOURCC('S','Y','V','Y'):
2418     *pix_format = CAMERA_PIXEL_FORMAT_UYVY;
2419     break;
2420   case GST_MAKE_FOURCC('N','V','1','2'):
2421   case GST_MAKE_FOURCC('S','N','1','2'):
2422     *pix_format = CAMERA_PIXEL_FORMAT_NV12;
2423     break;
2424   case GST_MAKE_FOURCC('N','V','2','1'):
2425   case GST_MAKE_FOURCC('S','N','2','1'):
2426     *pix_format = CAMERA_PIXEL_FORMAT_NV21;
2427     break;
2428   case GST_MAKE_FOURCC('J','P','E','G'):
2429     *pix_format = CAMERA_PIXEL_FORMAT_JPEG;
2430     break;
2431   case GST_MAKE_FOURCC('M','J','P','G'):
2432     *pix_format = CAMERA_PIXEL_FORMAT_MJPEG;
2433     break;
2434   default:
2435     GST_ERROR("unknown fourcc %c%c%c%c",
2436       fourcc, fourcc >> 8, fourcc >> 16, fourcc >> 24);
2437     return FALSE;
2438   }
2439
2440   GST_INFO("pixel format[%c%c%c%c] -> [%d]",
2441     fourcc, fourcc >> 8, fourcc >> 16, fourcc >> 24,
2442     *pix_format);
2443
2444   return TRUE;
2445 }
2446
2447
2448 static gboolean __gst_tizencamerasrc_get_tbm_format(int pix_format, guint32 *tbm_format)
2449 {
2450   if (tbm_format == NULL) {
2451     GST_ERROR("NULL pointer");
2452     return FALSE;
2453   }
2454
2455   switch (pix_format) {
2456   case CAMERA_PIXEL_FORMAT_I420:
2457     *tbm_format = TBM_FORMAT_YUV420;
2458     break;
2459   case CAMERA_PIXEL_FORMAT_YV12:
2460     *tbm_format = TBM_FORMAT_YVU420;
2461     break;
2462   case CAMERA_PIXEL_FORMAT_YUYV:
2463     *tbm_format = TBM_FORMAT_YUYV;
2464     break;
2465   case CAMERA_PIXEL_FORMAT_UYVY:
2466     *tbm_format = TBM_FORMAT_UYVY;
2467     break;
2468   case CAMERA_PIXEL_FORMAT_NV12:
2469     *tbm_format = TBM_FORMAT_NV12;
2470     break;
2471   case CAMERA_PIXEL_FORMAT_NV21:
2472     *tbm_format = TBM_FORMAT_NV21;
2473     break;
2474   default:
2475     GST_WARNING("unsupported pixel format[%d] for tbm", pix_format);
2476     return FALSE;
2477   }
2478
2479   return TRUE;
2480 }
2481
2482
2483 static gboolean __gst_tizencamerasrc_get_frame_size(int fourcc, int width, int height, unsigned int *outsize)
2484 {
2485   switch (fourcc) {
2486   case GST_MAKE_FOURCC('I','4','2','0'):  /* V4L2_PIX_FMT_YUV420 */
2487   case GST_MAKE_FOURCC('I','Y','U','V'):
2488   case GST_MAKE_FOURCC('Y','U','1','2'):
2489   case GST_MAKE_FOURCC('Y','V','1','2'):
2490   case GST_MAKE_FOURCC('S','4','2','0'):  /* V4L2_PIX_FMT_NV12 tiled non-linear */
2491     *outsize = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
2492     *outsize += 2 * ((GST_ROUND_UP_8 (width) / 2) * (GST_ROUND_UP_2 (height) / 2));
2493     break;
2494   case GST_MAKE_FOURCC('Y','U','Y','V'):  /* V4L2_PIX_FMT_YUYV */
2495   case GST_MAKE_FOURCC('Y','U','Y','2'):  /* V4L2_PIX_FMT_YUYV */
2496   case GST_MAKE_FOURCC('S','U','Y','V'):
2497   case GST_MAKE_FOURCC('S','U','Y','2'):
2498   case GST_MAKE_FOURCC('U','Y','V','Y'):  /* V4L2_PIX_FMT_UYVY */
2499   case GST_MAKE_FOURCC('S','Y','V','Y'):  /* V4L2_PIX_FMT_UYVY */
2500   case GST_MAKE_FOURCC('4','2','2','P'):  /* V4L2_PIX_FMT_YUV422P */
2501   case GST_MAKE_FOURCC('Y','4','2','B'):  /* V4L2_PIX_FMT_YUV422P */
2502   case GST_MAKE_FOURCC('Y','4','1','P'):  /* V4L2_PIX_FMT_Y41P */
2503     *outsize = (GST_ROUND_UP_2 (width) * 2) * height;
2504     break;
2505   case GST_MAKE_FOURCC('Y','4','1','B'):  /* V4L2_PIX_FMT_YUV411P */
2506     *outsize = GST_ROUND_UP_4 (width) * height;
2507     *outsize += 2 * ((GST_ROUND_UP_8 (width) / 4) * height);
2508     break;
2509   case GST_MAKE_FOURCC('N','V','1','2'):  /* V4L2_PIX_FMT_NV12 */
2510   case GST_MAKE_FOURCC('N','V','2','1'):  /* V4L2_PIX_FMT_NV21 */
2511   case GST_MAKE_FOURCC('S','N','1','2'):  /* V4L2_PIX_FMT_NV12 non-linear */
2512   case GST_MAKE_FOURCC('S','N','2','1'):  /* V4L2_PIX_FMT_NV21 non-linear */
2513     *outsize = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height);
2514     *outsize += (GST_ROUND_UP_4 (width) * height) / 2;
2515     break;
2516   case GST_MAKE_FOURCC('J','P','E','G'):
2517   case GST_MAKE_FOURCC('M','J','P','G'):
2518     /* jpeg size can't be calculated here. */
2519     *outsize = 0;
2520     break;
2521   default:
2522     /* unknown format!! */
2523     *outsize = 0;
2524     break;
2525   }
2526
2527   return TRUE;
2528 }
2529
2530
2531 static GstCaps *__gst_tizencamerasrc_get_caps_from_buffer(camera_buffer_s *buffer)
2532 {
2533   char *format_string = NULL;
2534   char mimetype[32];
2535   GstCaps *caps = NULL;
2536
2537   if (!buffer) {
2538     GST_ERROR("NULL buffer");
2539     return NULL;
2540   }
2541
2542   switch (buffer->format) {
2543   case CAMERA_PIXEL_FORMAT_NV12:
2544     snprintf(mimetype, sizeof(mimetype), "video/x-raw");
2545     format_string = "NV12";
2546     break;
2547   case CAMERA_PIXEL_FORMAT_NV21:
2548     snprintf(mimetype, sizeof(mimetype), "video/x-raw");
2549     format_string = "NV21";
2550     break;
2551   case CAMERA_PIXEL_FORMAT_I420:
2552     snprintf(mimetype, sizeof(mimetype), "video/x-raw");
2553     format_string = "I420";
2554     break;
2555   case CAMERA_PIXEL_FORMAT_YV12:
2556     snprintf(mimetype, sizeof(mimetype), "video/x-raw");
2557     format_string = "YV12";
2558     break;
2559   case CAMERA_PIXEL_FORMAT_YUYV:
2560     snprintf(mimetype, sizeof(mimetype), "video/x-raw");
2561     format_string = "YUY2";
2562     break;
2563   case CAMERA_PIXEL_FORMAT_UYVY:
2564     snprintf(mimetype, sizeof(mimetype), "video/x-raw");
2565     format_string = "UYVY";
2566     break;
2567   case CAMERA_PIXEL_FORMAT_H264:
2568     snprintf(mimetype, sizeof(mimetype), "video/x-h264");
2569     break;
2570   case CAMERA_PIXEL_FORMAT_JPEG:
2571     snprintf(mimetype, sizeof(mimetype), "image/jpeg");
2572     break;
2573   case CAMERA_PIXEL_FORMAT_MJPEG:
2574     snprintf(mimetype, sizeof(mimetype), "video/x-jpeg");
2575     break;
2576   case CAMERA_PIXEL_FORMAT_VP8:
2577     snprintf(mimetype, sizeof(mimetype), "video/x-vp8");
2578     break;
2579   case CAMERA_PIXEL_FORMAT_VP9:
2580     snprintf(mimetype, sizeof(mimetype), "video/x-vp9");
2581     break;
2582   default:
2583     GST_ERROR("unsupported format[%d]", buffer->format);
2584     return NULL;
2585   }
2586
2587   caps = gst_caps_new_simple(mimetype,
2588     "width", G_TYPE_INT, buffer->resolution.width,
2589     "height", G_TYPE_INT, buffer->resolution.height,
2590     NULL);
2591   if (!caps) {
2592     GST_ERROR("caps failed for [%s][%s]", mimetype, format_string);
2593     return NULL;
2594   }
2595
2596   if (format_string)
2597     gst_caps_set_simple(caps, "format", G_TYPE_STRING, format_string, NULL);
2598
2599   GST_INFO("new caps [%"GST_PTR_FORMAT"]", caps);
2600
2601   return caps;
2602 }
2603
2604
2605 static gboolean gst_tizencamerasrc_get_caps_info(GstTizenCameraSrc *camerasrc, GstCaps *caps, guint *size)
2606 {
2607   gint fps_n = 0;
2608   gint fps_d = 0;
2609   gint width = 0;
2610   gint height = 0;
2611   gint rotate = 0;
2612   const gchar *mimetype;
2613   GstVideoInfo video_info;
2614   const gchar *caps_format_name = NULL;
2615   guint32 caps_fourcc = 0;
2616   const GValue *framerate;
2617   GstStructure *structure = NULL;
2618
2619   GST_WARNING_OBJECT(camerasrc, "caps[%"GST_PTR_FORMAT"]", caps);
2620
2621   structure = gst_caps_get_structure(caps, 0);
2622
2623   if (!gst_structure_get_int(structure, "width", &width)) {
2624     GST_ERROR_OBJECT(camerasrc, "width failed");
2625     return FALSE;
2626   }
2627
2628   if (!gst_structure_get_int(structure, "height", &height)) {
2629     GST_ERROR_OBJECT(camerasrc, "height failed");
2630     return FALSE;
2631   }
2632
2633   if (!gst_structure_get_int(structure, "rotate", &rotate))
2634     GST_WARNING_OBJECT(camerasrc, "Failed to get rotate info in caps. set default 0.");
2635   else
2636     GST_INFO_OBJECT(camerasrc, "Succeed to get rotate [%d] info in caps", rotate);
2637
2638   if (!gst_video_info_from_caps(&camerasrc->video_info, caps)) {
2639     GST_ERROR_OBJECT(camerasrc, "failed to get video info from caps");
2640     return FALSE;
2641   }
2642
2643   camerasrc->width = width;
2644   camerasrc->height = height;
2645   camerasrc->rotate = rotate;
2646
2647   framerate = gst_structure_get_value(structure, "framerate");
2648   if (!framerate) {
2649     GST_INFO("Set FPS as default(30/1)");
2650
2651     /* set default fps if framerate is not existed in caps */
2652     fps_n = _DEFAULT_FPS;
2653     fps_d = 1;
2654   } else {
2655     fps_n = gst_value_get_fraction_numerator(framerate);
2656     fps_d = gst_value_get_fraction_denominator(framerate);
2657
2658     /* numerator and denominator should be bigger than zero */
2659     if (fps_n <= 0) {
2660       GST_WARNING("numerator of FPS is %d. make it default(15).", fps_n);
2661       fps_n = _DEFAULT_FPS;
2662     }
2663
2664     if (fps_d <= 0) {
2665       GST_WARNING("denominator of FPS is %d. make it 1.", fps_d);
2666       fps_d = 1;
2667     }
2668   }
2669
2670   camerasrc->fps = (int)((float)fps_n / (float)fps_d);
2671
2672   if (!gst_video_info_from_caps(&video_info, caps)) {
2673     GST_ERROR_OBJECT(camerasrc, "get video info from caps[%"GST_PTR_FORMAT"]", caps);
2674     return FALSE;
2675   }
2676
2677   if (GST_VIDEO_INFO_IS_YUV(&video_info)) {
2678     caps_format_name = gst_structure_get_string(structure, "format");
2679     if (!caps_format_name) {
2680       GST_ERROR_OBJECT(camerasrc, "NULL format name from caps[%"GST_PTR_FORMAT"]", caps);
2681       return FALSE;
2682     }
2683
2684     g_strlcpy(camerasrc->format_name, caps_format_name, sizeof(camerasrc->format_name));
2685     caps_fourcc = MAKE_FOURCC_FROM_STRING(camerasrc->format_name);
2686
2687     __gst_tizencamerasrc_get_frame_size(caps_fourcc, width, height, size);
2688     __gst_tizencamerasrc_get_raw_pixel_info(caps_fourcc, &camerasrc->pix_format);
2689
2690     camerasrc->is_encoded_format = FALSE;
2691   } else {
2692
2693     mimetype = gst_structure_get_name(structure);
2694     *size = 0;
2695
2696     if (!strcmp(mimetype, "video/x-h264")) {
2697       g_strlcpy(camerasrc->format_name, GST_VIDEO_INFO_NAME(&video_info), sizeof(camerasrc->format_name));
2698       camerasrc->pix_format = CAMERA_PIXEL_FORMAT_H264;
2699     } else if (!strcmp(mimetype, "image/jpeg") || !strcmp(mimetype, "video/x-jpeg")) {
2700       g_strlcpy(camerasrc->format_name, GST_VIDEO_INFO_NAME(&video_info), sizeof(camerasrc->format_name));
2701       camerasrc->pix_format = CAMERA_PIXEL_FORMAT_MJPEG;
2702     } else if (!strcmp(mimetype, "video/x-vp8")) {
2703       g_strlcpy(camerasrc->format_name, GST_VIDEO_INFO_NAME(&video_info), sizeof(camerasrc->format_name));
2704       camerasrc->pix_format = CAMERA_PIXEL_FORMAT_VP8;
2705     } else if (!strcmp(mimetype, "video/x-vp9")) {
2706       g_strlcpy(camerasrc->format_name, GST_VIDEO_INFO_NAME(&video_info), sizeof(camerasrc->format_name));
2707       camerasrc->pix_format = CAMERA_PIXEL_FORMAT_VP9;
2708     } else {
2709       GST_ERROR_OBJECT(camerasrc, "unsupported caps[%"GST_PTR_FORMAT"]", caps);
2710       return FALSE;
2711     }
2712
2713     camerasrc->is_encoded_format = TRUE;
2714   }
2715
2716   GST_INFO_OBJECT(camerasrc, "pixformat[%d], size[%u] from [%"GST_PTR_FORMAT"]",
2717     camerasrc->pix_format, *size, caps);
2718
2719   return TRUE;
2720 }
2721
2722
2723 static void __gst_tizencamerasrc_post_message_int(GstTizenCameraSrc *camerasrc, const char *msg_name, const char *field_name, int value)
2724 {
2725   GstMessage *m = NULL;
2726   GstStructure *s = NULL;
2727
2728   if (!camerasrc || !msg_name || !field_name) {
2729     GST_ERROR("pointer is NULL %p, %p, %p", camerasrc, msg_name, field_name);
2730     return;
2731   }
2732
2733   GST_INFO("post message [%s] %s %d", msg_name, field_name, value);
2734
2735   s = gst_structure_new(msg_name, field_name, G_TYPE_INT, value, NULL);
2736   if (s == NULL) {
2737     GST_ERROR("gst_structure_new failed");
2738     gst_tizencamerasrc_error_handler(camerasrc, CAMERA_ERROR_OUT_OF_MEMORY);
2739     return;
2740   }
2741
2742   m = gst_message_new_element(GST_OBJECT(camerasrc), s);
2743   if (m == NULL) {
2744     GST_ERROR("gst_message_new_element failed");
2745     gst_tizencamerasrc_error_handler(camerasrc, CAMERA_ERROR_OUT_OF_MEMORY);
2746     return;
2747   }
2748
2749   gst_element_post_message(GST_ELEMENT(camerasrc), m);
2750
2751   return;
2752 }
2753
2754
2755 static int __gst_tizencamerasrc_release_buffer(GstTizenCameraSrc *camerasrc, GstTizenCameraBufferType type, int index, int stream_id)
2756 {
2757   if (!camerasrc) {
2758     GST_ERROR("NULL handle");
2759     return CAMERA_ERROR_INVALID_PARAMETER;
2760   }
2761
2762   switch (type) {
2763   case BUFFER_TYPE_PREVIEW:
2764     return hal_camera_release_preview_buffer(camerasrc->hal_handle, index);
2765   case BUFFER_TYPE_VIDEO:
2766     return hal_camera_release_video_buffer(camerasrc->hal_handle, index);
2767   case BUFFER_TYPE_EXTRA_PREVIEW:
2768     return hal_camera_release_extra_preview_buffer(camerasrc->hal_handle, stream_id, index);
2769   default:
2770     GST_ERROR_OBJECT(camerasrc, "unknown type[%d], [%d,%d]", type, index, stream_id);
2771     return CAMERA_ERROR_INVALID_PARAMETER;
2772   }
2773 }
2774
2775
2776 static gboolean gst_tizencamerasrc_set_caps(GstBaseSrc *src, GstCaps *caps)
2777 {
2778   guint size;
2779   GstTizenCameraSrc *camerasrc = NULL;
2780   gboolean res = FALSE;
2781
2782   int tbm_ret = 0;
2783   tbm_surface_h t_surface = NULL;
2784
2785   camerasrc = GST_TIZENCAMERA_SRC(src);
2786
2787   GST_INFO_OBJECT(camerasrc, "ENTERED");
2788
2789   if (camerasrc->mode == VIDEO_IN_MODE_PREVIEW ||
2790       camerasrc->mode == VIDEO_IN_MODE_VIDEO) {
2791     GST_INFO_OBJECT(camerasrc, "Proceed set_caps");
2792     GST_INFO("            gst_tizencamerasrc_stop");
2793     if (!gst_tizencamerasrc_stop(camerasrc)) {
2794       GST_INFO_OBJECT(camerasrc, "Cam sensor stop failed.");
2795     }
2796   } else if (camerasrc->mode == VIDEO_IN_MODE_CAPTURE) {
2797     GST_ERROR_OBJECT(camerasrc, "A mode of avsystem camera is capture. Not to proceed set_caps.");
2798     GST_DEBUG_OBJECT(camerasrc, "LEAVE");
2799     return FALSE;
2800   } else {
2801     GST_INFO_OBJECT(camerasrc, "A mode of avsystem camera is unknown[%d]. Proceed set_caps.", camerasrc->mode);
2802   }
2803
2804   /* we want our own v4l2 type of fourcc codes */
2805   if (!gst_tizencamerasrc_get_caps_info(camerasrc, caps, &size)) {
2806     GST_INFO_OBJECT(camerasrc, "can't get capture information from caps %p", caps);
2807     return FALSE;
2808   }
2809
2810   /* get tbm surface info */
2811   if (__gst_tizencamerasrc_get_tbm_format(camerasrc->pix_format, &camerasrc->tbm_format)) {
2812
2813     t_surface = tbm_surface_create(camerasrc->width, camerasrc->height, camerasrc->tbm_format);
2814     if (!t_surface) {
2815       GST_ERROR_OBJECT(camerasrc, "tbm surface create failed");
2816       return FALSE;
2817     }
2818
2819     memset(&camerasrc->ts_info, 0x0, sizeof(tbm_surface_info_s));
2820
2821     tbm_ret = tbm_surface_get_info(t_surface, &camerasrc->ts_info);
2822
2823     GST_WARNING_OBJECT(camerasrc, "TBM info: res[%ux%u], stride[%u], size[%u]",
2824       camerasrc->ts_info.width, camerasrc->ts_info.height,
2825       camerasrc->ts_info.planes[0].stride, camerasrc->ts_info.size);
2826
2827     tbm_surface_destroy(t_surface);
2828     t_surface = NULL;
2829
2830     if (tbm_ret != TBM_SURFACE_ERROR_NONE) {
2831       GST_ERROR_OBJECT(camerasrc, "tbm surface info get failed");
2832       return FALSE;
2833     }
2834   } else if (camerasrc->pix_format != CAMERA_PIXEL_FORMAT_H264 &&
2835     camerasrc->pix_format != CAMERA_PIXEL_FORMAT_MJPEG &&
2836     camerasrc->pix_format != CAMERA_PIXEL_FORMAT_VP8 &&
2837     camerasrc->pix_format != CAMERA_PIXEL_FORMAT_VP9) {
2838     GST_ERROR_OBJECT(camerasrc, "unsupported pixel format %d",camerasrc->pix_format);
2839     return FALSE;
2840   }
2841
2842   GST_INFO("            gst_tizencamerasrc_start");
2843   if (!gst_tizencamerasrc_start(camerasrc)) {
2844     GST_INFO_OBJECT (camerasrc,  "Cam sensor start failed.");
2845   }
2846
2847   res = gst_pad_push_event (GST_BASE_SRC_PAD (src), gst_event_new_caps (caps));
2848
2849   GST_INFO_OBJECT (camerasrc, "LEAVE");
2850
2851   return res;
2852 }
2853
2854
2855 static gboolean gst_tizencamerasrc_unlock(GstBaseSrc *basesrc)
2856 {
2857   GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC(basesrc);
2858
2859   if (!camerasrc) {
2860     GST_ERROR("NULL handle");
2861     return FALSE;
2862   }
2863
2864   GST_INFO_OBJECT(camerasrc, "flush start");
2865
2866   camerasrc->is_flushing = TRUE;
2867
2868   return TRUE;
2869 }
2870
2871 static gboolean gst_tizencamerasrc_unlock_stop(GstBaseSrc *basesrc)
2872 {
2873   GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC(basesrc);
2874
2875   if (!camerasrc) {
2876     GST_ERROR("NULL handle");
2877     return FALSE;
2878   }
2879
2880   GST_INFO_OBJECT(camerasrc, "flush stop");
2881
2882   camerasrc->is_flushing = FALSE;
2883
2884   return TRUE;
2885 }
2886
2887 static void gst_tizencamerasrc_class_init(GstTizenCameraSrcClass *klass)
2888 {
2889   GST_DEBUG_CATEGORY_INIT(tizencamerasrc_debug, "tizencamerasrc", 0, "tizencamerasrc element");
2890
2891   GObjectClass *gobject_class;
2892   GstElementClass *element_class;
2893   GstBaseSrcClass *basesrc_class;
2894   GstPushSrcClass *pushsrc_class;
2895
2896   GST_DEBUG("ENTERED");
2897
2898   gobject_class = G_OBJECT_CLASS(klass);
2899   element_class = GST_ELEMENT_CLASS(klass);
2900   basesrc_class = GST_BASE_SRC_CLASS(klass);
2901   pushsrc_class = GST_PUSH_SRC_CLASS(klass);
2902
2903   gobject_class->set_property = gst_tizencamerasrc_set_property;
2904   gobject_class->get_property = gst_tizencamerasrc_get_property;
2905   gobject_class->finalize = gst_tizencamerasrc_finalize;
2906   element_class->change_state = gst_tizencamerasrc_change_state;
2907   gst_element_class_add_pad_template(element_class, gst_static_pad_template_get (&src_factory));
2908   gst_element_class_set_static_metadata(element_class,
2909     "Camera Source GStreamer Plug-in",
2910     "Source/Video",
2911     "camera src for videosrc based GStreamer Plug-in",
2912     "Jeongmo Yang <jm80.yang@samsung.com>");
2913   basesrc_class->start = gst_tizencamerasrc_src_start;
2914   basesrc_class->stop = gst_tizencamerasrc_src_stop;
2915   basesrc_class->get_caps = gst_tizencamerasrc_get_caps;
2916   basesrc_class->set_caps = gst_tizencamerasrc_set_caps;
2917   basesrc_class->negotiate = gst_tizencamerasrc_negotiate;
2918   basesrc_class->unlock = GST_DEBUG_FUNCPTR(gst_tizencamerasrc_unlock);
2919   basesrc_class->unlock_stop = GST_DEBUG_FUNCPTR(gst_tizencamerasrc_unlock_stop);
2920   pushsrc_class->create = gst_tizencamerasrc_src_create;
2921
2922   g_object_class_install_property(gobject_class, ARG_CAMERA_ID,
2923     g_param_spec_int("camera-id", "index number of camera to activate",
2924       "index number of camera to activate",
2925       _CAMERA_ID_MIN, _CAMERA_ID_MAX, 0,
2926       G_PARAM_READWRITE));
2927
2928   g_object_class_install_property(gobject_class, ARG_DEVICE_NAME,
2929     g_param_spec_string("device-name", "Device name",
2930       "Name of the device, camera-id will be ignored if this is set",
2931       NULL,
2932       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2933
2934   g_object_class_install_property(gobject_class, ARG_DEVICE_BUS,
2935     g_param_spec_int("device-bus", "The device bus number",
2936       "The device bus number",
2937       0, G_MAXINT, 0,
2938       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2939
2940   g_object_class_install_property(gobject_class, ARG_DEVICE_PORT,
2941     g_param_spec_string("device-port", "The device port number",
2942       "The device port number",
2943       NULL,
2944       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2945
2946   g_object_class_install_property(gobject_class, ARG_HAL_NAME,
2947     g_param_spec_string("hal-name", "HAL name",
2948       "The name of the HAL library, and setting \"NULL\" or empty string will load the default HAL. "
2949       "It should be set at least once after creating the element, "
2950       "otherwise it will fail when set something or change state.",
2951       NULL,
2952       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2953
2954   g_object_class_install_property(gobject_class, ARG_VFLIP,
2955     g_param_spec_boolean("vflip", "Flip vertically",
2956       "Flip camera input vertically",
2957       0,
2958       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2959
2960   g_object_class_install_property(gobject_class, ARG_HFLIP,
2961     g_param_spec_boolean("hflip", "Flip horizontally",
2962       "Flip camera input horizontally",
2963       0,
2964       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2965
2966   g_object_class_install_property(gobject_class, ARG_HIGH_SPEED_FPS,
2967     g_param_spec_int("high-speed-fps", "Fps for high speed recording",
2968       "If this value is 0, the element doesn't activate high speed recording.",
2969       0, G_MAXINT, _DEFAULT_HIGH_SPEED_FPS,
2970       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2971
2972   g_object_class_install_property(gobject_class, ARG_AUTO_FPS,
2973     g_param_spec_boolean("fps-auto", "FPS Auto",
2974       "Field for auto fps setting",
2975       _DEFAULT_FPS_AUTO,
2976       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2977
2978   g_object_class_install_property(gobject_class, ARG_EXTRA_PREVIEW,
2979     g_param_spec_boolean("extra-preview", "Extra preview",
2980       "Flag for extra preview",
2981       _DEFAULT_EXTRA_PREVIEW,
2982       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2983
2984   g_object_class_install_property(gobject_class, ARG_LIVE_BUFFER_MAX,
2985     g_param_spec_int("live-buffer-max", "Live buffer max",
2986       "Maximum number of live buffers",
2987       1, G_MAXINT, _DEFAULT_LIVE_BUFFER_MAX,
2988       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2989
2990   g_object_class_install_property(gobject_class, ARG_LIVE_BUFFER_MAX_RAW,
2991     g_param_spec_int("live-buffer-max-raw", "Live buffer max for RAW format",
2992       "Maximum number of live buffers for RAW format",
2993       1, G_MAXINT, _DEFAULT_LIVE_BUFFER_MAX_RAW,
2994       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2995
2996   g_object_class_install_property(gobject_class, ARG_EMPTY_BUFFER_TIMEOUT,
2997     g_param_spec_int("empty-buffer-timeout", "Timeout for empty buffer",
2998       "Timeout to wait for buffer to be available. (ms, 0 = unlimited)",
2999       0, G_MAXINT, _DEFAULT_EMPTY_BUFFER_TIMEOUT,
3000       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3001
3002   g_object_class_install_property(gobject_class, ARG_BUFFER_QUARK,
3003     g_param_spec_uint("buffer-quark", "Buffer quark",
3004       "GQuark for buffer.",
3005       0, G_MAXUINT, _DEFAULT_BUFFER_QUARK,
3006       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
3007
3008   g_object_class_install_property(gobject_class, ARG_CAPTURE_FOURCC,
3009     g_param_spec_uint("capture-fourcc", "Capture format",
3010       "Fourcc value for capture format",
3011       0, G_MAXUINT, 0,
3012       G_PARAM_READWRITE));
3013
3014   g_object_class_install_property(gobject_class, ARG_CAPTURE_WIDTH,
3015     g_param_spec_int("capture-width", "Capture width",
3016       "Width for camera size to capture, it should be set before Height",
3017       0, G_MAXINT, _DEFAULT_CAP_WIDTH,
3018       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3019
3020   g_object_class_install_property(gobject_class, ARG_CAPTURE_HEIGHT,
3021     g_param_spec_int("capture-height", "Capture height",
3022       "Height for camera size to capture, it should be set after width",
3023       0, G_MAXINT, _DEFAULT_CAP_HEIGHT,
3024       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3025
3026   g_object_class_install_property(gobject_class, ARG_CAPTURE_INTERVAL,
3027     g_param_spec_int("capture-interval", "Capture interval",
3028       "Interval time to capture (millisecond)",
3029       0, G_MAXINT, _DEFAULT_CAP_INTERVAL,
3030       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3031
3032   g_object_class_install_property(gobject_class, ARG_CAPTURE_COUNT,
3033     g_param_spec_int("capture-count", "Capture count",
3034       "Capture count for multishot",
3035       1, G_MAXINT, _DEFAULT_CAP_COUNT,
3036       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3037
3038   g_object_class_install_property(gobject_class, ARG_CAPTURE_QUALITY,
3039     g_param_spec_int("capture-quality", "Capture quality",
3040       "Quality of capture image",
3041       1, 100, _DEFAULT_CAP_QUALITY,
3042       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3043
3044   g_object_class_install_property(gobject_class, ARG_CAPTURE_PROVIDE_EXIF,
3045     g_param_spec_boolean("provide-exif", "Whether EXIF is provided",
3046       "Does capture provide EXIF?",
3047       _DEFAULT_CAP_PROVIDE_EXIF,
3048       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
3049
3050   g_object_class_install_property(gobject_class, ARG_BITRATE,
3051     g_param_spec_int("bitrate", "Bitrate of encoded stream",
3052       "Bitrate of encoded stream like H.264",
3053       1, G_MAXINT, _DEFAULT_BITRATE,
3054       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3055
3056   g_object_class_install_property(gobject_class, ARG_GOP_INTERVAL,
3057     g_param_spec_int("gop-interval", "GOP interval of encoded stream",
3058       "GOP(Group Of Pictures) interval of encoded stream like H.264",
3059       1, G_MAXINT, _DEFAULT_GOP_INTERVAL,
3060       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3061
3062   /**
3063   * GstTizenCameraSrc::still-capture:
3064   * @camerasrc: the camerasrc instance
3065   * @buffer: the buffer that will be pushed - Main
3066   * @buffer: the buffer that will be pushed - Thumbnail
3067   * @buffer: the buffer that will be pushed - Screennail
3068   */
3069   gst_tizencamerasrc_signals[SIGNAL_STILL_CAPTURE] =
3070     g_signal_new("still-capture",
3071       G_TYPE_FROM_CLASS(klass),
3072       G_SIGNAL_RUN_LAST,
3073       G_STRUCT_OFFSET(GstTizenCameraSrcClass, still_capture),
3074       NULL,
3075       NULL,
3076       gst_tizencamerasrc_VOID__OBJECT_OBJECT_OBJECT,
3077       G_TYPE_NONE,
3078       3, /* Number of parameter */
3079       GST_TYPE_SAMPLE,  /* Main image buffer */
3080       GST_TYPE_SAMPLE,  /* Thumbnail image buffer */
3081       GST_TYPE_SAMPLE); /* Screennail image buffer */
3082
3083   /**
3084   * GstCameraSrc::video-stream-cb:
3085   * @camerasrc: the camerasrc instance
3086   * @buffer: the buffer that will be pushed
3087   */
3088   gst_tizencamerasrc_signals[SIGNAL_VIDEO_STREAM_CB] =
3089     g_signal_new("video-stream-cb",
3090       G_TYPE_FROM_CLASS(klass),
3091       G_SIGNAL_RUN_LAST,
3092       G_STRUCT_OFFSET(GstTizenCameraSrcClass, video_stream_cb),
3093       NULL,
3094       NULL,
3095       gst_tizencamerasrc_VOID__OBJECT_VIDEO_STREAM,
3096       G_TYPE_NONE,
3097       1, /* Number of parameter */
3098       GST_TYPE_SAMPLE); /* record buffer */
3099
3100   /**
3101   * GstCameraSrc::extra-preview-stream-cb:
3102   * @camerasrc: the camerasrc instance
3103   * @stream_id: the id of extra stream
3104   * @buffer: the buffer that will be pushed
3105   */
3106   gst_tizencamerasrc_signals[SIGNAL_EXTRA_PREVIEW_STREAM_CB] =
3107     g_signal_new("extra-preview-stream-cb",
3108       G_TYPE_FROM_CLASS(klass),
3109       G_SIGNAL_RUN_LAST,
3110       G_STRUCT_OFFSET(GstTizenCameraSrcClass, extra_preview_stream_cb),
3111       NULL,
3112       NULL,
3113       gst_tizencamerasrc_VOID__OBJECT_EXTRA_PREVIEW_STREAM,
3114       G_TYPE_NONE,
3115       2, /* Number of parameter */
3116       G_TYPE_INT,       /* stream id */
3117       GST_TYPE_SAMPLE); /* extra preview buffer */
3118
3119   GST_DEBUG("LEAVE");
3120
3121   return;
3122 }
3123
3124
3125 static void gst_tizencamerasrc_init(GstTizenCameraSrc *camerasrc)
3126 {
3127   GST_INFO_OBJECT(camerasrc, "ENTERED");
3128
3129   camerasrc->hal_handle = NULL;
3130   camerasrc->mode = VIDEO_IN_MODE_NONE;
3131   camerasrc->firsttime = TRUE;
3132   camerasrc->cap_count_current = -1;
3133   camerasrc->cap_count_reverse = _DEFAULT_CAP_COUNT;
3134
3135   /* camera */
3136   camerasrc->device_info = g_new0(camera_device_info_list_s, 1);
3137   camerasrc->fps = _DEFAULT_FPS;
3138   camerasrc->rotate = 0;
3139   camerasrc->high_speed_fps = _DEFAULT_HIGH_SPEED_FPS;
3140   camerasrc->fps_auto = _DEFAULT_FPS_AUTO;
3141   camerasrc->pix_format = _DEFAULT_PIX_FORMAT;
3142   g_strlcpy(camerasrc->format_name, _DEFAULT_PIX_FORMAT_NAME, sizeof(camerasrc->format_name));
3143   camerasrc->preview_control.running = FALSE;
3144   camerasrc->vflip = FALSE;
3145   camerasrc->hflip = FALSE;
3146   camerasrc->camera_id = _DEFAULT_CAMERA_ID;
3147   camerasrc->device_name = NULL;
3148   camerasrc->device_port = NULL;
3149   camerasrc->preview_buffer_list = g_queue_new ();
3150   camerasrc->live_buffer_max = _DEFAULT_LIVE_BUFFER_MAX;
3151   camerasrc->live_buffer_max_raw = _DEFAULT_LIVE_BUFFER_MAX_RAW;
3152   camerasrc->empty_buffer_timeout = _DEFAULT_EMPTY_BUFFER_TIMEOUT;
3153
3154   /* capture */
3155   camerasrc->cap_fourcc = MAKE_FOURCC_FROM_STRING(_DEFAULT_CAPTURE_FORMAT_NAME);
3156   camerasrc->cap_width = _DEFAULT_CAP_WIDTH;
3157   camerasrc->cap_height = _DEFAULT_CAP_HEIGHT;
3158   camerasrc->cap_interval = _DEFAULT_CAP_INTERVAL;
3159   camerasrc->cap_count = _DEFAULT_CAP_COUNT;
3160   camerasrc->cap_quality = _DEFAULT_CAP_QUALITY;
3161   camerasrc->cap_provide_exif = _DEFAULT_CAP_PROVIDE_EXIF;
3162
3163   /* encoded stream */
3164   camerasrc->bitrate = _DEFAULT_BITRATE;
3165   camerasrc->gop_interval = _DEFAULT_GOP_INTERVAL;
3166
3167   g_mutex_init(&camerasrc->preview_control.lock);
3168   g_cond_init(&camerasrc->preview_control.cond);
3169   g_mutex_init(&camerasrc->extra_preview_control.lock);
3170   g_cond_init(&camerasrc->extra_preview_control.cond);
3171   g_mutex_init(&camerasrc->video_control.lock);
3172   g_cond_init(&camerasrc->video_control.cond);
3173
3174   /* tizen allocator */
3175   camerasrc->allocator = gst_tizen_allocator_new();
3176
3177   camerasrc->buffer_quark = _DEFAULT_BUFFER_QUARK;
3178
3179   /* we operate in time */
3180   gst_base_src_set_format(GST_BASE_SRC(camerasrc), GST_FORMAT_TIME);
3181   gst_base_src_set_live(GST_BASE_SRC(camerasrc), TRUE);
3182   gst_base_src_set_do_timestamp(GST_BASE_SRC(camerasrc), TRUE);
3183
3184   GST_INFO_OBJECT(camerasrc, "LEAVE");
3185
3186   return;
3187 }
3188
3189
3190 static gboolean plugin_init(GstPlugin *plugin)
3191 {
3192   gboolean error;
3193
3194   error = gst_element_register(plugin, "tizencamerasrc", GST_RANK_PRIMARY + 100, GST_TYPE_TIZENCAMERA_SRC);
3195
3196   return error;
3197 }
3198
3199
3200 GST_PLUGIN_DEFINE(GST_VERSION_MAJOR,
3201                   GST_VERSION_MINOR,
3202                   tizencamerasrc,
3203                   "Tizen reference camera source plug-in",
3204                   plugin_init,
3205                   PACKAGE_VERSION,
3206                   "LGPL",
3207                   "Samsung Electronics Co",
3208                   "http://www.samsung.com")
3209
3210 /* GstURIHandler interface */
3211 static GstURIType
3212 gst_tizencamerasrc_uri_get_type (GType type)
3213 {
3214   return GST_URI_SRC;
3215 }
3216
3217 static const gchar * const*
3218 gst_tizencamerasrc_uri_get_protocols (GType type)
3219 {
3220   static const gchar *protocols[] = { "camera", NULL };
3221   return protocols;
3222 }
3223
3224 static gchar *
3225 gst_tizencamerasrc_uri_get_uri (GstURIHandler * handler)
3226 {
3227   return strdup("camera://0");
3228 }
3229
3230 static gboolean
3231 gst_tizencamerasrc_uri_set_uri (GstURIHandler * handler, const gchar * uri, GError **error)
3232 {
3233   GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC (handler);
3234   const gchar *device = "0";
3235   if (strcmp (uri, "camera://") != 0) {
3236     device = uri + 9;
3237   }
3238   g_object_set (camerasrc, "camera-id", atoi(device), NULL);
3239
3240   return TRUE;
3241 }
3242
3243
3244 static void
3245 gst_tizencamerasrc_uri_handler_init (gpointer g_iface, gpointer iface_data)
3246 {
3247   GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
3248
3249   iface->get_type = gst_tizencamerasrc_uri_get_type;
3250   iface->get_protocols = gst_tizencamerasrc_uri_get_protocols;
3251   iface->get_uri = gst_tizencamerasrc_uri_get_uri;
3252   iface->set_uri = gst_tizencamerasrc_uri_set_uri;
3253 }
3254 /* EOF */