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