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