Export MM_CAMCORDER_EXTRA_PREVIEW_STREAM_MAX
[platform/core/multimedia/libmm-camcorder.git] / src / mm_camcorder_util.c
1 /*
2  * libmm-camcorder
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jeongmo Yang <jm80.yang@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 /*=======================================================================================
23 |  INCLUDE FILES                                                                        |
24 =======================================================================================*/
25 #include <stdio.h>
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <inttypes.h>
29 #include <sys/vfs.h> /* struct statfs */
30 #include <sys/time.h> /* gettimeofday */
31 #include <sys/stat.h>
32 #include <gst/video/video-info.h>
33 #include <gio/gio.h>
34
35 #include "mm_camcorder_internal.h"
36 #include "mm_camcorder_util.h"
37 #include "mm_camcorder_sound.h"
38 #include <mm_util_image.h>
39 #include <mm_util_imgp.h>
40 #include <mm_util_jpeg.h>
41
42 /*-----------------------------------------------------------------------
43 |    GLOBAL VARIABLE DEFINITIONS for internal                           |
44 -----------------------------------------------------------------------*/
45 static int mmcam_log_level = MM_CAMCORDER_LOG_LEVEL_INFO;
46
47 /*-----------------------------------------------------------------------
48 |    LOCAL VARIABLE DEFINITIONS for internal                            |
49 -----------------------------------------------------------------------*/
50 #define TIME_STRING_MAX_LEN                     64
51 #define __MMCAMCORDER_CAPTURE_WAIT_TIMEOUT      5
52 #define __MMCAMCORDER_MAX_WIDTH                 8192
53 #define __MMCAMCORDER_MAX_HEIGHT                8192
54
55 #define FPUTC_CHECK(x_char, x_file) \
56 { \
57         if (fputc(x_char, x_file) == EOF) { \
58                 MMCAM_LOG_ERROR("[Critical] fputc() returns fail.\n"); \
59                 return FALSE; \
60         } \
61 }
62 #define FPUTS_CHECK(x_str, x_file) \
63 { \
64         if (fputs(x_str, x_file) == EOF) { \
65                 MMCAM_LOG_ERROR("[Critical] fputs() returns fail.\n"); \
66                 SAFE_G_FREE(str); \
67                 return FALSE; \
68         } \
69 }
70
71 /*---------------------------------------------------------------------------
72 |    LOCAL FUNCTION PROTOTYPES:                                                                                         |
73 ---------------------------------------------------------------------------*/
74 /* STATIC INTERNAL FUNCTION */
75
76 //static gint            skip_mdat(FILE *f);
77 static guint16           get_language_code(const char *str);
78 static gchar*            str_to_utf8(const gchar *str);
79 static inline gboolean   write_tag(FILE *f, const gchar *tag);
80 static inline gboolean   write_to_32(FILE *f, guint val);
81 static inline gboolean   write_to_16(FILE *f, guint val);
82 static inline gboolean   write_to_24(FILE *f, guint val);
83 static gboolean _mmcamcorder_convert_YUYV_to_I420(unsigned char *src, guint width, guint height, unsigned char **dst, unsigned int *dst_len);
84 static gboolean _mmcamcorder_convert_UYVY_to_I420(unsigned char *src, guint width, guint height, unsigned char **dst, unsigned int *dst_len);
85 static gboolean _mmcamcorder_convert_NV12_to_I420(unsigned char *src, guint width, guint height, unsigned char **dst, unsigned int *dst_len);
86
87
88 /*===========================================================================================
89 |                                                                                                                                                                                       |
90 |  FUNCTION DEFINITIONS                                                                                                                                         |
91 |                                                                                                                                                                                       |
92 ========================================================================================== */
93 /*---------------------------------------------------------------------------
94 |    GLOBAL FUNCTION DEFINITIONS:                                                                                       |
95 ---------------------------------------------------------------------------*/
96
97 static int __gdbus_method_call_sync(GDBusConnection *conn, const char *bus_name,
98         const char *object, const char *iface, const char *method,
99         GVariant *args, GVariant **result, bool is_sync)
100 {
101         int ret = MM_ERROR_NONE;
102         GVariant *dbus_reply = NULL;
103
104         if (!conn || !object || !iface || !method) {
105                 MMCAM_LOG_ERROR("Invalid Argument %p %p %p %p",
106                         conn, object, iface, method);
107                 return MM_ERROR_INVALID_ARGUMENT;
108         }
109
110         MMCAM_LOG_WARNING("Dbus call - obj [%s], iface [%s], method [%s]", object, iface, method);
111
112         if (is_sync) {
113                 dbus_reply = g_dbus_connection_call_sync(conn,
114                         bus_name, object, iface, method, args, NULL,
115                         G_DBUS_CALL_FLAGS_NONE, G_DBUS_TIMEOUT, NULL, NULL);
116                 if (dbus_reply) {
117                         MMCAM_LOG_WARNING("Method Call '%s.%s' Success", iface, method);
118                         *result = dbus_reply;
119                 } else {
120                         MMCAM_LOG_ERROR("dbus method call sync reply failed");
121                         ret = MM_ERROR_CAMCORDER_INTERNAL;
122                 }
123         } else {
124                 g_dbus_connection_call(conn, bus_name, object, iface, method, args, NULL,
125                         G_DBUS_CALL_FLAGS_NONE, G_DBUS_TIMEOUT, NULL, NULL, NULL);
126         }
127
128         MMCAM_LOG_WARNING("done");
129
130         return ret;
131 }
132
133 static int __gdbus_subscribe_signal(GDBusConnection *conn,
134         const char *object_name, const char *iface_name, const char *signal_name,
135         GDBusSignalCallback signal_cb, guint *subscribe_id, void *userdata)
136 {
137         guint subs_id = 0;
138
139         if (!conn || !object_name || !iface_name || !signal_name || !signal_cb || !subscribe_id) {
140                 MMCAM_LOG_ERROR("Invalid Argument %p %p %p %p %p %p",
141                         conn, object_name, iface_name, signal_name, signal_cb, subscribe_id);
142                 return MM_ERROR_INVALID_ARGUMENT;
143         }
144
145         MMCAM_LOG_INFO("subscirbe signal Obj %s, iface_name %s, sig_name %s",
146                 object_name, iface_name, signal_name);
147
148         subs_id = g_dbus_connection_signal_subscribe(conn,
149                 NULL, iface_name, signal_name, object_name, NULL,
150                 G_DBUS_SIGNAL_FLAGS_NONE, signal_cb, userdata, NULL);
151         if (!subs_id) {
152                 MMCAM_LOG_ERROR("g_dbus_connection_signal_subscribe() failed");
153                 return MM_ERROR_CAMCORDER_INTERNAL;
154         } else {
155                 *subscribe_id = subs_id;
156                 MMCAM_LOG_INFO("subs_id %u", subs_id);
157         }
158
159         return MM_ERROR_NONE;
160 }
161
162
163 static void __gdbus_stream_eos_cb(GDBusConnection *connection,
164         const gchar *sender_name, const gchar *object_path, const gchar *interface_name,
165         const gchar *signal_name, GVariant *param, gpointer user_data)
166 {
167         int played_idx = 0;
168         gboolean stopped_by_user = FALSE;
169         _MMCamcorderGDbusCbInfo *gdbus_info = NULL;
170         mmf_camcorder_t *hcamcorder = NULL;
171
172         MMCAM_LOG_WARNING("entered");
173
174         if (!param || !user_data) {
175                 MMCAM_LOG_ERROR("invalid parameter %p %p", param, user_data);
176                 return;
177         }
178
179         gdbus_info = (_MMCamcorderGDbusCbInfo *)user_data;
180         hcamcorder = (mmf_camcorder_t *)gdbus_info->mm_handle;
181
182         g_variant_get(param, "(ib)", &played_idx, &stopped_by_user);
183
184         g_mutex_lock(&gdbus_info->sync_mutex);
185
186         MMCAM_LOG_WARNING("gdbus_info->param %d, played_idx %d, stopped_by_user %d, handle %p",
187                 gdbus_info->param, played_idx, stopped_by_user, hcamcorder);
188
189         if (gdbus_info->param == played_idx) {
190                 g_dbus_connection_signal_unsubscribe(connection, gdbus_info->subscribe_id);
191
192                 gdbus_info->is_playing = FALSE;
193                 gdbus_info->subscribe_id = 0;
194                 gdbus_info->param = 0;
195
196                 g_cond_signal(&gdbus_info->sync_cond);
197         }
198
199         g_mutex_unlock(&gdbus_info->sync_mutex);
200
201         MMCAM_LOG_WARNING("done");
202
203         return;
204 }
205
206 static int __gdbus_wait_for_cb_return(_MMCamcorderGDbusCbInfo *gdbus_info, int time_out)
207 {
208         int ret = MM_ERROR_NONE;
209         gint64 end_time = 0;
210
211         if (!gdbus_info) {
212                 MMCAM_LOG_ERROR("invalid info");
213                 return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
214         }
215
216         g_mutex_lock(&gdbus_info->sync_mutex);
217
218         MMCAM_LOG_WARNING("entered");
219
220         if (gdbus_info->is_playing == FALSE) {
221                 MMCAM_LOG_INFO("callback is already returned");
222                 g_mutex_unlock(&gdbus_info->sync_mutex);
223                 return MM_ERROR_NONE;
224         }
225
226         end_time = g_get_monotonic_time() + (time_out * G_TIME_SPAN_MILLISECOND);
227
228         if (g_cond_wait_until(&gdbus_info->sync_cond, &gdbus_info->sync_mutex, end_time)) {
229                 MMCAM_LOG_WARNING("wait signal received");
230         } else {
231                 MMCAM_LOG_ERROR("wait time is expired");
232                 ret = MM_ERROR_CAMCORDER_RESPONSE_TIMEOUT;
233         }
234
235         g_mutex_unlock(&gdbus_info->sync_mutex);
236
237         MMCAM_LOG_WARNING("done");
238
239         return ret;
240 }
241
242
243 gint32 _mmcamcorder_double_to_fix(gdouble d_number)
244 {
245         return (gint32) (d_number * 65536.0);
246 }
247
248 // find top level tag only, do not use this function for finding sub level tags
249 gint _mmcamcorder_find_tag(FILE *f, guint32 tag_fourcc, gboolean do_rewind)
250 {
251         size_t read_item = 0;
252         guchar buf[8];
253
254         if (do_rewind)
255                 rewind(f);
256
257         while ((read_item = fread(&buf, sizeof(guchar), 8, f)) > 0) {
258                 uint64_t buf_size = 0;
259                 uint32_t buf_fourcc = 0;
260
261                 if (read_item < 8) {
262                         MMCAM_LOG_ERROR("fread failed : %zu", read_item);
263                         break;
264                 }
265
266                 buf_fourcc = MMCAM_FOURCC(buf[4], buf[5], buf[6], buf[7]);
267
268                 if (tag_fourcc == buf_fourcc) {
269                         MMCAM_LOG_INFO("find tag : %c%c%c%c", MMCAM_FOURCC_ARGS(tag_fourcc));
270                         return TRUE;
271                 } else {
272                         MMCAM_LOG_INFO("skip [%c%c%c%c] tag", MMCAM_FOURCC_ARGS(buf_fourcc));
273
274                         buf_size = _mmcamcorder_get_container_size(buf);
275
276                         /* if size of mdat is 1, it means largesize is used.(bigger than 4GB) */
277                         if (buf_fourcc == MMCAM_FOURCC('m', 'd', 'a', 't') &&
278                             buf_size == 1) {
279                                 read_item = fread(&buf, sizeof(guchar), 8, f);
280                                 if (read_item < 8) {
281                                         MMCAM_LOG_ERROR("fread failed");
282                                         return FALSE;
283                                 }
284
285                                 buf_size = _mmcamcorder_get_container_size64(buf);
286                                 buf_size = buf_size - 16; /* include tag and large file flag(size 1) */
287                         } else {
288                                 buf_size = buf_size - 8; /* include tag */
289                         }
290
291                         MMCAM_LOG_INFO("seek %"PRIu64, buf_size);
292                         if (fseeko(f, (off_t)buf_size, SEEK_CUR) != 0) {
293                                 MMCAM_LOG_ERROR("fseeko() fail");
294                                 return FALSE;
295                         }
296                 }
297         }
298
299         MMCAM_LOG_INFO("cannot find tag : %c%c%c%c", MMCAM_FOURCC_ARGS(tag_fourcc));
300
301         return FALSE;
302 }
303
304 gboolean _mmcamcorder_find_fourcc(FILE *f, guint32 tag_fourcc, gboolean do_rewind)
305 {
306         size_t read_item = 0;
307         guchar buf[8];
308
309         if (do_rewind)
310                 rewind(f);
311
312         while ((read_item = fread(&buf, sizeof(guchar), 8, f))  > 0) {
313                 uint64_t buf_size = 0;
314                 uint32_t buf_fourcc = 0;
315
316                 if (read_item < 8) {
317                         MMCAM_LOG_ERROR("fread failed : %zu", read_item);
318                         break;
319                 }
320
321                 buf_fourcc = MMCAM_FOURCC(buf[4], buf[5], buf[6], buf[7]);
322
323                 if (tag_fourcc == buf_fourcc) {
324                         MMCAM_LOG_INFO("find tag : %c%c%c%c", MMCAM_FOURCC_ARGS(tag_fourcc));
325                         return TRUE;
326                 } else if (buf_fourcc == MMCAM_FOURCC('m', 'o', 'o', 'v') &&
327                                    tag_fourcc != buf_fourcc) {
328                         if (_mmcamcorder_find_fourcc(f, tag_fourcc, FALSE))
329                                 return TRUE;
330                         else
331                                 continue;
332                 } else {
333                         MMCAM_LOG_INFO("skip [%c%c%c%c] tag", MMCAM_FOURCC_ARGS(buf_fourcc));
334
335                         buf_size = _mmcamcorder_get_container_size(buf);
336
337                         /* if size of mdat is 1, it means largesize is used.(bigger than 4GB) */
338                         if (buf_fourcc == MMCAM_FOURCC('m', 'd', 'a', 't') &&
339                             buf_size == 1) {
340                                 read_item = fread(&buf, sizeof(guchar), 8, f);
341                                 if (read_item < 8) {
342                                         MMCAM_LOG_ERROR("fread failed");
343                                         return FALSE;
344                                 }
345
346                                 buf_size = _mmcamcorder_get_container_size64(buf);
347                                 buf_size = buf_size - 16; /* include tag and large file flag(size 1) */
348                         } else {
349                                 buf_size = buf_size - 8; /* include tag */
350                         }
351
352                         MMCAM_LOG_INFO("seek %"PRIu64, buf_size);
353                         if (fseeko(f, (off_t)buf_size, SEEK_CUR) != 0) {
354                                 MMCAM_LOG_ERROR("fseeko() fail");
355                                 return FALSE;
356                         }
357                 }
358         }
359
360         MMCAM_LOG_INFO("cannot find tag : %c%c%c%c", MMCAM_FOURCC_ARGS(tag_fourcc));
361
362         return FALSE;
363 }
364
365 gboolean _mmcamcorder_update_size(FILE *f, gint64 prev_pos, gint64 curr_pos)
366 {
367         MMCAM_LOG_INFO("size : %"G_GINT64_FORMAT"", curr_pos-prev_pos);
368         if (fseeko(f, prev_pos, SEEK_SET) != 0) {
369                 MMCAM_LOG_ERROR("fseeko() fail");
370                 return FALSE;
371         }
372
373         if (!write_to_32(f, curr_pos -prev_pos))
374                 return FALSE;
375
376         if (fseeko(f, curr_pos, SEEK_SET) != 0) {
377                 MMCAM_LOG_ERROR("fseeko() fail");
378                 return FALSE;
379         }
380
381         return TRUE;
382 }
383
384 gboolean _mmcamcorder_write_loci(FILE *f, _MMCamcorderLocationInfo info)
385 {
386         gint64 current_pos, pos;
387         gchar *str = NULL;
388
389         MMCAM_LOG_INFO("");
390
391         if ((pos = ftello(f)) < 0) {
392                 MMCAM_LOG_ERROR("ftello() returns negative value");
393                 return FALSE;
394         }
395
396         if (!write_to_32(f, 0)) //size
397                 return FALSE;
398
399         if (!write_tag(f, "loci")) // type
400                 return FALSE;
401
402         FPUTC_CHECK(0, f);              // version
403
404         if (!write_to_24(f, 0)) // flags
405                 return FALSE;
406
407         if (!write_to_16(f, get_language_code("eng"))) // language
408                 return FALSE;
409
410         str = str_to_utf8("location_name");
411
412         FPUTS_CHECK(str, f); // name
413         SAFE_G_FREE(str);
414
415         FPUTC_CHECK('\0', f);
416         FPUTC_CHECK(0, f);              //role
417
418         if (!write_to_32(f, info.longitude))    // Longitude
419                 return FALSE;
420
421         if (!write_to_32(f, info.latitude)) // Latitude
422                 return FALSE;
423
424         if (!write_to_32(f, info.altitude))     // Altitude
425                 return FALSE;
426
427         str = str_to_utf8("Astronomical_body");
428         FPUTS_CHECK(str, f);//Astronomical_body
429         SAFE_G_FREE(str);
430
431         FPUTC_CHECK('\0', f);
432
433         str = str_to_utf8("Additional_notes");
434         FPUTS_CHECK(str, f); // Additional_notes
435         SAFE_G_FREE(str);
436
437         FPUTC_CHECK('\0', f);
438
439         if ((current_pos = ftello(f)) < 0) {
440                 MMCAM_LOG_ERROR("ftello() returns negative value");
441                 return FALSE;
442         }
443
444         if (!_mmcamcorder_update_size(f, pos, current_pos))
445                 return FALSE;
446
447         return TRUE;
448 }
449
450 void _mmcamcorder_write_Latitude(FILE *f, int value)
451 {
452         char s_latitude[16];
453         int l_decimal = 0;
454         int l_below_decimal = 0;
455
456         l_decimal = value / 10000;
457         if (value < 0) {
458                 if (l_decimal == 0)
459                         snprintf(s_latitude, sizeof(s_latitude), "-%.2d.", l_decimal);
460                 else
461                         snprintf(s_latitude, sizeof(s_latitude), "%.2d.", l_decimal);
462         } else {
463                 snprintf(s_latitude, sizeof(s_latitude), "+%.2d.", l_decimal);
464         }
465
466         l_below_decimal = value - (l_decimal * 10000);
467         if (l_below_decimal < 0)
468                 l_below_decimal = -l_below_decimal;
469
470         snprintf(&s_latitude[4], sizeof(s_latitude) - 4, "%.4d", l_below_decimal);
471
472         write_tag(f, s_latitude);
473 }
474
475 void _mmcamcorder_write_Longitude(FILE *f, int value)
476 {
477         char s_longitude[24];
478         int l_decimal = 0;
479         int l_below_decimal = 0;
480
481         l_decimal = value / 10000;
482         if (value < 0) {
483                 if (l_decimal == 0)
484                         snprintf(s_longitude, sizeof(s_longitude), "-%.3d.", l_decimal);
485                 else
486                         snprintf(s_longitude, sizeof(s_longitude), "%.3d.", l_decimal);
487         } else {
488                 snprintf(s_longitude, sizeof(s_longitude), "+%.3d.", l_decimal);
489         }
490
491         l_below_decimal = value - (l_decimal * 10000);
492         if (l_below_decimal < 0)
493                 l_below_decimal = -l_below_decimal;
494
495         snprintf(&s_longitude[5], sizeof(s_longitude) - 5, "%.4d", l_below_decimal);
496
497         write_tag(f, s_longitude);
498 }
499
500 #define D_GEOGRAPH "\xA9xyz"
501 // 0x0012 -> latitude(8) + longitude(9) + seperator(1) = 18
502 // 0x15c7 -> encode in english
503 #define D_INFO_GEOGRAPH 0x001215c7
504
505 gboolean _mmcamcorder_write_geodata(FILE *f, _MMCamcorderLocationInfo info)
506 {
507         gint64 current_pos, pos;
508
509         MMCAM_LOG_INFO("");
510
511         if ((pos = ftello(f)) < 0) {
512                 MMCAM_LOG_ERROR("ftello() returns negative value");
513                 return FALSE;
514         }
515
516         if (!write_to_32(f, 0))                 //size
517                 return FALSE;
518         // tag -> .xyz
519         if (!write_tag(f, D_GEOGRAPH))  // type
520                 return FALSE;
521
522         if (!write_to_32(f, D_INFO_GEOGRAPH))
523                 return FALSE;
524
525         _mmcamcorder_write_Latitude(f, info.latitude);
526         _mmcamcorder_write_Longitude(f, info.longitude);
527
528         FPUTC_CHECK(0x2F, f);
529
530         if ((current_pos = ftello(f)) < 0) {
531                 MMCAM_LOG_ERROR("ftello() returns negative value");
532                 return FALSE;
533         }
534
535         if (!_mmcamcorder_update_size(f, pos, current_pos))
536                 return FALSE;
537
538         return TRUE;
539 }
540
541
542 gboolean _mmcamcorder_write_udta(FILE *f, int gps_enable, _MMCamcorderLocationInfo info, _MMCamcorderLocationInfo geotag)
543 {
544         gint64 current_pos, pos;
545
546         MMCAM_LOG_INFO("gps enable : %d", gps_enable);
547         if (gps_enable == FALSE) {
548                 MMCAM_LOG_INFO("no need to write udta");
549                 return TRUE;
550         }
551
552         if ((pos = ftello(f)) < 0) {
553                 MMCAM_LOG_ERROR("ftello() returns negative value");
554                 return FALSE;
555         }
556
557         /* size */
558         if (!write_to_32(f, 0)) {
559                 MMCAM_LOG_ERROR("failed to write size");
560                 return FALSE;
561         }
562
563         /* type */
564         if (!write_tag(f, "udta")) {
565                 MMCAM_LOG_ERROR("failed to write type udta");
566                 return FALSE;
567         }
568
569         if (gps_enable) {
570                 if (!_mmcamcorder_write_loci(f, info)) {
571                         MMCAM_LOG_ERROR("failed to write loci");
572                         return FALSE;
573                 }
574
575                 if (!_mmcamcorder_write_geodata(f, geotag)) {
576                         MMCAM_LOG_ERROR("failed to write geodata");
577                         return FALSE;
578                 }
579         }
580
581         if ((current_pos = ftello(f)) < 0) {
582                 MMCAM_LOG_ERROR("ftello() returns negative value");
583                 return FALSE;
584         }
585
586         if (!_mmcamcorder_update_size(f, pos, current_pos)) {
587                 MMCAM_LOG_ERROR("failed to update size");
588                 return FALSE;
589         }
590
591         MMCAM_LOG_INFO("done");
592
593         return TRUE;
594 }
595
596
597 guint64 _mmcamcorder_get_container_size(const guchar *size)
598 {
599         guint64 result = 0;
600         guint64 temp = 0;
601
602         temp = size[0];
603         result = temp << 24;
604         temp = size[1];
605         result = result | (temp << 16);
606         temp = size[2];
607         result = result | (temp << 8);
608         result = result | size[3];
609
610         MMCAM_LOG_INFO("result : %"G_GUINT64_FORMAT, result);
611
612         return result;
613 }
614
615
616 guint64 _mmcamcorder_get_container_size64(const guchar *size)
617 {
618         guint64 result = 0;
619         guint64 temp = 0;
620
621         temp = size[0];
622         result = temp << 56;
623         temp = size[1];
624         result = result | (temp << 48);
625         temp = size[2];
626         result = result | (temp << 40);
627         temp = size[3];
628         result = result | (temp << 32);
629         temp = size[4];
630         result = result | (temp << 24);
631         temp = size[5];
632         result = result | (temp << 16);
633         temp = size[6];
634         result = result | (temp << 8);
635         result = result | size[7];
636
637         MMCAM_LOG_INFO("result : %"G_GUINT64_FORMAT, result);
638
639         return result;
640 }
641
642
643 gboolean _mmcamcorder_update_composition_matrix(FILE *f, int orientation)
644 {
645         /* for 0 degree */
646         guint32 a = 0x00010000;
647         guint32 b = 0;
648         guint32 c = 0;
649         guint32 d = 0x00010000;
650
651         switch (orientation) {
652         case MM_CAMCORDER_TAG_VIDEO_ORT_90:/* 90 degree */
653                 a = 0;
654                 b = 0x00010000;
655                 c = 0xffff0000;
656                 d = 0;
657                 break;
658         case MM_CAMCORDER_TAG_VIDEO_ORT_180:/* 180 degree */
659                 a = 0xffff0000;
660                 d = 0xffff0000;
661                 break;
662         case MM_CAMCORDER_TAG_VIDEO_ORT_270:/* 270 degree */
663                 a = 0;
664                 b = 0xffff0000;
665                 c = 0x00010000;
666                 d = 0;
667                 break;
668         case MM_CAMCORDER_TAG_VIDEO_ORT_NONE:/* 0 degree */
669         default:
670                 break;
671         }
672
673         write_to_32(f, a);
674         write_to_32(f, b);
675         write_to_32(f, 0);
676         write_to_32(f, c);
677         write_to_32(f, d);
678         write_to_32(f, 0);
679         write_to_32(f, 0);
680         write_to_32(f, 0);
681         write_to_32(f, 0x40000000);
682
683         MMCAM_LOG_INFO("orientation : %d, write data 0x%x 0x%x 0x%x 0x%x",
684                                    orientation, a, b, c, d);
685
686         return TRUE;
687 }
688
689
690 static int __mmcamcorder_storage_supported_cb(int storage_id, storage_type_e type,
691         storage_state_e state, const char *path, void *user_data)
692 {
693         _MMCamcorderStorageInfo *info = (_MMCamcorderStorageInfo *)user_data;
694
695         if (!info) {
696                 MMCAM_LOG_ERROR("NULL info");
697                 return FALSE;
698         }
699
700         if (type == info->type) {
701                 info->id = storage_id;
702                 return FALSE;
703         }
704
705         return TRUE;
706 }
707
708
709 int _mmcamcorder_get_storage_validity(MMHandleType handle, const char *filename, guint64 min_space, gboolean *storage_validity)
710 {
711         int ret = MM_ERROR_NONE;
712         int err = 0;
713         char *dir_name = NULL;
714         guint64 free_space = 0;
715         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
716
717         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
718         mmf_return_val_if_fail(storage_validity, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
719
720         if (!filename) {
721                 MMCAM_LOG_WARNING("NULL filename, but keep going...");
722                 *storage_validity = TRUE;
723                 return MM_ERROR_NONE;
724         }
725
726         dir_name = g_path_get_dirname(filename);
727         mmf_return_val_if_fail(dir_name, MM_ERROR_OUT_OF_STORAGE);
728
729         err = _mmcamcorder_get_storage_info(dir_name, hcamcorder->root_directory, &hcamcorder->storage_info);
730         if (err != 0) {
731                 MMCAM_LOG_ERROR("get storage info failed");
732                 ret = MM_ERROR_CAMCORDER_INTERNAL;
733                 goto _CHECK_DONE;
734         }
735
736         err = _mmcamcorder_get_freespace(hcamcorder->storage_info.type, &free_space);
737         if (err != 0) {
738                 MMCAM_LOG_ERROR("get free space failed");
739                 ret = MM_ERROR_CAMCORDER_INTERNAL;
740                 goto _CHECK_DONE;
741         }
742
743         MMCAM_LOG_WARNING("current free space - %s [%" G_GUINT64_FORMAT "]", dir_name, free_space);
744
745 _CHECK_DONE:
746         g_free(dir_name);
747
748         if (ret == MM_ERROR_NONE && free_space > min_space) {
749                 *storage_validity = TRUE;
750                 MMCAM_LOG_INFO("validity and free space of storage : OK");
751         } else {
752                 *storage_validity = FALSE;
753                 MMCAM_LOG_ERROR("OUT of STORAGE [err:%d or free space [%"G_GUINT64_FORMAT"] is smaller than [%"G_GUINT64_FORMAT"]",
754                         err, free_space, min_space);
755         }
756
757         return ret;
758 }
759
760
761 void _mmcamcorder_adjust_recording_max_size(const char *filename, guint64 *max_size)
762 {
763         int file_system_type = 0;
764         char *dir_name = NULL;
765
766         mmf_return_if_fail(max_size);
767         mmf_return_if_fail(filename);
768
769         dir_name = g_path_get_dirname(filename);
770         mmf_return_if_fail(dir_name);
771
772         if (_mmcamcorder_get_file_system_type(dir_name, &file_system_type) == 0) {
773                 /* MSDOS_SUPER_MAGIC : 0x4d44 */
774                 if (file_system_type == MSDOS_SUPER_MAGIC &&
775                         (*max_size == 0 || *max_size > FAT32_FILE_SYSTEM_MAX_SIZE)) {
776                         MMCAM_LOG_WARNING("FAT32 and too large max[%"G_GUINT64_FORMAT"], set max as %lu",
777                                 *max_size, FAT32_FILE_SYSTEM_MAX_SIZE);
778                         *max_size = FAT32_FILE_SYSTEM_MAX_SIZE;
779                 } else {
780                         MMCAM_LOG_WARNING("file system 0x%x, max size %"G_GUINT64_FORMAT,
781                                 file_system_type, *max_size);
782                 }
783         }
784
785         g_free(dir_name);
786 }
787
788
789 int _mmcamcorder_get_storage_info(const gchar *path, const gchar *root_directory, _MMCamcorderStorageInfo *info)
790 {
791         int ret = 0;
792         struct stat stat_path;
793         struct stat stat_root;
794
795         if (!path || !root_directory || !info) {
796                 MMCAM_LOG_ERROR("invalid parameter %p %p %p", path, root_directory, info);
797                 return -1;
798         }
799
800         if (strlen(root_directory) > 0) {
801                 if (stat(path, &stat_path) != 0) {
802                         MMCAM_LOG_ERROR("failed to stat for [%s][errno %d]", path, errno);
803                         return -1;
804                 }
805
806                 if (stat(root_directory, &stat_root) != 0) {
807                         MMCAM_LOG_ERROR("failed to stat for [%s][errno %d]", root_directory, errno);
808                         return -1;
809                 }
810
811                 if (stat_path.st_dev == stat_root.st_dev)
812                         info->type = STORAGE_TYPE_INTERNAL;
813                 else
814                         info->type = STORAGE_TYPE_EXTERNAL;
815         } else {
816                 info->type = STORAGE_TYPE_INTERNAL;
817                 MMCAM_LOG_WARNING("invalid length of root directory, assume that it's internal storage.");
818         }
819
820         ret = storage_foreach_device_supported((storage_device_supported_cb)__mmcamcorder_storage_supported_cb, info);
821         if (ret != STORAGE_ERROR_NONE) {
822                 MMCAM_LOG_ERROR("storage_foreach_device_supported failed 0x%x", ret);
823                 return -1;
824         }
825
826         MMCAM_LOG_INFO("storage info - type %d, id %d", info->type, info->id);
827
828         return 0;
829 }
830
831
832 int _mmcamcorder_get_freespace(storage_type_e type, guint64 *free_space)
833 {
834         int ret = 0;
835         struct statvfs vfs;
836
837         if (type == STORAGE_TYPE_INTERNAL)
838                 ret = storage_get_internal_memory_size(&vfs);
839         else
840                 ret = storage_get_external_memory_size(&vfs);
841
842         if (ret != STORAGE_ERROR_NONE) {
843                 *free_space = 0;
844                 MMCAM_LOG_ERROR("get memory size failed [type %d] 0x%x", type, ret);
845                 return -1;
846         }
847
848         *free_space = vfs.f_bsize * vfs.f_bavail;
849         /*
850         MMCAM_LOG_INFO("vfs.f_bsize [%lu], vfs.f_bavail [%lu]", vfs.f_bsize, vfs.f_bavail);
851         MMCAM_LOG_INFO("memory size %"G_GUINT64_FORMAT" [%s]", *free_space, path);
852         */
853         return 0;
854 }
855
856
857 int _mmcamcorder_get_file_system_type(const gchar *path, int *file_system_type)
858 {
859         struct statfs fs;
860
861         g_assert(path);
862
863         if (!g_file_test(path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
864                 MMCAM_LOG_INFO("File(%s) doesn't exist.", path);
865                 return -2;
866         }
867
868         if (-1 == statfs(path, &fs)) {
869                 MMCAM_LOG_INFO("statfs failed.(%s)", path);
870                 return -1;
871         }
872
873         *file_system_type = (int)fs.f_type;
874
875         return 0;
876 }
877
878
879 int _mmcamcorder_get_camera_id(int device_type, int *camera_id)
880 {
881         int ret = MM_ERROR_NONE;
882         MMCamPreset info = {.videodev_type = device_type};
883         MMHandleType handle = NULL;
884         mmf_camcorder_t *hcamcorder = NULL;
885         type_int_array *input_index = NULL;
886
887         mmf_return_val_if_fail(camera_id, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
888
889         ret = _mmcamcorder_create(&handle, &info);
890         if (ret != MM_ERROR_NONE) {
891                 MMCAM_LOG_ERROR("_mmcamcorder_create failed[0x%x]", ret);
892                 return ret;
893         }
894
895         hcamcorder = MMF_CAMCORDER(handle);
896
897         _mmcamcorder_conf_get_value_int_array(hcamcorder->conf_ctrl,
898                 CONFIGURE_CATEGORY_CTRL_CAMERA,
899                 "InputIndex", &input_index);
900         if (!input_index) {
901                 MMCAM_LOG_ERROR("Get input index failed");
902                 ret = MM_ERROR_CAMCORDER_INTERNAL;
903                 goto _GET_CAMERA_ID_OUT;
904         }
905
906         *camera_id = input_index->default_value;
907
908         MMCAM_LOG_INFO("device type[%d] -> camera id[%d]", device_type, *camera_id);
909
910 _GET_CAMERA_ID_OUT:
911         _mmcamcorder_destroy(handle);
912
913         return ret;
914 }
915
916
917 int _mmcamcorder_get_device_led_brightness(GDBusConnection *conn, int *brightness)
918 {
919         int get_value = 0;
920         int ret = MM_ERROR_NONE;
921         GVariant *params = NULL;
922         GVariant *result = NULL;
923
924         ret = __gdbus_method_call_sync(conn, "org.tizen.system.deviced",
925                 "/Org/Tizen/System/DeviceD/Led", "org.tizen.system.deviced.Led",
926                 "GetBrightnessForCamera", params, &result, TRUE);
927         if (ret != MM_ERROR_NONE) {
928                 MMCAM_LOG_ERROR("Dbus Call on Client Error");
929                 return ret;
930         }
931
932         if (result) {
933                 g_variant_get(result, "(i)", &get_value);
934                 *brightness = get_value;
935                 MMCAM_LOG_INFO("flash brightness : %d", *brightness);
936                 g_variant_unref(result);
937         } else {
938                 MMCAM_LOG_ERROR("replied result is null");
939                 ret = MM_ERROR_CAMCORDER_INTERNAL;
940         }
941
942         return ret;
943 }
944
945
946 int _mmcamcorder_send_sound_play_message(GDBusConnection *conn, _MMCamcorderGDbusCbInfo *gdbus_info,
947         const char *sample_name, const char *stream_role, const char *volume_gain, int sync_play)
948 {
949         int get_value = 0;
950         int ret = MM_ERROR_NONE;
951         GVariant *params = NULL;
952         GVariant *result = NULL;
953         guint subs_id = 0;
954
955         if (!conn || !gdbus_info) {
956                 MMCAM_LOG_ERROR("Invalid parameter %p %p", conn, gdbus_info);
957                 return MM_ERROR_CAMCORDER_INTERNAL;
958         }
959
960         params = g_variant_new("(sss)", sample_name, stream_role, volume_gain);
961
962         ret = __gdbus_method_call_sync(conn, "org.pulseaudio.Server",
963                 "/org/pulseaudio/SoundPlayer", "org.pulseaudio.SoundPlayer",
964                 "SamplePlay", params, &result, TRUE);
965         if (ret != MM_ERROR_NONE) {
966                 MMCAM_LOG_ERROR("Dbus Call on Client Error");
967                 return ret;
968         }
969
970         if (result) {
971                 g_variant_get(result, "(i)", &get_value);
972                 MMCAM_LOG_INFO("played index : %d", get_value);
973                 g_variant_unref(result);
974         } else {
975                 MMCAM_LOG_ERROR("replied result is null");
976                 return MM_ERROR_CAMCORDER_INTERNAL;
977         }
978
979         g_mutex_lock(&gdbus_info->sync_mutex);
980
981         if (gdbus_info->subscribe_id > 0) {
982                 MMCAM_LOG_WARNING("subscribe_id[%u] is remained. remove it.", gdbus_info->subscribe_id);
983
984                 g_dbus_connection_signal_unsubscribe(conn, gdbus_info->subscribe_id);
985
986                 gdbus_info->subscribe_id = 0;
987         }
988
989         gdbus_info->is_playing = TRUE;
990         gdbus_info->param = get_value;
991
992         ret = __gdbus_subscribe_signal(conn,
993                 "/org/pulseaudio/SoundPlayer", "org.pulseaudio.SoundPlayer", "EOS",
994                 __gdbus_stream_eos_cb, &subs_id, gdbus_info);
995
996         if (ret == MM_ERROR_NONE)
997                 gdbus_info->subscribe_id = subs_id;
998
999         g_mutex_unlock(&gdbus_info->sync_mutex);
1000
1001         if (sync_play && ret == MM_ERROR_NONE)
1002                 ret = __gdbus_wait_for_cb_return(gdbus_info, G_DBUS_TIMEOUT);
1003
1004         return ret;
1005 }
1006
1007
1008 void _mmcamcorder_request_dpm_popup(GDBusConnection *conn, const char *restricted_policy)
1009 {
1010         int ret = MM_ERROR_NONE;
1011         gboolean get_value = 0;
1012         GVariant *params = NULL;
1013         GVariant *result = NULL;
1014
1015         if (!conn || !restricted_policy) {
1016                 MMCAM_LOG_ERROR("Invalid parameter %p %p", conn, restricted_policy);
1017                 return;
1018         }
1019
1020         params = g_variant_new("(s)", restricted_policy);
1021
1022         ret = __gdbus_method_call_sync(conn,
1023                 "org.tizen.DevicePolicyManager",
1024                 "/org/tizen/DevicePolicyManager/Syspopup",
1025                 "org.tizen.DevicePolicyManager.Syspopup",
1026                 "show", params, &result, TRUE);
1027         if (ret != MM_ERROR_NONE) {
1028                 MMCAM_LOG_ERROR("Dbus Call on Client Error 0x%x", ret);
1029                 return;
1030         }
1031
1032         if (result) {
1033                 g_variant_get(result, "(b)", &get_value);
1034                 MMCAM_LOG_INFO("request result : %d", get_value);
1035                 g_variant_unref(result);
1036         } else {
1037                 MMCAM_LOG_ERROR("replied result is null");
1038         }
1039
1040         return;
1041 }
1042
1043
1044 int _mmcamcorder_get_file_size(const char *filename, guint64 *size)
1045 {
1046         struct stat buf;
1047
1048         if (stat(filename, &buf) != 0)
1049                 return -1;
1050         *size = (guint64)buf.st_size;
1051         return 1;
1052 }
1053
1054
1055 void _mmcamcorder_remove_buffer_probe(MMHandleType handle, _MMCamcorderHandlerCategory category)
1056 {
1057         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
1058         GList *list = NULL;
1059         MMCamcorderHandlerItem *item = NULL;
1060
1061         mmf_return_if_fail(hcamcorder);
1062
1063         if (!hcamcorder->buffer_probes) {
1064                 MMCAM_LOG_WARNING("list for buffer probe is NULL");
1065                 return;
1066         }
1067
1068         MMCAM_LOG_INFO("start - category : 0x%x", category);
1069
1070         list = hcamcorder->buffer_probes;
1071         while (list) {
1072                 item = list->data;
1073                 if (!item) {
1074                         MMCAM_LOG_ERROR("Remove buffer probe failed, the item is NULL");
1075                         list = g_list_next(list);
1076                         continue;
1077                 }
1078
1079                 if (item->category & category) {
1080                         if (item->object && GST_IS_PAD(item->object)) {
1081                                 MMCAM_LOG_INFO("Remove buffer probe on [%s:%s] - [ID : %lu], [Category : %x]",
1082                                         GST_DEBUG_PAD_NAME(item->object), item->handler_id,  item->category);
1083                                 gst_pad_remove_probe(GST_PAD(item->object), item->handler_id);
1084                         } else {
1085                                 MMCAM_LOG_WARNING("Remove buffer probe failed, the pad is null or not pad, just remove item from list and free it");
1086                         }
1087
1088                         list = g_list_next(list);
1089                         hcamcorder->buffer_probes = g_list_remove(hcamcorder->buffer_probes, item);
1090                         SAFE_G_FREE(item);
1091                 } else {
1092                         MMCAM_LOG_INFO("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
1093                         list = g_list_next(list);
1094                 }
1095         }
1096
1097         if (category == _MMCAMCORDER_HANDLER_CATEGORY_ALL) {
1098                 g_list_free(hcamcorder->buffer_probes);
1099                 hcamcorder->buffer_probes = NULL;
1100         }
1101
1102         MMCAM_LOG_INFO("done");
1103
1104         return;
1105 }
1106
1107
1108 void _mmcamcorder_remove_one_buffer_probe(MMHandleType handle, void *object)
1109 {
1110         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
1111         GList *list = NULL;
1112         MMCamcorderHandlerItem *item = NULL;
1113
1114         mmf_return_if_fail(hcamcorder);
1115
1116         if (!hcamcorder->buffer_probes) {
1117                 MMCAM_LOG_WARNING("list for buffer probe is NULL");
1118                 return;
1119         }
1120
1121         MMCAM_LOG_INFO("start - object : %p", object);
1122
1123         list = hcamcorder->buffer_probes;
1124         while (list) {
1125                 item = list->data;
1126                 if (!item) {
1127                         MMCAM_LOG_ERROR("Remove buffer probe failed, the item is NULL");
1128                         list = g_list_next(list);
1129                         continue;
1130                 }
1131
1132                 if (item->object && item->object == object) {
1133                         if (GST_IS_PAD(item->object)) {
1134                                 MMCAM_LOG_INFO("Remove buffer probe on [%s:%s] - [ID : %lu], [Category : %x]",
1135                                         GST_DEBUG_PAD_NAME(item->object), item->handler_id,  item->category);
1136                                 gst_pad_remove_probe(GST_PAD(item->object), item->handler_id);
1137                         } else {
1138                                 MMCAM_LOG_WARNING("Remove buffer probe failed, the pad is null or not pad, just remove item from list and free it");
1139                         }
1140
1141                         list = g_list_next(list);
1142                         hcamcorder->buffer_probes = g_list_remove(hcamcorder->buffer_probes, item);
1143                         SAFE_G_FREE(item);
1144
1145                         break;
1146                 } else {
1147                         MMCAM_LOG_INFO("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
1148                         list = g_list_next(list);
1149                 }
1150         }
1151
1152         MMCAM_LOG_INFO("done");
1153
1154         return;
1155 }
1156
1157
1158 void _mmcamcorder_remove_event_probe(MMHandleType handle, _MMCamcorderHandlerCategory category)
1159 {
1160         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
1161         GList *list = NULL;
1162         MMCamcorderHandlerItem *item = NULL;
1163
1164         mmf_return_if_fail(hcamcorder);
1165
1166         if (!hcamcorder->event_probes) {
1167                 MMCAM_LOG_WARNING("list for event probe is NULL");
1168                 return;
1169         }
1170
1171         MMCAM_LOG_INFO("start - category : 0x%x", category);
1172
1173         list = hcamcorder->event_probes;
1174         while (list) {
1175                 item = list->data;
1176                 if (!item) {
1177                         MMCAM_LOG_ERROR("Remove event probe failed, the item is NULL");
1178                         list = g_list_next(list);
1179                         continue;
1180                 }
1181
1182                 if (item->category & category) {
1183                         if (item->object && GST_IS_PAD(item->object)) {
1184                                 MMCAM_LOG_INFO("Remove event probe on [%s:%s] - [ID : %lu], [Category : %x]",
1185                                         GST_DEBUG_PAD_NAME(item->object), item->handler_id,  item->category);
1186                                 gst_pad_remove_probe(GST_PAD(item->object), item->handler_id);
1187                         } else {
1188                                 MMCAM_LOG_WARNING("Remove event probe failed, the pad is null or not pad, just remove item from list and free it");
1189                         }
1190
1191                         list = g_list_next(list);
1192                         hcamcorder->event_probes = g_list_remove(hcamcorder->event_probes, item);
1193                         SAFE_G_FREE(item);
1194                 } else {
1195                         MMCAM_LOG_INFO("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
1196                         list = g_list_next(list);
1197                 }
1198         }
1199
1200         if (category == _MMCAMCORDER_HANDLER_CATEGORY_ALL) {
1201                 g_list_free(hcamcorder->event_probes);
1202                 hcamcorder->event_probes = NULL;
1203         }
1204
1205         MMCAM_LOG_INFO("done");
1206
1207         return;
1208 }
1209
1210
1211 void _mmcamcorder_disconnect_signal(MMHandleType handle, _MMCamcorderHandlerCategory category)
1212 {
1213         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
1214         GList *list = NULL;
1215         MMCamcorderHandlerItem *item = NULL;
1216
1217         mmf_return_if_fail(hcamcorder);
1218
1219         if (!hcamcorder->signals) {
1220                 MMCAM_LOG_WARNING("list for signal is NULL");
1221                 return;
1222         }
1223
1224         MMCAM_LOG_INFO("start - category : 0x%x", category);
1225
1226         list = hcamcorder->signals;
1227         while (list) {
1228                 item = list->data;
1229                 if (!item) {
1230                         MMCAM_LOG_ERROR("Fail to Disconnecting signal, the item is NULL");
1231                         list = g_list_next(list);
1232                         continue;
1233                 }
1234
1235                 if (item->category & category) {
1236                         if (item->object && GST_IS_ELEMENT(item->object)) {
1237                                 if (g_signal_handler_is_connected(item->object, item->handler_id)) {
1238                                         MMCAM_LOG_INFO("Disconnect signal from [%s] : [ID : %lu], [Category : %x]",
1239                                                 GST_OBJECT_NAME(item->object), item->handler_id, item->category);
1240                                         g_signal_handler_disconnect(item->object, item->handler_id);
1241                                 } else {
1242                                         MMCAM_LOG_WARNING("Signal was not connected, cannot disconnect it :  [%s]  [ID : %lu], [Category : %x]",
1243                                                 GST_OBJECT_NAME(item->object), item->handler_id, item->category);
1244                                 }
1245                         } else {
1246                                 MMCAM_LOG_ERROR("Fail to Disconnecting signal, the element is null or not element, just remove item from list and free it");
1247                         }
1248
1249                         list = g_list_next(list);
1250                         hcamcorder->signals = g_list_remove(hcamcorder->signals, item);
1251                         SAFE_G_FREE(item);
1252                 } else {
1253                         MMCAM_LOG_INFO("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
1254                         list = g_list_next(list);
1255                 }
1256         }
1257
1258         if (category == _MMCAMCORDER_HANDLER_CATEGORY_ALL) {
1259                 g_list_free(hcamcorder->signals);
1260                 hcamcorder->signals = NULL;
1261         }
1262
1263         MMCAM_LOG_INFO("done");
1264
1265         return;
1266 }
1267
1268
1269 void _mmcamcorder_remove_all_handlers(MMHandleType handle,  _MMCamcorderHandlerCategory category)
1270 {
1271         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
1272
1273         MMCAM_LOG_INFO("ENTER");
1274
1275         if (hcamcorder->signals)
1276                 _mmcamcorder_disconnect_signal((MMHandleType)hcamcorder, category);
1277         if (hcamcorder->event_probes)
1278                 _mmcamcorder_remove_event_probe((MMHandleType)hcamcorder, category);
1279         if (hcamcorder->buffer_probes)
1280                 _mmcamcorder_remove_buffer_probe((MMHandleType)hcamcorder, category);
1281
1282         MMCAM_LOG_INFO("LEAVE");
1283 }
1284
1285
1286 void _mmcamcorder_element_release_noti(gpointer data, GObject *where_the_object_was)
1287 {
1288         int i = 0;
1289         _MMCamcorderSubContext *sc = (_MMCamcorderSubContext *)data;
1290
1291         mmf_return_if_fail(sc);
1292         mmf_return_if_fail(sc->element);
1293
1294         for (i = 0 ; i < _MMCAMCORDER_PIPELINE_ELEMENT_NUM ; i++) {
1295                 if (sc->element[i].gst && (G_OBJECT(sc->element[i].gst) == where_the_object_was)) {
1296                         MMCAM_LOG_WARNING("The element[%d][%p] is finalized", sc->element[i].id, sc->element[i].gst);
1297                         sc->element[i].gst = NULL;
1298                         sc->element[i].id = _MMCAMCORDER_NONE;
1299                         return;
1300                 }
1301         }
1302
1303         mmf_return_if_fail(sc->encode_element);
1304
1305         for (i = 0 ; i < _MMCAMCORDER_ENCODE_PIPELINE_ELEMENT_NUM ; i++) {
1306                 if (sc->encode_element[i].gst && (G_OBJECT(sc->encode_element[i].gst) == where_the_object_was)) {
1307                         MMCAM_LOG_WARNING("The encode element[%d][%p] is finalized", sc->encode_element[i].id, sc->encode_element[i].gst);
1308                         sc->encode_element[i].gst = NULL;
1309                         sc->encode_element[i].id = _MMCAMCORDER_ENCODE_NONE;
1310                         return;
1311                 }
1312         }
1313
1314         MMCAM_LOG_WARNING("there is no matching element %p", where_the_object_was);
1315
1316         return;
1317 }
1318
1319
1320 #ifdef _MMCAMCORDER_ENABLE_IDLE_MESSAGE_CALLBACK
1321 gboolean _mmcamcorder_msg_callback(void *data)
1322 {
1323         _MMCamcorderMsgItem *item = (_MMCamcorderMsgItem*)data;
1324         mmf_camcorder_t *hcamcorder = NULL;
1325         mmf_return_val_if_fail(item, FALSE);
1326
1327         g_mutex_lock(&item->lock);
1328
1329         hcamcorder = MMF_CAMCORDER(item->handle);
1330         if (hcamcorder == NULL) {
1331                 MMCAM_LOG_WARNING("msg id:0x%x, item:%p, handle is NULL", item->id, item);
1332                 goto MSG_CALLBACK_DONE;
1333         }
1334
1335         /*MMCAM_LOG_INFO("msg id:%x, msg_cb:%p, msg_data:%p, item:%p", item->id, hcamcorder->msg_cb, hcamcorder->msg_data, item);*/
1336
1337         _MMCAMCORDER_LOCK(hcamcorder);
1338
1339         /* remove item from msg data */
1340         if (hcamcorder->msg_data) {
1341                 /*MMCAM_LOG_INFO("remove item %p", item);*/
1342                 hcamcorder->msg_data = g_list_remove(hcamcorder->msg_data, item);
1343         } else {
1344                 MMCAM_LOG_WARNING("msg_data is NULL but item[%p] will be removed", item);
1345         }
1346
1347         _MMCAMCORDER_UNLOCK(hcamcorder);
1348
1349         _MMCAMCORDER_LOCK_MESSAGE_CALLBACK(hcamcorder);
1350
1351         if ((hcamcorder) && (hcamcorder->msg_cb))
1352                 hcamcorder->msg_cb(item->id, (MMMessageParamType*)(&(item->param)), hcamcorder->msg_cb_param);
1353
1354         _MMCAMCORDER_UNLOCK_MESSAGE_CALLBACK(hcamcorder);
1355
1356         _MMCAMCORDER_SIGNAL(hcamcorder);
1357
1358 MSG_CALLBACK_DONE:
1359         /* release allocated memory */
1360         if (item->id == MM_MESSAGE_CAMCORDER_FACE_DETECT_INFO) {
1361                 MMCamFaceDetectInfo *cam_fd_info = (MMCamFaceDetectInfo *)item->param.data;
1362                 if (cam_fd_info) {
1363                         SAFE_G_FREE(cam_fd_info->face_info);
1364                         SAFE_G_FREE(cam_fd_info);
1365
1366                         item->param.data = NULL;
1367                         item->param.size = 0;
1368                 }
1369         } else if (item->id == MM_MESSAGE_CAMCORDER_VIDEO_CAPTURED || item->id == MM_MESSAGE_CAMCORDER_AUDIO_CAPTURED) {
1370                 MMCamRecordingReport *report = (MMCamRecordingReport *)item->param.data;
1371                 if (report) {
1372                         SAFE_G_FREE(report->recording_filename);
1373                         g_free(report);
1374                         report = NULL;
1375                         item->param.data = NULL;
1376                 }
1377         }
1378
1379         g_mutex_unlock(&item->lock);
1380         g_mutex_clear(&item->lock);
1381
1382         SAFE_G_FREE(item);
1383
1384         /* For not being called again */
1385         return FALSE;
1386 }
1387 #endif /* _MMCAMCORDER_ENABLE_IDLE_MESSAGE_CALLBACK */
1388
1389
1390 gboolean _mmcamcorder_send_message(MMHandleType handle, _MMCamcorderMsgItem *data)
1391 {
1392         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
1393 #ifdef _MMCAMCORDER_ENABLE_IDLE_MESSAGE_CALLBACK
1394         _MMCamcorderMsgItem *item = NULL;
1395 #endif /* _MMCAMCORDER_ENABLE_IDLE_MESSAGE_CALLBACK */
1396
1397         mmf_return_val_if_fail(hcamcorder, FALSE);
1398         mmf_return_val_if_fail(data, FALSE);
1399
1400         switch (data->id) {
1401         case MM_MESSAGE_CAMCORDER_STATE_CHANGED:
1402         case MM_MESSAGE_CAMCORDER_STATE_CHANGED_BY_RM:
1403                 data->param.union_type = MM_MSG_UNION_STATE;
1404                 break;
1405         case MM_MESSAGE_CAMCORDER_RECORDING_STATUS:
1406                 data->param.union_type = MM_MSG_UNION_RECORDING_STATUS;
1407                 break;
1408         case MM_MESSAGE_CAMCORDER_FIRMWARE_UPDATE:
1409                 data->param.union_type = MM_MSG_UNION_FIRMWARE;
1410                 break;
1411         case MM_MESSAGE_CAMCORDER_CURRENT_VOLUME:
1412                 data->param.union_type = MM_MSG_UNION_REC_VOLUME_DB;
1413                 break;
1414         case MM_MESSAGE_CAMCORDER_TIME_LIMIT:
1415         case MM_MESSAGE_CAMCORDER_MAX_SIZE:
1416         case MM_MESSAGE_CAMCORDER_NO_FREE_SPACE:
1417         case MM_MESSAGE_CAMCORDER_ERROR:
1418         case MM_MESSAGE_CAMCORDER_FOCUS_CHANGED:
1419         case MM_MESSAGE_CAMCORDER_CAPTURED:
1420         case MM_MESSAGE_CAMCORDER_VIDEO_CAPTURED:
1421         case MM_MESSAGE_CAMCORDER_AUDIO_CAPTURED:
1422         case MM_MESSAGE_READY_TO_RESUME:
1423         default:
1424                 data->param.union_type = MM_MSG_UNION_CODE;
1425                 break;
1426         }
1427
1428 #ifdef _MMCAMCORDER_ENABLE_IDLE_MESSAGE_CALLBACK
1429         item = g_malloc(sizeof(_MMCamcorderMsgItem));
1430
1431         memcpy(item, data, sizeof(_MMCamcorderMsgItem));
1432         item->handle = handle;
1433         g_mutex_init(&item->lock);
1434
1435         _MMCAMCORDER_LOCK(handle);
1436         hcamcorder->msg_data = g_list_append(hcamcorder->msg_data, item);
1437         /*MMCAM_LOG_INFO("item[%p]", item);*/
1438
1439         /* Use DEFAULT priority */
1440         g_idle_add_full(G_PRIORITY_DEFAULT, _mmcamcorder_msg_callback, item, NULL);
1441
1442         _MMCAMCORDER_UNLOCK(handle);
1443 #else /* _MMCAMCORDER_ENABLE_IDLE_MESSAGE_CALLBACK */
1444         _MMCAMCORDER_LOCK_MESSAGE_CALLBACK(hcamcorder);
1445
1446         if (hcamcorder->msg_cb)
1447                 hcamcorder->msg_cb(data->id, (MMMessageParamType*)(&(data->param)), hcamcorder->msg_cb_param);
1448         else
1449                 MMCAM_LOG_INFO("message callback is NULL. message id %d", data->id);
1450
1451         _MMCAMCORDER_UNLOCK_MESSAGE_CALLBACK(hcamcorder);
1452
1453         /* release allocated memory */
1454         if (data->id == MM_MESSAGE_CAMCORDER_FACE_DETECT_INFO) {
1455                 MMCamFaceDetectInfo *cam_fd_info = (MMCamFaceDetectInfo *)data->param.data;
1456                 if (cam_fd_info) {
1457                         SAFE_G_FREE(cam_fd_info->face_info);
1458                         data->param.data = NULL;
1459                         g_free(cam_fd_info);
1460                 }
1461         } else if (data->id == MM_MESSAGE_CAMCORDER_VIDEO_CAPTURED || data->id == MM_MESSAGE_CAMCORDER_AUDIO_CAPTURED) {
1462                 MMCamRecordingReport *report = (MMCamRecordingReport *)data->param.data;
1463                 if (report) {
1464                         SAFE_G_FREE(report->recording_filename);
1465                         data->param.data = NULL;
1466                         g_free(report);
1467                 }
1468         }
1469 #endif /* _MMCAMCORDER_ENABLE_IDLE_MESSAGE_CALLBACK */
1470
1471         return TRUE;
1472 }
1473
1474
1475 void _mmcamcorder_remove_message_all(MMHandleType handle)
1476 {
1477         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
1478         gboolean ret = TRUE;
1479 #ifdef _MMCAMCORDER_ENABLE_IDLE_MESSAGE_CALLBACK
1480         _MMCamcorderMsgItem *item = NULL;
1481         GList *list = NULL;
1482         gint64 end_time = 0;
1483 #endif /* _MMCAMCORDER_ENABLE_IDLE_MESSAGE_CALLBACK */
1484
1485         mmf_return_if_fail(hcamcorder);
1486
1487         _MMCAMCORDER_LOCK(handle);
1488
1489 #ifdef _MMCAMCORDER_ENABLE_IDLE_MESSAGE_CALLBACK
1490         if (!hcamcorder->msg_data) {
1491                 MMCAM_LOG_INFO("No message data is remained.");
1492         } else {
1493                 list = hcamcorder->msg_data;
1494
1495                 while (list) {
1496                         item = list->data;
1497                         list = g_list_next(list);
1498
1499                         if (!item) {
1500                                 MMCAM_LOG_ERROR("Fail to remove message. The item is NULL");
1501                         } else {
1502                                 if (g_mutex_trylock(&(item->lock))) {
1503                                         ret = g_idle_remove_by_data(item);
1504
1505                                         MMCAM_LOG_INFO("remove msg item[%p], ret[%d]", item, ret);
1506
1507                                         if (ret == FALSE) {
1508                                                 item->handle = 0;
1509                                                 MMCAM_LOG_WARNING("failed to remove msg cb for item %p, it will be called later with NULL handle", item);
1510                                         }
1511
1512                                         /* release allocated memory */
1513                                         if (item->id == MM_MESSAGE_CAMCORDER_FACE_DETECT_INFO) {
1514                                                 MMCamFaceDetectInfo *cam_fd_info = (MMCamFaceDetectInfo *)item->param.data;
1515                                                 if (cam_fd_info) {
1516                                                         SAFE_G_FREE(cam_fd_info->face_info);
1517                                                         item->param.size = 0;
1518                                                 }
1519                                                 SAFE_G_FREE(cam_fd_info);
1520                                         } else if (item->id == MM_MESSAGE_CAMCORDER_VIDEO_CAPTURED || item->id == MM_MESSAGE_CAMCORDER_AUDIO_CAPTURED) {
1521                                                 MMCamRecordingReport *report = (MMCamRecordingReport *)item->param.data;
1522                                                 if (report)
1523                                                         SAFE_G_FREE(report->recording_filename);
1524
1525                                                 SAFE_G_FREE(report);
1526                                         }
1527
1528                                         hcamcorder->msg_data = g_list_remove(hcamcorder->msg_data, item);
1529
1530                                         g_mutex_unlock(&(item->lock));
1531
1532                                         if (ret == TRUE) {
1533                                                 g_mutex_clear(&item->lock);
1534
1535                                                 SAFE_G_FREE(item);
1536
1537                                                 MMCAM_LOG_INFO("remove msg done");
1538                                         }
1539                                 } else {
1540                                         MMCAM_LOG_WARNING("item lock failed. it's being called...");
1541
1542                                         end_time = g_get_monotonic_time() + (100 * G_TIME_SPAN_MILLISECOND);
1543
1544                                         if (_MMCAMCORDER_WAIT_UNTIL(handle, end_time))
1545                                                 MMCAM_LOG_WARNING("signal received");
1546                                         else
1547                                                 MMCAM_LOG_WARNING("timeout");
1548                                 }
1549                         }
1550                 }
1551
1552                 g_list_free(hcamcorder->msg_data);
1553                 hcamcorder->msg_data = NULL;
1554         }
1555 #endif /* _MMCAMCORDER_ENABLE_IDLE_MESSAGE_CALLBACK */
1556
1557         /* remove idle function for playing capture sound */
1558         do {
1559                 ret = g_idle_remove_by_data(hcamcorder);
1560                 MMCAM_LOG_INFO("remove idle function for playing capture sound. ret[%d]", ret);
1561         } while (ret);
1562
1563         _MMCAMCORDER_UNLOCK(handle);
1564
1565         return;
1566 }
1567
1568
1569 int _mmcamcorder_get_pixel_format(GstCaps *caps, gboolean is_preview)
1570 {
1571         gchar *caps_string = NULL;
1572         const char *media_type;
1573         const char *format;
1574
1575         mmf_return_val_if_fail(caps != NULL, MM_PIXEL_FORMAT_INVALID);
1576
1577         if (_mmcamcorder_get_log_level() >= MM_CAMCORDER_LOG_LEVEL_DEBUG) {
1578                 caps_string = gst_caps_to_string(caps);
1579                 MMCAM_LOG_DEBUG("caps[%s]", caps_string);
1580                 g_free(caps_string);
1581         }
1582
1583         media_type = gst_structure_get_name(gst_caps_get_structure(caps, 0));
1584         if (!media_type) {
1585                 MMCAM_LOG_ERROR("failed to get media_type");
1586                 return MM_PIXEL_FORMAT_INVALID;
1587         }
1588
1589         if (!strcmp(media_type, "image/jpeg"))
1590                 return (is_preview ? MM_PIXEL_FORMAT_ENCODED_MJPEG : MM_PIXEL_FORMAT_ENCODED);
1591         else if (!strcmp(media_type, "video/x-h264"))
1592                 return MM_PIXEL_FORMAT_ENCODED_H264;
1593         else if (!strcmp(media_type, "video/x-jpeg"))
1594                 return MM_PIXEL_FORMAT_ENCODED_MJPEG;
1595         else if (!strcmp(media_type, "video/x-vp8"))
1596                 return MM_PIXEL_FORMAT_ENCODED_VP8;
1597         else if (!strcmp(media_type, "video/x-vp9"))
1598                 return MM_PIXEL_FORMAT_ENCODED_VP9;
1599
1600         format = gst_structure_get_string(gst_caps_get_structure(caps, 0), "format");
1601         if (!format) {
1602                 caps_string = gst_caps_to_string(caps);
1603                 MMCAM_LOG_ERROR("unsupported caps[%s]", caps_string);
1604                 g_free(caps_string);
1605
1606                 return MM_PIXEL_FORMAT_INVALID;
1607         }
1608
1609         return _mmcamcorder_get_pixtype(GST_STR_FOURCC(format));
1610 }
1611
1612
1613 MMPixelFormatType _mmcamcorder_get_pixel_format2(GstCameraControlImageFormat img_fmt)
1614 {
1615         const MMPixelFormatType pixel_format_table[] = {
1616                 [GST_CAMERA_CONTROL_IMAGE_FORMAT_NV12] = MM_PIXEL_FORMAT_NV12,
1617                 [GST_CAMERA_CONTROL_IMAGE_FORMAT_NV21] = MM_PIXEL_FORMAT_NV21,
1618                 [GST_CAMERA_CONTROL_IMAGE_FORMAT_I420] = MM_PIXEL_FORMAT_I420,
1619                 [GST_CAMERA_CONTROL_IMAGE_FORMAT_YV12] = MM_PIXEL_FORMAT_YV12,
1620                 [GST_CAMERA_CONTROL_IMAGE_FORMAT_YUYV] = MM_PIXEL_FORMAT_YUYV,
1621                 [GST_CAMERA_CONTROL_IMAGE_FORMAT_UYVY] = MM_PIXEL_FORMAT_UYVY,
1622                 [GST_CAMERA_CONTROL_IMAGE_FORMAT_BGRA] = MM_PIXEL_FORMAT_RGBA,
1623                 [GST_CAMERA_CONTROL_IMAGE_FORMAT_ARGB] = MM_PIXEL_FORMAT_ARGB,
1624                 [GST_CAMERA_CONTROL_IMAGE_FORMAT_JPEG] = MM_PIXEL_FORMAT_ENCODED,
1625                 [GST_CAMERA_CONTROL_IMAGE_FORMAT_H264] = MM_PIXEL_FORMAT_ENCODED_H264,
1626                 [GST_CAMERA_CONTROL_IMAGE_FORMAT_MJPEG] = MM_PIXEL_FORMAT_ENCODED_MJPEG,
1627                 [GST_CAMERA_CONTROL_IMAGE_FORMAT_VP8] = MM_PIXEL_FORMAT_ENCODED_VP8,
1628                 [GST_CAMERA_CONTROL_IMAGE_FORMAT_VP9] = MM_PIXEL_FORMAT_ENCODED_VP9,
1629         };
1630
1631         if (img_fmt < GST_CAMERA_CONTROL_IMAGE_FORMAT_NV12 || img_fmt > GST_CAMERA_CONTROL_IMAGE_FORMAT_VP9) {
1632                 MMCAM_LOG_ERROR("invalid format[%d], return default[NV12]", img_fmt);
1633                 return MM_PIXEL_FORMAT_NV12;
1634         }
1635
1636         return pixel_format_table[img_fmt];
1637 }
1638
1639
1640 GstCameraControlImageFormat _mmcamcorder_get_camera_control_image_format(int pixel_format)
1641 {
1642         const GstCameraControlImageFormat img_fmt_table[] = {
1643                 [MM_PIXEL_FORMAT_NV12] = GST_CAMERA_CONTROL_IMAGE_FORMAT_NV12,
1644                 [MM_PIXEL_FORMAT_NV21] = GST_CAMERA_CONTROL_IMAGE_FORMAT_NV21,
1645                 [MM_PIXEL_FORMAT_I420] = GST_CAMERA_CONTROL_IMAGE_FORMAT_I420,
1646                 [MM_PIXEL_FORMAT_YV12] = GST_CAMERA_CONTROL_IMAGE_FORMAT_YV12,
1647                 [MM_PIXEL_FORMAT_YUYV] = GST_CAMERA_CONTROL_IMAGE_FORMAT_YUYV,
1648                 [MM_PIXEL_FORMAT_UYVY] = GST_CAMERA_CONTROL_IMAGE_FORMAT_UYVY,
1649                 [MM_PIXEL_FORMAT_RGBA] = GST_CAMERA_CONTROL_IMAGE_FORMAT_BGRA,
1650                 [MM_PIXEL_FORMAT_ARGB] = GST_CAMERA_CONTROL_IMAGE_FORMAT_ARGB,
1651                 [MM_PIXEL_FORMAT_ENCODED] = GST_CAMERA_CONTROL_IMAGE_FORMAT_JPEG,
1652                 [MM_PIXEL_FORMAT_ENCODED_H264] = GST_CAMERA_CONTROL_IMAGE_FORMAT_H264,
1653                 [MM_PIXEL_FORMAT_ENCODED_MJPEG] = GST_CAMERA_CONTROL_IMAGE_FORMAT_MJPEG,
1654                 [MM_PIXEL_FORMAT_ENCODED_VP8] = GST_CAMERA_CONTROL_IMAGE_FORMAT_VP8,
1655                 [MM_PIXEL_FORMAT_ENCODED_VP9] = GST_CAMERA_CONTROL_IMAGE_FORMAT_VP9
1656         };
1657
1658         if (pixel_format < MM_PIXEL_FORMAT_NV12 || pixel_format > MM_PIXEL_FORMAT_ENCODED_VP9) {
1659                 MMCAM_LOG_ERROR("invalid format[%d], return default[NV12]", pixel_format);
1660                 return GST_CAMERA_CONTROL_IMAGE_FORMAT_NV12;
1661         }
1662
1663         return img_fmt_table[pixel_format];
1664 }
1665
1666
1667 unsigned int _mmcamcorder_get_fourcc(int pixtype, int codectype, int use_zero_copy_format)
1668 {
1669         unsigned int fourcc = 0;
1670
1671         /*MMCAM_LOG_INFO("pixtype(%d)", pixtype);*/
1672
1673         switch (pixtype) {
1674         case MM_PIXEL_FORMAT_NV12:
1675                 if (use_zero_copy_format)
1676                         fourcc = GST_MAKE_FOURCC('S', 'N', '1', '2');
1677                 else
1678                         fourcc = GST_MAKE_FOURCC('N', 'V', '1', '2');
1679
1680                 break;
1681         case MM_PIXEL_FORMAT_NV21:
1682                 if (use_zero_copy_format)
1683                         fourcc = GST_MAKE_FOURCC('S', 'N', '2', '1');
1684                 else
1685                         fourcc = GST_MAKE_FOURCC('N', 'V', '2', '1');
1686
1687                 break;
1688         case MM_PIXEL_FORMAT_YUYV:
1689                 if (use_zero_copy_format)
1690                         fourcc = GST_MAKE_FOURCC('S', 'U', 'Y', 'V');
1691                 else
1692                         fourcc = GST_MAKE_FOURCC('Y', 'U', 'Y', '2');
1693
1694                 break;
1695         case MM_PIXEL_FORMAT_UYVY:
1696                 if (use_zero_copy_format)
1697                         fourcc = GST_MAKE_FOURCC('S', 'Y', 'V', 'Y');
1698                 else
1699                         fourcc = GST_MAKE_FOURCC('U', 'Y', 'V', 'Y');
1700
1701                 break;
1702         case MM_PIXEL_FORMAT_I420:
1703                 if (use_zero_copy_format)
1704                         fourcc = GST_MAKE_FOURCC('S', '4', '2', '0');
1705                 else
1706                         fourcc = GST_MAKE_FOURCC('I', '4', '2', '0');
1707
1708                 break;
1709         case MM_PIXEL_FORMAT_YV12:
1710                 fourcc = GST_MAKE_FOURCC('Y', 'V', '1', '2');
1711                 break;
1712         case MM_PIXEL_FORMAT_422P:
1713                 fourcc = GST_MAKE_FOURCC('4', '2', '2', 'P');
1714                 break;
1715         case MM_PIXEL_FORMAT_RGB565:
1716                 fourcc = GST_MAKE_FOURCC('R', 'G', 'B', 'P');
1717                 break;
1718         case MM_PIXEL_FORMAT_RGB888:
1719                 fourcc = GST_MAKE_FOURCC('R', 'G', 'B', ' ');
1720                 break;
1721         case MM_PIXEL_FORMAT_RGBA:
1722                 fourcc = GST_MAKE_FOURCC('B', 'G', 'R', 'x');
1723                 break;
1724         case MM_PIXEL_FORMAT_ARGB:
1725                 fourcc = GST_MAKE_FOURCC('x', 'R', 'G', 'B');
1726                 break;
1727         case MM_PIXEL_FORMAT_ENCODED:
1728                 if (codectype == MM_IMAGE_CODEC_JPEG) {
1729                         fourcc = GST_MAKE_FOURCC('J', 'P', 'E', 'G');
1730                 } else if (codectype == MM_IMAGE_CODEC_JPEG_SRW) {
1731                         fourcc = GST_MAKE_FOURCC('J', 'P', 'E', 'G'); /*TODO: JPEG+SamsungRAW format */
1732                 } else if (codectype == MM_IMAGE_CODEC_SRW) {
1733                         fourcc = GST_MAKE_FOURCC('J', 'P', 'E', 'G'); /*TODO: SamsungRAW format */
1734                 } else if (codectype == MM_IMAGE_CODEC_PNG) {
1735                         fourcc = GST_MAKE_FOURCC('P', 'N', 'G', ' ');
1736                 } else {
1737                         /* Please let us know what other fourcces are. ex) BMP, GIF?*/
1738                         fourcc = GST_MAKE_FOURCC('J', 'P', 'E', 'G');
1739                 }
1740                 break;
1741         case MM_PIXEL_FORMAT_ITLV_JPEG_UYVY:
1742                 fourcc = GST_MAKE_FOURCC('I', 'T', 'L', 'V');
1743                 break;
1744         case MM_PIXEL_FORMAT_ENCODED_H264:
1745                 fourcc = GST_MAKE_FOURCC('H', '2', '6', '4');
1746                 break;
1747         case MM_PIXEL_FORMAT_INVZ:
1748                 fourcc = GST_MAKE_FOURCC('I', 'N', 'V', 'Z');
1749                 break;
1750         case MM_PIXEL_FORMAT_ENCODED_MJPEG:
1751                 fourcc = GST_MAKE_FOURCC ('M', 'J', 'P', 'G');
1752                 break;
1753         case MM_PIXEL_FORMAT_ENCODED_VP8:
1754                 fourcc = GST_MAKE_FOURCC ('V', 'P', '8', '0');
1755                 break;
1756         case MM_PIXEL_FORMAT_ENCODED_VP9:
1757                 fourcc = GST_MAKE_FOURCC ('V', 'P', '9', '0');
1758                 break;
1759         default:
1760                 MMCAM_LOG_INFO("Not proper pixel type[%d]. Set default - I420", pixtype);
1761                 if (use_zero_copy_format)
1762                         fourcc = GST_MAKE_FOURCC('S', '4', '2', '0');
1763                 else
1764                         fourcc = GST_MAKE_FOURCC('I', '4', '2', '0');
1765
1766                 break;
1767         }
1768
1769         return fourcc;
1770 }
1771
1772
1773 int _mmcamcorder_get_pixtype(unsigned int fourcc)
1774 {
1775         int pixtype = MM_PIXEL_FORMAT_INVALID;
1776         /*
1777         char *pfourcc = (char*)&fourcc;
1778
1779         MMCAM_LOG_INFO("fourcc(%c%c%c%c)",
1780                                    pfourcc[0], pfourcc[1], pfourcc[2], pfourcc[3]);
1781         */
1782
1783         switch (fourcc) {
1784         case GST_MAKE_FOURCC('S', 'N', '1', '2'):
1785                 /* fall through */
1786         case GST_MAKE_FOURCC('N', 'V', '1', '2'):
1787                 pixtype = MM_PIXEL_FORMAT_NV12;
1788                 break;
1789         case GST_MAKE_FOURCC('S', 'N', '2', '1'):
1790                 /* fall through */
1791         case GST_MAKE_FOURCC('N', 'V', '2', '1'):
1792                 pixtype = MM_PIXEL_FORMAT_NV21;
1793                 break;
1794         case GST_MAKE_FOURCC('S', 'U', 'Y', 'V'):
1795                 /* fall through */
1796         case GST_MAKE_FOURCC('Y', 'U', 'Y', 'V'):
1797                 /* fall through */
1798         case GST_MAKE_FOURCC('Y', 'U', 'Y', '2'):
1799                 pixtype = MM_PIXEL_FORMAT_YUYV;
1800                 break;
1801         case GST_MAKE_FOURCC('S', 'Y', 'V', 'Y'):
1802                 /* fall through */
1803         case GST_MAKE_FOURCC('U', 'Y', 'V', 'Y'):
1804                 pixtype = MM_PIXEL_FORMAT_UYVY;
1805                 break;
1806         case GST_MAKE_FOURCC('S', '4', '2', '0'):
1807                 /* fall through */
1808         case GST_MAKE_FOURCC('I', '4', '2', '0'):
1809                 pixtype = MM_PIXEL_FORMAT_I420;
1810                 break;
1811         case GST_MAKE_FOURCC('Y', 'V', '1', '2'):
1812                 pixtype = MM_PIXEL_FORMAT_YV12;
1813                 break;
1814         case GST_MAKE_FOURCC('4', '2', '2', 'P'):
1815                 pixtype = MM_PIXEL_FORMAT_422P;
1816                 break;
1817         case GST_MAKE_FOURCC('R', 'G', 'B', 'P'):
1818                 pixtype = MM_PIXEL_FORMAT_RGB565;
1819                 break;
1820         case GST_MAKE_FOURCC('R', 'G', 'B', '3'):
1821                 pixtype = MM_PIXEL_FORMAT_RGB888;
1822                 break;
1823         case GST_MAKE_FOURCC('A', 'R', 'G', 'B'):
1824                 /* fall through */
1825         case GST_MAKE_FOURCC('x', 'R', 'G', 'B'):
1826                 pixtype = MM_PIXEL_FORMAT_ARGB;
1827                 break;
1828         case GST_MAKE_FOURCC('B', 'G', 'R', 'A'):
1829                 /* fall through */
1830         case GST_MAKE_FOURCC('B', 'G', 'R', 'x'):
1831                 /* fall through */
1832         case GST_MAKE_FOURCC('S', 'R', '3', '2'):
1833                 pixtype = MM_PIXEL_FORMAT_RGBA;
1834                 break;
1835         case GST_MAKE_FOURCC('J', 'P', 'E', 'G'):
1836                 pixtype = MM_PIXEL_FORMAT_ENCODED;
1837                 break;
1838         /*FIXME*/
1839         case GST_MAKE_FOURCC('I', 'T', 'L', 'V'):
1840                 pixtype = MM_PIXEL_FORMAT_ITLV_JPEG_UYVY;
1841                 break;
1842         case GST_MAKE_FOURCC('H', '2', '6', '4'):
1843                 pixtype = MM_PIXEL_FORMAT_ENCODED_H264;
1844                 break;
1845         case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
1846                 pixtype = MM_PIXEL_FORMAT_ENCODED_MJPEG;
1847                 break;
1848         case GST_MAKE_FOURCC ('V', 'P', '8', '0'):
1849                 /* fall through */
1850         case GST_MAKE_FOURCC ('v', 'p', '0', '8'):
1851                 pixtype = MM_PIXEL_FORMAT_ENCODED_VP8;
1852                 break;
1853         case GST_MAKE_FOURCC ('V', 'P', '9', '0'):
1854                 /* fall through */
1855         case GST_MAKE_FOURCC ('v', 'p', '0', '9'):
1856                 pixtype = MM_PIXEL_FORMAT_ENCODED_VP9;
1857                 break;
1858         case GST_MAKE_FOURCC('I', 'N', 'V', 'Z'):
1859                 pixtype = MM_PIXEL_FORMAT_INVZ;
1860                 break;
1861         default:
1862                 MMCAM_LOG_INFO("Not supported fourcc type(%c%c%c%c)", fourcc, fourcc>>8, fourcc>>16, fourcc>>24);
1863                 pixtype = MM_PIXEL_FORMAT_INVALID;
1864                 break;
1865         }
1866
1867         return pixtype;
1868 }
1869
1870
1871 gboolean _mmcamcorder_add_elements_to_bin(GstBin *bin, GList *element_list)
1872 {
1873         GList *local_list = element_list;
1874         _MMCamcorderGstElement *element = NULL;
1875
1876         mmf_return_val_if_fail(bin && local_list, FALSE);
1877
1878         while (local_list) {
1879                 element = (_MMCamcorderGstElement*)local_list->data;
1880                 if (element && element->gst) {
1881                         if (!gst_bin_add(bin, GST_ELEMENT(element->gst))) {
1882                                 MMCAM_LOG_ERROR("Add element [%s] to bin [%s] FAILED",
1883                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
1884                                         GST_ELEMENT_NAME(GST_ELEMENT(bin)));
1885                                 return FALSE;
1886                         } else {
1887                                 MMCAM_LOG_INFO("Add element [%s] to bin [%s] OK",
1888                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
1889                                         GST_ELEMENT_NAME(GST_ELEMENT(bin)));
1890                         }
1891                 }
1892                 local_list = local_list->next;
1893         }
1894
1895         return TRUE;
1896 }
1897
1898 gboolean _mmcamcorder_link_elements(GList *element_list)
1899 {
1900         GList                  *local_list  = element_list;
1901         _MMCamcorderGstElement *element     = NULL;
1902         _MMCamcorderGstElement *pre_element = NULL;
1903
1904         mmf_return_val_if_fail(local_list, FALSE);
1905
1906         pre_element = (_MMCamcorderGstElement*)local_list->data;
1907         local_list = local_list->next;
1908
1909         while (local_list) {
1910                 element = (_MMCamcorderGstElement*)local_list->data;
1911                 if (pre_element && pre_element->gst && element && element->gst) {
1912                         if (_MM_GST_ELEMENT_LINK(GST_ELEMENT(pre_element->gst), GST_ELEMENT(element->gst))) {
1913                                 MMCAM_LOG_INFO("Link [%s] to [%s] OK",
1914                                         GST_ELEMENT_NAME(GST_ELEMENT(pre_element->gst)),
1915                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
1916                         } else {
1917                                 MMCAM_LOG_ERROR("Link [%s] to [%s] FAILED",
1918                                         GST_ELEMENT_NAME(GST_ELEMENT(pre_element->gst)),
1919                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
1920                                 return FALSE;
1921                         }
1922                 }
1923
1924                 pre_element = element;
1925                 local_list = local_list->next;
1926         }
1927
1928         return TRUE;
1929 }
1930
1931 GstCaps *_mmcamcorder_get_video_caps(MMHandleType handle, MMPixelFormatType format, int width, int height, int fps, int rotate)
1932 {
1933         int codec_type = MM_IMAGE_CODEC_JPEG;
1934         guint32 fourcc = 0;
1935         char fourcc_string[sizeof(guint32) + 1];
1936 #ifdef _MMCAMCORDER_PRODUCT_TV
1937         int maxwidth = 0;
1938         int maxheight = 0;
1939         int display_surface_type = MM_DISPLAY_SURFACE_NULL;
1940 #endif /* _MMCAMCORDER_PRODUCT_TV */
1941         gchar *caps_string = NULL;
1942         GstCaps *caps = NULL;;
1943         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1944
1945         switch (format) {
1946         case MM_PIXEL_FORMAT_ENCODED_H264:
1947 #ifdef _MMCAMCORDER_PRODUCT_TV
1948                 mm_camcorder_get_attributes(handle, NULL,
1949                         MMCAM_DISPLAY_SURFACE, &display_surface_type,
1950                         NULL);
1951                 if (display_surface_type != MM_DISPLAY_SURFACE_NULL &&
1952                         __mmcamcorder_find_max_resolution(handle, &maxwidth, &maxheight) == false) {
1953                         MMCAM_LOG_ERROR("can not find max resolution limitation");
1954                         return false;
1955                 } else if (display_surface_type == MM_DISPLAY_SURFACE_NULL) {
1956                         maxwidth = width;
1957                         maxheight = height;
1958                 }
1959 #endif /* _MMCAMCORDER_PRODUCT_TV */
1960                 caps = gst_caps_new_simple("video/x-h264",
1961                         "stream-format", G_TYPE_STRING, "byte-stream",
1962 #ifdef _MMCAMCORDER_PRODUCT_TV
1963                         "maxwidth", G_TYPE_INT, maxwidth,
1964                         "maxheight", G_TYPE_INT, maxheight,
1965                         "alignment", G_TYPE_STRING, "au",
1966 #endif /* _MMCAMCORDER_PRODUCT_TV */
1967                         NULL);
1968                 break;
1969         case MM_PIXEL_FORMAT_ENCODED_MJPEG:
1970 #ifdef _MMCAMCORDER_PRODUCT_TV
1971                 caps = gst_caps_new_empty_simple("video/x-jpeg");
1972 #else
1973                 caps = gst_caps_new_empty_simple("image/jpeg");
1974 #endif
1975                 break;
1976         case MM_PIXEL_FORMAT_ENCODED_VP8:
1977                 caps = gst_caps_new_empty_simple("video/x-vp8");
1978                 break;
1979         case MM_PIXEL_FORMAT_ENCODED_VP9:
1980                 caps = gst_caps_new_empty_simple("video/x-vp9");
1981                 break;
1982         default:
1983                 mm_camcorder_get_attributes(handle, NULL,
1984                         MMCAM_IMAGE_ENCODER, &codec_type,
1985                         NULL);
1986
1987                 fourcc = (guint32)_mmcamcorder_get_fourcc(format, codec_type, hcamcorder->use_zero_copy_format);
1988                 snprintf(fourcc_string, sizeof(fourcc_string), "%"GST_FOURCC_FORMAT, GST_FOURCC_ARGS(fourcc));
1989                 caps = gst_caps_new_simple("video/x-raw",
1990                         "format", G_TYPE_STRING, fourcc_string,
1991                         NULL);
1992                 break;
1993         }
1994
1995         gst_caps_set_simple(caps,
1996                 "width", G_TYPE_INT, width,
1997                 "height", G_TYPE_INT, height,
1998                 NULL);
1999
2000         if (fps > 0) {
2001                 gst_caps_set_simple(caps,
2002                         "framerate", GST_TYPE_FRACTION, fps, 1,
2003                         NULL);
2004         }
2005
2006         if (rotate >= 0) {
2007                 gst_caps_set_simple(caps,
2008                         "rotate", G_TYPE_INT, rotate,
2009                         NULL);
2010         }
2011
2012         caps_string = gst_caps_to_string(caps);
2013         MMCAM_LOG_INFO("caps[%s]", caps_string);
2014         g_free(caps_string);
2015
2016         return caps;
2017 }
2018
2019 gboolean _mmcamcorder_resize_frame(unsigned char *src_data, unsigned int src_width, unsigned int src_height, unsigned int src_length, int src_format,
2020         unsigned char **dst_data, unsigned int *dst_width, unsigned int *dst_height, size_t *dst_length)
2021 {
2022         int mm_ret = MM_ERROR_NONE;
2023         int input_format = MM_UTIL_COLOR_YUV420;
2024         mm_util_image_h src_image = NULL;
2025         mm_util_image_h dst_image = NULL;
2026
2027         if (!src_data || !dst_data || !dst_width || !dst_height || !dst_length) {
2028                 MMCAM_LOG_ERROR("something is NULL %p,%p,%p,%p,%p",
2029                         src_data, dst_data, dst_width, dst_height, dst_length);
2030                 return FALSE;
2031         }
2032
2033         /* set input format for mm-util */
2034         switch (src_format) {
2035         case MM_PIXEL_FORMAT_I420:
2036                 input_format = MM_UTIL_COLOR_I420;
2037                 break;
2038         case MM_PIXEL_FORMAT_YV12:
2039                 input_format = MM_UTIL_COLOR_YUV420;
2040                 break;
2041         case MM_PIXEL_FORMAT_NV12:
2042                 input_format = MM_UTIL_COLOR_NV12;
2043                 break;
2044         case MM_PIXEL_FORMAT_YUYV:
2045                 input_format = MM_UTIL_COLOR_YUYV;
2046                 break;
2047         case MM_PIXEL_FORMAT_UYVY:
2048                 input_format = MM_UTIL_COLOR_UYVY;
2049                 break;
2050         case MM_PIXEL_FORMAT_RGB888:
2051                 input_format = MM_UTIL_COLOR_RGB24;
2052                 break;
2053         default:
2054                 MMCAM_LOG_ERROR("NOT supported format [%d]", src_format);
2055                 return FALSE;
2056         }
2057
2058         MMCAM_LOG_INFO("src size %dx%d -> dst size %dx%d", src_width, src_height, *dst_width, *dst_height);
2059
2060         mm_ret = mm_image_create_image(src_width, src_height, input_format, src_data, (size_t)src_length, &src_image);
2061         if (mm_ret != MM_ERROR_NONE) {
2062                 MMCAM_LOG_ERROR("mm_image_create_image failed 0x%x", mm_ret);
2063                 return FALSE;
2064         }
2065
2066         mm_ret = mm_util_resize_image(src_image, *dst_width, *dst_height, &dst_image);
2067         mm_image_destroy_image(src_image);
2068         if (mm_ret != MM_ERROR_NONE) {
2069                 MMCAM_LOG_ERROR("mm_util_resize_image failed 0x%x", mm_ret);
2070                 return FALSE;
2071         }
2072
2073         mm_ret = mm_image_get_image(dst_image, dst_width, dst_height, NULL, dst_data, dst_length);
2074         mm_image_destroy_image(dst_image);
2075         if (mm_ret != MM_ERROR_NONE) {
2076                 MMCAM_LOG_ERROR("mm_image_get_image failed 0x%x", mm_ret);
2077                 return FALSE;
2078         }
2079
2080         MMCAM_LOG_INFO("resize done %dx%d -> %dx%d, %p, length %zu",
2081                 src_width, src_height, *dst_width, *dst_height, *dst_data, *dst_length);
2082
2083         return TRUE;
2084 }
2085
2086
2087 gboolean _mmcamcorder_encode_jpeg(void *src_data, unsigned int src_width, unsigned int src_height,
2088         int src_format, unsigned int src_length, unsigned int jpeg_quality,
2089         void **result_data, unsigned int *result_length)
2090 {
2091         int ret = MM_UTIL_ERROR_NONE;
2092         gboolean ret_conv = TRUE;
2093         mm_util_color_format_e jpeg_format = MM_UTIL_COLOR_NUM;
2094         unsigned char *converted_src = NULL;
2095         unsigned int converted_src_size = 0;
2096         mm_util_image_h decoded = NULL;
2097         void *encoded_data = NULL;
2098         size_t encoded_data_size = 0;
2099
2100         mmf_return_val_if_fail(src_data && result_data && result_length, FALSE);
2101
2102         switch (src_format) {
2103         case MM_PIXEL_FORMAT_NV12:
2104                 //jpeg_format = MM_UTIL_COLOR_NV12;
2105                 ret_conv = _mmcamcorder_convert_NV12_to_I420(src_data, src_width, src_height, &converted_src, &converted_src_size);
2106                 jpeg_format = MM_UTIL_COLOR_YUV420;
2107                 break;
2108         case MM_PIXEL_FORMAT_NV16:
2109                 jpeg_format = MM_UTIL_COLOR_NV16;
2110                 converted_src = src_data;
2111                 break;
2112         case MM_PIXEL_FORMAT_NV21:
2113                 jpeg_format = MM_UTIL_COLOR_NV21;
2114                 converted_src = src_data;
2115                 break;
2116         case MM_PIXEL_FORMAT_YUYV:
2117                 //jpeg_format = MM_UTIL_COLOR_YUYV;
2118                 ret_conv = _mmcamcorder_convert_YUYV_to_I420(src_data, src_width, src_height, &converted_src, &converted_src_size);
2119                 jpeg_format = MM_UTIL_COLOR_YUV420;
2120                 break;
2121         case MM_PIXEL_FORMAT_UYVY:
2122                 //jpeg_format = MM_UTIL_COLOR_UYVY;
2123                 ret_conv = _mmcamcorder_convert_UYVY_to_I420(src_data, src_width, src_height, &converted_src, &converted_src_size);
2124                 jpeg_format = MM_UTIL_COLOR_YUV420;
2125                 break;
2126         case MM_PIXEL_FORMAT_I420:
2127                 jpeg_format = MM_UTIL_COLOR_YUV420;
2128                 converted_src = src_data;
2129                 break;
2130         case MM_PIXEL_FORMAT_RGB888:
2131                 jpeg_format = MM_UTIL_COLOR_RGB24;
2132                 converted_src = src_data;
2133                 break;
2134         case MM_PIXEL_FORMAT_RGBA:
2135                 jpeg_format = MM_UTIL_COLOR_RGBA;
2136                 converted_src = src_data;
2137                 break;
2138         case MM_PIXEL_FORMAT_ARGB:
2139                 jpeg_format = MM_UTIL_COLOR_ARGB;
2140                 converted_src = src_data;
2141                 break;
2142         case MM_PIXEL_FORMAT_422P:
2143                 jpeg_format = MM_UTIL_COLOR_YUV422;     // not supported
2144                 return FALSE;
2145         case MM_PIXEL_FORMAT_NV12T:
2146         case MM_PIXEL_FORMAT_YV12:
2147         case MM_PIXEL_FORMAT_RGB565:
2148         case MM_PIXEL_FORMAT_ENCODED:
2149         case MM_PIXEL_FORMAT_ITLV_JPEG_UYVY:
2150         default:
2151                 return FALSE;
2152         }
2153
2154         if (ret_conv == FALSE) {
2155                 if (converted_src &&
2156                     converted_src != src_data) {
2157                         free(converted_src);
2158                         converted_src = NULL;
2159                 }
2160                 MMCAM_LOG_ERROR("color convert error source format[%d], jpeg format[%d]", src_format, jpeg_format);
2161                 return FALSE;
2162         }
2163
2164         converted_src_size = (converted_src && (converted_src != src_data)) ? converted_src_size : src_length;
2165         ret = mm_image_create_image(src_width, src_height, jpeg_format, converted_src, (size_t)converted_src_size, &decoded);
2166         if (ret != MM_UTIL_ERROR_NONE) {
2167                 MMCAM_LOG_ERROR("mm_image_create_image error [%d]", ret);
2168                 if (converted_src && (converted_src != src_data))
2169                         free(converted_src);
2170                 return FALSE;
2171         }
2172
2173         ret = mm_util_encode_to_jpeg_memory(decoded, jpeg_quality, &encoded_data, &encoded_data_size);
2174         mm_image_destroy_image(decoded);
2175
2176         if (converted_src && (converted_src != src_data)) {
2177                 free(converted_src);
2178                 converted_src = NULL;
2179         }
2180
2181         if (ret != MM_UTIL_ERROR_NONE) {
2182                 MMCAM_LOG_ERROR("No encoder supports %d format, error code %x", src_format, ret);
2183                 if (encoded_data)
2184                         free(encoded_data);
2185                 return FALSE;
2186         }
2187
2188         *result_data = encoded_data;
2189         *result_length = (unsigned int)encoded_data_size;
2190
2191         return TRUE;
2192 }
2193
2194
2195 /* make UYVY smaller as multiple size. ex: 640x480 -> 320x240 or 160x120 ... */
2196 gboolean _mmcamcorder_downscale_UYVYorYUYV(unsigned char *src, unsigned int src_width, unsigned int src_height,
2197         unsigned char **dst, unsigned int dst_width, unsigned int dst_height)
2198 {
2199         unsigned int i = 0;
2200         int j = 0;
2201         int k = 0;
2202         int src_index = 0;
2203         int ratio_width = 0;
2204         int ratio_height = 0;
2205         int line_base = 0;
2206         int line_width = 0;
2207         int jump_width = 0;
2208         unsigned char *result = NULL;
2209
2210         if (src == NULL || dst == NULL) {
2211                 MMCAM_LOG_ERROR("src[%p] or dst[%p] is NULL", src, dst);
2212                 return FALSE;
2213         }
2214
2215         result = (unsigned char *)malloc((dst_width * dst_height)<<1);
2216         if (!result) {
2217                 MMCAM_LOG_ERROR("failed to alloc dst data");
2218                 return FALSE;
2219         }
2220
2221         ratio_width = src_width / dst_width;
2222         ratio_height = src_height / dst_height;
2223         line_width = src_width << 1;
2224         jump_width = ratio_width << 1;
2225
2226         MMCAM_LOG_WARNING("[src %dx%d] [dst %dx%d] [line width %d] [ratio width %d, height %d]",
2227                 src_width, src_height, dst_width, dst_height, line_width, ratio_width, ratio_height);
2228
2229         for (i = 0 ; i < src_height ; i += ratio_height) {
2230                 line_base = i * line_width;
2231                 for (j = 0 ; j < line_width ; j += jump_width) {
2232                         src_index = line_base + j;
2233                         result[k++] = src[src_index];
2234                         result[k++] = src[src_index+1];
2235
2236                         j += jump_width;
2237                         src_index = line_base + j;
2238                         if (src_index % 4 == 0)
2239                                 result[k++] = src[src_index+2];
2240                         else
2241                                 result[k++] = src[src_index];
2242
2243                         result[k++] = src[src_index+1];
2244                 }
2245         }
2246
2247         *dst = result;
2248
2249         MMCAM_LOG_WARNING("converting done - result %p", result);
2250
2251         return TRUE;
2252 }
2253
2254
2255 static guint16 get_language_code(const char *str)
2256 {
2257         return (guint16)(((str[0]-0x60) & 0x1F) << 10) + (((str[1]-0x60) & 0x1F) << 5) + ((str[2]-0x60) & 0x1F);
2258 }
2259
2260 static gchar * str_to_utf8(const gchar *str)
2261 {
2262         return g_convert(str, -1, "UTF-8", "ASCII", NULL, NULL, NULL);
2263 }
2264
2265 static inline gboolean write_tag(FILE *f, const gchar *tag)
2266 {
2267         while (*tag)
2268                 FPUTC_CHECK(*tag++, f);
2269
2270         return TRUE;
2271 }
2272
2273 static inline gboolean write_to_32(FILE *f, guint val)
2274 {
2275         FPUTC_CHECK(val >> 24, f);
2276         FPUTC_CHECK(val >> 16, f);
2277         FPUTC_CHECK(val >> 8, f);
2278         FPUTC_CHECK(val, f);
2279         return TRUE;
2280 }
2281
2282 static inline gboolean write_to_16(FILE *f, guint val)
2283 {
2284         FPUTC_CHECK(val >> 8, f);
2285         FPUTC_CHECK(val, f);
2286         return TRUE;
2287 }
2288
2289 static inline gboolean write_to_24(FILE *f, guint val)
2290 {
2291         write_to_16(f, val >> 8);
2292         FPUTC_CHECK(val, f);
2293         return TRUE;
2294 }
2295
2296 void *_mmcamcorder_util_task_thread_func(void *data)
2297 {
2298         int ret = MM_ERROR_NONE;
2299         mmf_camcorder_t *hcamcorder = (mmf_camcorder_t *)data;
2300
2301         if (!hcamcorder) {
2302                 MMCAM_LOG_ERROR("handle is NULL");
2303                 return NULL;
2304         }
2305
2306         MMCAM_LOG_WARNING("start thread");
2307
2308         g_mutex_lock(&hcamcorder->task_thread_lock);
2309
2310         while (hcamcorder->task_thread_state != _MMCAMCORDER_TASK_THREAD_STATE_EXIT) {
2311                 switch (hcamcorder->task_thread_state) {
2312                 case _MMCAMCORDER_TASK_THREAD_STATE_NONE:
2313                         MMCAM_LOG_WARNING("wait for task signal");
2314                         g_cond_wait(&hcamcorder->task_thread_cond, &hcamcorder->task_thread_lock);
2315                         MMCAM_LOG_WARNING("task signal received : state %d", hcamcorder->task_thread_state);
2316                         break;
2317                 case _MMCAMCORDER_TASK_THREAD_STATE_SOUND_PLAY_START:
2318                         _mmcamcorder_sound_play((MMHandleType)hcamcorder, _MMCAMCORDER_SAMPLE_SOUND_NAME_CAPTURE02, FALSE);
2319                         hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_NONE;
2320                         break;
2321                 case _MMCAMCORDER_TASK_THREAD_STATE_SOUND_SOLO_PLAY_START:
2322                         _mmcamcorder_sound_solo_play((MMHandleType)hcamcorder, _MMCAMCORDER_SAMPLE_SOUND_NAME_CAPTURE01, FALSE);
2323                         hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_NONE;
2324                         break;
2325                 case _MMCAMCORDER_TASK_THREAD_STATE_ENCODE_PIPE_CREATE:
2326                         ret = _mmcamcorder_video_prepare_record((MMHandleType)hcamcorder);
2327
2328                         /* Play record start sound */
2329                         _mmcamcorder_sound_solo_play((MMHandleType)hcamcorder, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_START, FALSE);
2330
2331                         MMCAM_LOG_INFO("_mmcamcorder_video_prepare_record return 0x%x", ret);
2332                         hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_NONE;
2333                         break;
2334                 case _MMCAMCORDER_TASK_THREAD_STATE_CHECK_CAPTURE_IN_RECORDING:
2335                         {
2336                                 gint64 end_time = 0;
2337
2338                                 MMCAM_LOG_WARNING("wait for capture data in recording. wait signal...");
2339
2340                                 end_time = g_get_monotonic_time() + (5 * G_TIME_SPAN_SECOND);
2341
2342                                 if (g_cond_wait_until(&hcamcorder->task_thread_cond, &hcamcorder->task_thread_lock, end_time)) {
2343                                         MMCAM_LOG_WARNING("signal received");
2344                                 } else {
2345                                         _MMCamcorderMsgItem message;
2346
2347                                         memset(&message, 0x0, sizeof(_MMCamcorderMsgItem));
2348
2349                                         MMCAM_LOG_ERROR("capture data wait time out, send error message");
2350
2351                                         message.id = MM_MESSAGE_CAMCORDER_ERROR;
2352                                         message.param.code = MM_ERROR_CAMCORDER_RESPONSE_TIMEOUT;
2353
2354                                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &message);
2355
2356                                         hcamcorder->capture_in_recording = FALSE;
2357                                 }
2358
2359                                 hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_NONE;
2360                         }
2361                         break;
2362                 default:
2363                         MMCAM_LOG_WARNING("invalid task thread state %d", hcamcorder->task_thread_state);
2364                         hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_EXIT;
2365                         break;
2366                 }
2367         }
2368
2369         g_mutex_unlock(&hcamcorder->task_thread_lock);
2370
2371         MMCAM_LOG_WARNING("exit thread");
2372
2373         return NULL;
2374 }
2375
2376
2377 static gboolean _mmcamcorder_convert_YUYV_to_I420(unsigned char *src, guint width, guint height, unsigned char **dst, unsigned int *dst_len)
2378 {
2379         unsigned int i = 0;
2380         int j = 0;
2381         int src_offset = 0;
2382         int dst_y_offset = 0;
2383         int dst_u_offset = 0;
2384         int dst_v_offset = 0;
2385         int loop_length = 0;
2386         unsigned int dst_size = 0;
2387         unsigned char *dst_data = NULL;
2388
2389         if (!src || !dst || !dst_len) {
2390                 MMCAM_LOG_ERROR("NULL pointer %p, %p, %p", src, dst, dst_len);
2391                 return FALSE;
2392         }
2393
2394         dst_size = (width * height * 3) >> 1;
2395
2396         MMCAM_LOG_INFO("YUVY -> I420 : %dx%d, dst size %d", width, height, dst_size);
2397
2398         dst_data = (unsigned char *)malloc(dst_size);
2399         if (!dst_data) {
2400                 MMCAM_LOG_ERROR("failed to alloc dst_data. size %d", dst_size);
2401                 return FALSE;
2402         }
2403
2404         loop_length = width << 1;
2405         dst_u_offset = width * height;
2406         dst_v_offset = dst_u_offset + (dst_u_offset >> 2);
2407
2408         MMCAM_LOG_INFO("offset y %d, u %d, v %d", dst_y_offset, dst_u_offset, dst_v_offset);
2409
2410         for (i = 0 ; i < height ; i++) {
2411                 for (j = 0 ; j < loop_length ; j += 2) {
2412                         dst_data[dst_y_offset++] = src[src_offset++]; /*Y*/
2413
2414                         if (i % 2 == 0) {
2415                                 if (j % 4 == 0)
2416                                         dst_data[dst_u_offset++] = src[src_offset++]; /*U*/
2417                                 else
2418                                         dst_data[dst_v_offset++] = src[src_offset++]; /*V*/
2419                         } else {
2420                                 src_offset++;
2421                         }
2422                 }
2423         }
2424
2425         *dst = dst_data;
2426         *dst_len = dst_size;
2427
2428         MMCAM_LOG_INFO("DONE: YUVY -> I420 : %dx%d, dst data %p, size %d", width, height, *dst, dst_size);
2429
2430         return TRUE;
2431 }
2432
2433
2434 static gboolean _mmcamcorder_convert_UYVY_to_I420(unsigned char *src, guint width, guint height, unsigned char **dst, unsigned int *dst_len)
2435 {
2436         unsigned int i = 0;
2437         int j = 0;
2438         int src_offset = 0;
2439         int dst_y_offset = 0;
2440         int dst_u_offset = 0;
2441         int dst_v_offset = 0;
2442         int loop_length = 0;
2443         unsigned int dst_size = 0;
2444         unsigned char *dst_data = NULL;
2445
2446         if (!src || !dst || !dst_len) {
2447                 MMCAM_LOG_ERROR("NULL pointer %p, %p, %p", src, dst, dst_len);
2448                 return FALSE;
2449         }
2450
2451         dst_size = (width * height * 3) >> 1;
2452
2453         MMCAM_LOG_INFO("UYVY -> I420 : %dx%d, dst size %d", width, height, dst_size);
2454
2455         dst_data = (unsigned char *)malloc(dst_size);
2456         if (!dst_data) {
2457                 MMCAM_LOG_ERROR("failed to alloc dst_data. size %d", dst_size);
2458                 return FALSE;
2459         }
2460
2461         loop_length = width << 1;
2462         dst_u_offset = width * height;
2463         dst_v_offset = dst_u_offset + (dst_u_offset >> 2);
2464
2465         MMCAM_LOG_INFO("offset y %d, u %d, v %d", dst_y_offset, dst_u_offset, dst_v_offset);
2466
2467         for (i = 0 ; i < height ; i++) {
2468                 for (j = 0 ; j < loop_length ; j += 2) {
2469                         if (i % 2 == 0) {
2470                                 if (j % 4 == 0)
2471                                         dst_data[dst_u_offset++] = src[src_offset++]; /*U*/
2472                                 else
2473                                         dst_data[dst_v_offset++] = src[src_offset++]; /*V*/
2474                         } else {
2475                                 src_offset++;
2476                         }
2477
2478                         dst_data[dst_y_offset++] = src[src_offset++]; /*Y*/
2479                 }
2480         }
2481
2482         *dst = dst_data;
2483         *dst_len = dst_size;
2484
2485         MMCAM_LOG_INFO("DONE: UYVY -> I420 : %dx%d, dst data %p, size %d", width, height, *dst, dst_size);
2486
2487         return TRUE;
2488 }
2489
2490
2491 static gboolean _mmcamcorder_convert_NV12_to_I420(unsigned char *src, guint width, guint height, unsigned char **dst, unsigned int *dst_len)
2492 {
2493         int i = 0;
2494         int src_offset = 0;
2495         int dst_y_offset = 0;
2496         int dst_u_offset = 0;
2497         int dst_v_offset = 0;
2498         int loop_length = 0;
2499         unsigned int dst_size = 0;
2500         unsigned char *dst_data = NULL;
2501
2502         if (!src || !dst || !dst_len) {
2503                 MMCAM_LOG_ERROR("NULL pointer %p, %p, %p", src, dst, dst_len);
2504                 return FALSE;
2505         }
2506
2507         /* buffer overflow prevention check */
2508         if (width > __MMCAMCORDER_MAX_WIDTH || height > __MMCAMCORDER_MAX_HEIGHT) {
2509                 MMCAM_LOG_ERROR("too large size %d x %d", width, height);
2510                 return FALSE;
2511         }
2512
2513         dst_size = (width * height * 3) >> 1;
2514
2515         MMCAM_LOG_INFO("NV12 -> I420 : %dx%d, dst size %d", width, height, dst_size);
2516
2517         dst_data = (unsigned char *)malloc(dst_size);
2518         if (!dst_data) {
2519                 MMCAM_LOG_ERROR("failed to alloc dst_data. size %d", dst_size);
2520                 return FALSE;
2521         }
2522
2523         loop_length = width << 1;
2524         dst_u_offset = width * height;
2525         dst_v_offset = dst_u_offset + (dst_u_offset >> 2);
2526
2527         MMCAM_LOG_INFO("offset y %d, u %d, v %d", dst_y_offset, dst_u_offset, dst_v_offset);
2528
2529         /* memcpy Y */
2530         memcpy(dst_data, src, dst_u_offset);
2531
2532         loop_length = dst_u_offset >> 1;
2533         src_offset = dst_u_offset;
2534
2535         /* set U and V */
2536         for (i = 0 ; i < loop_length ; i++) {
2537                 if (i % 2 == 0)
2538                         dst_data[dst_u_offset++] = src[src_offset++];
2539                 else
2540                         dst_data[dst_v_offset++] = src[src_offset++];
2541         }
2542
2543         *dst = dst_data;
2544         *dst_len = dst_size;
2545
2546         MMCAM_LOG_INFO("DONE: NV12 -> I420 : %dx%d, dst data %p, size %d", width, height, *dst, dst_size);
2547
2548         return TRUE;
2549 }
2550
2551
2552 void _mmcamcorder_emit_dbus_signal(GDBusConnection *conn, const char *object_name,
2553         const char *interface_name, const char *signal_name, int value)
2554 {
2555         if (!conn || !object_name || !interface_name || !signal_name) {
2556                 MMCAM_LOG_ERROR("NULL pointer %p %p %p %p",
2557                         conn, object_name, interface_name, signal_name);
2558                 return;
2559         }
2560
2561         if (!g_dbus_connection_emit_signal(conn, NULL,
2562                 object_name, interface_name, signal_name,
2563                 g_variant_new("(i)", value), NULL)) {
2564                 MMCAM_LOG_WARNING("failed to emit signal");
2565         } else {
2566                 MMCAM_LOG_INFO("emit signal done - value 0x%.8x", value);
2567                 g_dbus_connection_flush(conn, NULL, NULL, NULL);
2568                 MMCAM_LOG_INFO("signal flush done");
2569         }
2570
2571         return;
2572 }
2573
2574
2575 int _mmcamcorder_get_audiosrc_blocksize(int samplerate, int format, int channel, int interval, int *blocksize)
2576 {
2577         int depth = 8;
2578
2579         if (!blocksize) {
2580                 MMCAM_LOG_ERROR("NULL ptr");
2581                 return FALSE;
2582         }
2583
2584         if (samplerate == 0 || channel == 0 || interval == 0) {
2585                 MMCAM_LOG_ERROR("invalid param %d %d %d", samplerate, channel, interval);
2586                 return FALSE;
2587         }
2588
2589         if (format == MM_CAMCORDER_AUDIO_FORMAT_PCM_S16_LE)
2590                 depth = 16;
2591
2592         *blocksize = samplerate * depth * channel * interval / 8000;
2593
2594         return TRUE;
2595 }
2596
2597 gboolean _mmcamcorder_is_encoded_preview_pixel_format(int pixel_format)
2598 {
2599         return (pixel_format == MM_PIXEL_FORMAT_ENCODED ||
2600                 pixel_format == MM_PIXEL_FORMAT_ENCODED_H264 ||
2601                 pixel_format == MM_PIXEL_FORMAT_ENCODED_MJPEG ||
2602                 pixel_format == MM_PIXEL_FORMAT_ENCODED_VP8 ||
2603                 pixel_format == MM_PIXEL_FORMAT_ENCODED_VP9);
2604 }
2605
2606 void _mmcamcorder_set_log_level(int level)
2607 {
2608         MMCAM_LOG_WARNING("set log level[%d]", level);
2609         mmcam_log_level = level;
2610 }
2611
2612 int _mmcamcorder_get_log_level(void)
2613 {
2614         return mmcam_log_level;
2615 }
2616
2617 void _mmcamcorder_measure_fps(void *data)
2618 {
2619         int diff_sec;
2620         int frame_count = 0;
2621         struct timeval current_video_time;
2622         _MMCamcorderKPIMeasure *kpi = (_MMCamcorderKPIMeasure *)data;
2623
2624         mmf_return_if_fail(kpi);
2625
2626         if (!timerisset(&kpi->init_video_time) && !timerisset(&kpi->last_video_time)) {
2627                 MMCAM_LOG_INFO("START to measure FPS");
2628                 gettimeofday(&(kpi->init_video_time), NULL);
2629         }
2630
2631         frame_count = ++(kpi->video_framecount);
2632
2633         gettimeofday(&current_video_time, NULL);
2634
2635         diff_sec = current_video_time.tv_sec - kpi->last_video_time.tv_sec;
2636         if (diff_sec == 0)
2637                 return;
2638
2639         kpi->current_fps = (frame_count - kpi->last_framecount) / diff_sec;
2640
2641         if ((current_video_time.tv_sec - kpi->init_video_time.tv_sec) != 0)
2642                 kpi->average_fps = kpi->video_framecount / (current_video_time.tv_sec - kpi->init_video_time.tv_sec);
2643
2644         kpi->last_framecount = frame_count;
2645         kpi->last_video_time.tv_sec = current_video_time.tv_sec;
2646         kpi->last_video_time.tv_usec = current_video_time.tv_usec;
2647
2648         MMCAM_LOG_INFO("current fps[%d], average[%d]", kpi->current_fps, kpi->average_fps);
2649 }