Fix typo - camcroder -> camcorder
[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 <sys/vfs.h> /* struct statfs */
29 #include <sys/time.h> /* gettimeofday */
30 #include <sys/stat.h>
31 #include <gst/video/video-info.h>
32 #include <gio/gio.h>
33
34 #include "mm_camcorder_internal.h"
35 #include "mm_camcorder_util.h"
36 #include "mm_camcorder_sound.h"
37 #include <mm_util_imgp.h>
38 #include <mm_util_jpeg.h>
39
40 /*-----------------------------------------------------------------------
41 |    GLOBAL VARIABLE DEFINITIONS for internal                           |
42 -----------------------------------------------------------------------*/
43
44 /*-----------------------------------------------------------------------
45 |    LOCAL VARIABLE DEFINITIONS for internal                            |
46 -----------------------------------------------------------------------*/
47 #define TIME_STRING_MAX_LEN     64
48
49 #define FPUTC_CHECK(x_char, x_file)\
50 {\
51         if (fputc(x_char, x_file) == EOF) \
52         {\
53                 _mmcam_dbg_err("[Critical] fputc() returns fail.\n");   \
54                 return FALSE;\
55         }\
56 }
57 #define FPUTS_CHECK(x_str, x_file)\
58 {\
59         if (fputs(x_str, x_file) == EOF) \
60         {\
61                 _mmcam_dbg_err("[Critical] fputs() returns fail.\n");\
62                 SAFE_FREE(str); \
63                 return FALSE;\
64         }\
65 }
66
67 /*---------------------------------------------------------------------------
68 |    LOCAL FUNCTION PROTOTYPES:                                                                                         |
69 ---------------------------------------------------------------------------*/
70 /* STATIC INTERNAL FUNCTION */
71
72 //static gint           skip_mdat(FILE *f);
73 static guint16           get_language_code(const char *str);
74 static gchar*            str_to_utf8(const gchar *str);
75 static inline gboolean   write_tag(FILE *f, const gchar *tag);
76 static inline gboolean   write_to_32(FILE *f, guint val);
77 static inline gboolean   write_to_16(FILE *f, guint val);
78 static inline gboolean   write_to_24(FILE *f, guint val);
79 #ifdef _USE_YUV_TO_RGB888_
80 static gboolean _mmcamcorder_convert_YUV_to_RGB888(unsigned char *src, int src_fmt, guint width, guint height, unsigned char **dst, unsigned int *dst_len);
81 #endif /* _USE_YUV_TO_RGB888_ */
82 static gboolean _mmcamcorder_convert_YUYV_to_I420(unsigned char *src, guint width, guint height, unsigned char **dst, unsigned int *dst_len);
83 static gboolean _mmcamcorder_convert_UYVY_to_I420(unsigned char *src, guint width, guint height, unsigned char **dst, unsigned int *dst_len);
84 static gboolean _mmcamcorder_convert_NV12_to_I420(unsigned char *src, guint width, guint height, unsigned char **dst, unsigned int *dst_len);
85
86
87 /*===========================================================================================
88 |                                                                                                                                                                                       |
89 |  FUNCTION DEFINITIONS                                                                                                                                         |
90 |                                                                                                                                                                                       |
91 ========================================================================================== */
92 /*---------------------------------------------------------------------------
93 |    GLOBAL FUNCTION DEFINITIONS:                                                                                       |
94 ---------------------------------------------------------------------------*/
95
96 static int __gdbus_method_call_sync(const char* bus_name, const char* object, const char* iface,
97                                                         const char* method, GVariant* args, GVariant** result, bool is_sync)
98 {
99         int ret = MM_ERROR_NONE;
100         GError *err = NULL;
101         GVariant* dbus_reply = NULL;
102         GDBusConnection *conn = NULL;
103
104         if (!object || !iface || !method) {
105                 _mmcam_dbg_err("Invalid Argument");
106                 if (!object)
107                         _mmcam_dbg_err("object null");
108                 if (!iface)
109                         _mmcam_dbg_err("iface null");
110                 if (!method)
111                         _mmcam_dbg_err("method null");
112                 return MM_ERROR_INVALID_ARGUMENT;
113         }
114
115         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
116         if (conn == NULL) {
117                 _mmcam_dbg_err("get connection failed");
118                 return MM_ERROR_CAMCORDER_INTERNAL;
119         }
120
121         _mmcam_dbg_log("Dbus call with obj : '%s' iface : '%s' method : '%s'", object, iface, method);
122
123         if (is_sync) {
124                 if (dbus_reply = g_dbus_connection_call_sync(conn, bus_name, object, iface, \
125                                      method, args,\
126                                      NULL, G_DBUS_CALL_FLAGS_NONE, G_DBUS_REPLY_TIMEOUT, NULL, &err )) {
127                         _mmcam_dbg_log("Method Call '%s.%s' Success", iface, method);
128                         *result = dbus_reply;
129                 } else {
130                         _mmcam_dbg_err("dbus method call sync reply failed");
131                         ret = MM_ERROR_CAMCORDER_INTERNAL;
132                 }
133         } else {
134                 g_dbus_connection_call(conn, bus_name, object, iface, \
135                                                              method, args, \
136                                                              NULL, G_DBUS_CALL_FLAGS_NONE, G_DBUS_REPLY_TIMEOUT, \
137                                                              NULL, NULL, NULL);
138         }
139         g_object_unref(conn);
140         return ret;
141 }
142
143 gint32 _mmcamcorder_double_to_fix(gdouble d_number)
144 {
145         return (gint32) (d_number * 65536.0);
146 }
147
148 // find top level tag only, do not use this function for finding sub level tags
149 gint _mmcamcorder_find_tag(FILE *f, guint32 tag_fourcc, gboolean do_rewind)
150 {
151         size_t read_item = 0;
152         guchar buf[8];
153
154         if (do_rewind) {
155                 rewind(f);
156         }
157
158         while ((read_item = fread(&buf, sizeof(guchar), 8, f)) > 0) {
159                 unsigned long long buf_size = 0;
160                 unsigned int buf_fourcc = 0;
161
162                 if (read_item < 8) {
163                         _mmcam_dbg_err("fread failed : %d", read_item);
164                         break;
165                 }
166
167                 buf_fourcc = MMCAM_FOURCC(buf[4], buf[5], buf[6], buf[7]);
168
169                 if (tag_fourcc == buf_fourcc) {
170                         _mmcam_dbg_log("find tag : %c%c%c%c", MMCAM_FOURCC_ARGS(tag_fourcc));
171                         return TRUE;
172                 } else {
173                         _mmcam_dbg_log("skip [%c%c%c%c] tag", MMCAM_FOURCC_ARGS(buf_fourcc));
174
175                         buf_size = (unsigned long long)_mmcamcorder_get_container_size(buf);
176                         buf_size = buf_size - 8; /* include tag */
177
178                         do {
179                                 if (buf_size > _MMCAMCORDER_MAX_INT) {
180                                         _mmcam_dbg_log("seek %d", _MMCAMCORDER_MAX_INT);
181                                         if (fseek(f, _MMCAMCORDER_MAX_INT, SEEK_CUR) != 0) {
182                                                 _mmcam_dbg_err("fseek() fail");
183                                                 return FALSE;
184                                         }
185
186                                         buf_size -= _MMCAMCORDER_MAX_INT;
187                                 } else {
188                                         _mmcam_dbg_log("seek %d", buf_size);
189                                         if (fseek(f, buf_size, SEEK_CUR) != 0) {
190                                                 _mmcam_dbg_err("fseek() fail");
191                                                 return FALSE;
192                                         }
193                                         break;
194                                 }
195                         } while (TRUE);
196                 }
197         }
198
199         _mmcam_dbg_log("cannot find tag : %c%c%c%c", MMCAM_FOURCC_ARGS(tag_fourcc));
200
201         return FALSE;
202 }
203
204 gboolean _mmcamcorder_find_fourcc(FILE *f, guint32 tag_fourcc, gboolean do_rewind)
205 {
206         size_t read_item = 0;
207         guchar buf[8];
208
209         if (do_rewind) {
210                 rewind(f);
211         }
212
213         while ((read_item = fread(&buf, sizeof(guchar), 8, f))  > 0) {
214                 unsigned long long buf_size = 0;
215                 unsigned int buf_fourcc = 0;
216
217                 if (read_item < 8) {
218                         _mmcam_dbg_err("fread failed : %d", read_item);
219                         break;
220                 }
221
222                 buf_fourcc = MMCAM_FOURCC(buf[4], buf[5], buf[6], buf[7]);
223
224                 if (tag_fourcc == buf_fourcc) {
225                         _mmcam_dbg_log("find tag : %c%c%c%c", MMCAM_FOURCC_ARGS(tag_fourcc));
226                         return TRUE;
227                 }
228                 else if((buf_fourcc == MMCAM_FOURCC('m','o','o','v')) && (tag_fourcc != buf_fourcc)){
229                         if(_mmcamcorder_find_fourcc(f,tag_fourcc,FALSE)){
230                                 return TRUE;
231                         }
232                         else{
233                                 continue;
234                         }
235                 } else {
236                         _mmcam_dbg_log("skip [%c%c%c%c] tag", MMCAM_FOURCC_ARGS(buf_fourcc));
237
238                         buf_size = (unsigned long long)_mmcamcorder_get_container_size(buf);
239                         buf_size = buf_size - 8; /* include tag */
240
241                         do {
242                                 if (buf_size > _MMCAMCORDER_MAX_INT) {
243                                         _mmcam_dbg_log("seek %d", _MMCAMCORDER_MAX_INT);
244                                         if (fseek(f, _MMCAMCORDER_MAX_INT, SEEK_CUR) != 0) {
245                                                 _mmcam_dbg_err("fseek() fail");
246                                                 return FALSE;
247                                         }
248
249                                         buf_size -= _MMCAMCORDER_MAX_INT;
250                                 } else {
251                                         _mmcam_dbg_log("seek %d", buf_size);
252                                         if (fseek(f, buf_size, SEEK_CUR) != 0) {
253                                                 _mmcam_dbg_err("fseek() fail");
254                                                 return FALSE;
255                                         }
256                                         break;
257                                 }
258                         } while (TRUE);
259                 }
260         }
261
262         _mmcam_dbg_log("cannot find tag : %c%c%c%c", MMCAM_FOURCC_ARGS(tag_fourcc));
263
264         return FALSE;
265 }
266
267 gboolean _mmcamcorder_update_size(FILE *f, gint64 prev_pos, gint64 curr_pos)
268 {
269         _mmcam_dbg_log("size : %"G_GINT64_FORMAT"", curr_pos-prev_pos);
270         if(fseek(f, prev_pos, SEEK_SET) != 0)
271         {
272                 _mmcam_dbg_err("fseek() fail");
273                 return FALSE;
274         }
275
276         if (!write_to_32(f, curr_pos -prev_pos))
277                 return FALSE;
278
279         if(fseek(f, curr_pos, SEEK_SET) != 0)
280         {
281                 _mmcam_dbg_err("fseek() fail");
282                 return FALSE;
283         }
284
285         return TRUE;
286 }
287
288 gboolean _mmcamcorder_write_loci(FILE *f, _MMCamcorderLocationInfo info)
289 {
290         gint64 current_pos, pos;
291         gchar *str = NULL;
292
293         _mmcam_dbg_log("");
294
295         if((pos = ftell(f))<0)
296         {
297                 _mmcam_dbg_err("ftell() returns negative value");       
298                 return FALSE;
299         }
300         
301         if(!write_to_32(f, 0)) //size
302                 return FALSE;
303         
304         if(!write_tag(f, "loci"))       // type
305                 return FALSE;
306
307         FPUTC_CHECK(0, f);              // version
308
309         if(!write_to_24(f, 0))  // flags
310                 return FALSE;
311
312         if(!write_to_16(f, get_language_code("eng"))) // language
313                 return FALSE;
314
315         str = str_to_utf8("location_name");
316
317         FPUTS_CHECK(str, f); // name
318         SAFE_FREE(str);
319
320         FPUTC_CHECK('\0', f);
321         FPUTC_CHECK(0, f);              //role
322
323         if(!write_to_32(f, info.longitude))     // Longitude
324                 return FALSE;
325
326         if(!write_to_32(f, info.latitude)) // Latitude
327                 return FALSE;
328
329         if(! write_to_32(f, info.altitude))     // Altitude
330                 return FALSE;
331
332         str = str_to_utf8("Astronomical_body");
333         FPUTS_CHECK(str, f);//Astronomical_body
334         SAFE_FREE(str);
335
336         FPUTC_CHECK('\0', f);
337
338         str = str_to_utf8("Additional_notes");
339         FPUTS_CHECK(str, f); // Additional_notes
340         SAFE_FREE(str);
341
342         FPUTC_CHECK('\0', f);
343
344         if((current_pos = ftell(f))<0)
345         {
346                 _mmcam_dbg_err("ftell() returns negative value");
347                 return FALSE;
348         }
349
350         if(! _mmcamcorder_update_size(f, pos, current_pos))
351                 return FALSE;
352
353         return TRUE;
354 }
355
356 void _mmcamcorder_write_Latitude(FILE *f,int value) {
357         char s_latitude[9];
358         int l_decimal = 0;
359         int l_below_decimal = 0;
360
361         l_decimal = value / 10000;
362         if (value < 0) {
363                 if( l_decimal == 0) {
364                         snprintf(s_latitude, 5, "-%.2d.", l_decimal);
365                 } else {
366                         snprintf(s_latitude, 5, "%.2d.", l_decimal);
367                 }
368         } else {
369                 snprintf(s_latitude, 5, "+%.2d.", l_decimal);
370         }
371
372         l_below_decimal = value - (l_decimal * 10000);
373         if (l_below_decimal < 0) {
374                 l_below_decimal = -l_below_decimal;
375         }
376         snprintf(&s_latitude[4], 5, "%.4d", l_below_decimal);
377
378         write_tag(f, s_latitude);
379 }
380
381 void _mmcamcorder_write_Longitude(FILE *f,int value) {
382         char s_longitude[10];
383         int l_decimal = 0;
384         int l_below_decimal = 0;
385
386         l_decimal = value / 10000;
387         if (value < 0) {
388                 if( l_decimal == 0) {
389                         snprintf(s_longitude, 6, "-%.3d.", l_decimal);
390                 } else {
391                         snprintf(s_longitude, 6, "%.3d.", l_decimal);
392                 }
393         } else {
394                 snprintf(s_longitude, 6, "+%.3d.", l_decimal);
395         }
396
397         l_below_decimal = value - (l_decimal * 10000);
398         if (l_below_decimal < 0) {
399                 l_below_decimal = -l_below_decimal;
400         }
401         snprintf(&s_longitude[5], 5, "%.4d", l_below_decimal);
402
403         write_tag(f, s_longitude);
404 }
405
406 #define D_GEOGRAPH "\xA9xyz"
407 // 0x0012 -> latitude(8) + longitude(9) + seperator(1) = 18
408 // 0x15c7 -> encode in english
409 #define D_INFO_GEOGRAPH 0x001215c7
410
411 gboolean _mmcamcorder_write_geodata(FILE *f,_MMCamcorderLocationInfo info) {
412
413         gint64 current_pos, pos;
414
415         _mmcam_dbg_log("");
416
417         if((pos = ftell(f))<0)
418         {
419                 _mmcam_dbg_err("ftell() returns negative value");
420                 return FALSE;
421         }
422
423         if(!write_to_32(f, 0))  //size
424                 return FALSE;
425         // tag -> .xyz
426         if(!write_tag(f, D_GEOGRAPH))   // type
427                 return FALSE;
428
429         if(!write_to_32(f, D_INFO_GEOGRAPH))
430                 return FALSE;
431
432         _mmcamcorder_write_Latitude(f,info.latitude);
433         _mmcamcorder_write_Longitude(f,info.longitude);
434
435         FPUTC_CHECK(0x2F, f);
436
437         if((current_pos = ftell(f))<0)
438         {
439                 _mmcam_dbg_err("ftell() returns negative value");
440                 return FALSE;
441         }
442
443         if(! _mmcamcorder_update_size(f, pos, current_pos))
444                 return FALSE;
445
446         return TRUE;
447 }
448
449
450 gboolean _mmcamcorder_write_udta(FILE *f, int gps_enable, _MMCamcorderLocationInfo info, _MMCamcorderLocationInfo geotag)
451 {
452         gint64 current_pos, pos;
453
454         _mmcam_dbg_log("gps enable : %d", gps_enable);
455         if (gps_enable == FALSE) {
456                 _mmcam_dbg_log("no need to write udta");
457                 return TRUE;
458         }
459
460         if ((pos = ftell(f))<0) {
461                 _mmcam_dbg_err("ftell() returns negative value");
462                 return FALSE;
463         }
464
465         /* size */
466         if (!write_to_32(f, 0)) {
467                 _mmcam_dbg_err("failed to write size");
468                 return FALSE;
469         }
470
471         /* type */
472         if (!write_tag(f, "udta")) {
473                 _mmcam_dbg_err("failed to write type udta");
474                 return FALSE;
475         }
476
477         if (gps_enable) {
478                 if (!_mmcamcorder_write_loci(f, info)) {
479                         _mmcam_dbg_err("failed to write loci");
480                         return FALSE;
481                 }
482
483                 if (!_mmcamcorder_write_geodata(f,geotag)) {
484                         _mmcam_dbg_err("failed to write geodata");
485                         return FALSE;
486                 }
487         }
488
489         if ((current_pos = ftell(f))<0) {
490                 _mmcam_dbg_err("ftell() returns negative value");
491                 return FALSE;
492         }
493
494         if (!_mmcamcorder_update_size(f, pos, current_pos)) {
495                 _mmcam_dbg_err("failed to update size");
496                 return FALSE;
497         }
498
499         _mmcam_dbg_log("done");
500
501         return TRUE;
502 }
503
504
505 guint64 _mmcamcorder_get_container_size(const guchar *size)
506 {
507         guint64 result = 0;
508         guint64 temp = 0;
509
510         temp = size[0];
511         result = temp << 24;
512         temp = size[1];
513         result = result | (temp << 16);
514         temp = size[2];
515         result = result | (temp << 8);
516         result = result | size[3];
517
518         _mmcam_dbg_log("result : %lld", (unsigned long long)result);
519
520         return result;
521 }
522
523
524 gboolean _mmcamcorder_update_composition_matrix(FILE *f, int orientation)
525 {
526         /* for 0 degree */
527         guint32 a = 0x00010000;
528         guint32 b = 0;
529         guint32 c = 0;
530         guint32 d = 0x00010000;
531
532         switch (orientation) {
533         case MM_CAMCORDER_TAG_VIDEO_ORT_90:/* 90 degree */
534                 a = 0;
535                 b = 0x00010000;
536                 c = 0xffff0000;
537                 d = 0;
538                 break;
539         case MM_CAMCORDER_TAG_VIDEO_ORT_180:/* 180 degree */
540                 a = 0xffff0000;
541                 d = 0xffff0000;
542                 break;
543         case MM_CAMCORDER_TAG_VIDEO_ORT_270:/* 270 degree */
544                 a = 0;
545                 b = 0xffff0000;
546                 c = 0x00010000;
547                 d = 0;
548                 break;
549         case MM_CAMCORDER_TAG_VIDEO_ORT_NONE:/* 0 degree */
550         default:
551                 break;
552         }
553
554         write_to_32(f, a);
555         write_to_32(f, b);
556         write_to_32(f, 0);
557         write_to_32(f, c);
558         write_to_32(f, d);
559         write_to_32(f, 0);
560         write_to_32(f, 0);
561         write_to_32(f, 0);
562         write_to_32(f, 0x40000000);
563
564         _mmcam_dbg_log("orientation : %d, write data 0x%x 0x%x 0x%x 0x%x",
565                        orientation, a, b, c, d);
566
567         return TRUE;
568 }
569
570
571 int _mmcamcorder_get_freespace(const gchar *path, guint64 *free_space)
572 {
573         struct statfs fs;
574
575         g_assert(path);
576
577         if (!g_file_test(path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
578                 _mmcam_dbg_log("File(%s) doesn't exist.", path);
579                 return -2;
580         }
581
582         if (-1 == statfs(path, &fs)) {
583                 _mmcam_dbg_log("statfs failed.(%s)", path);
584                 return -1;
585         }
586
587         *free_space = (guint64)fs.f_bsize * fs.f_bavail;
588         return 1;
589 }
590
591
592 int _mmcamcorder_get_file_system_type(const gchar *path, int *file_system_type)
593 {
594         struct statfs fs;
595
596         g_assert(path);
597
598         if (!g_file_test(path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
599                 _mmcam_dbg_log("File(%s) doesn't exist.", path);
600                 return -2;
601         }
602
603         if (-1 == statfs(path, &fs)) {
604                 _mmcam_dbg_log("statfs failed.(%s)", path);
605                 return -1;
606         }
607
608         *file_system_type = (int)fs.f_type;
609
610         return 0;
611 }
612
613 int _mmcamcorder_get_freespace_except_system(guint64 *free_space)
614 {
615         double total_space=0;
616         double avail_space=0;
617
618         int ret = MM_ERROR_NONE;
619         GVariant *params = NULL, *result = NULL;
620         const char *param_type = "(xx)";
621
622         if ((ret = __gdbus_method_call_sync("org.tizen.system.deviced",
623                                             "/Org/Tizen/System/DeviceD/Storage",
624                                             "org.tizen.system.deviced.storage",
625                                             "getstorage",
626                                             params,
627                                             &result,
628                                             TRUE)) != MM_ERROR_NONE) {
629                 _mmcam_dbg_err("Dbus Call on Client Error");
630                 return ret;
631         }
632
633         if (result) {
634                 g_variant_get(result, param_type, &total_space, &avail_space);
635                 *free_space = (guint64)avail_space;
636                 _mmcam_dbg_log("free space [%" G_GUINT64_FORMAT "] ", *free_space);
637         } else {
638                 _mmcam_dbg_err("replied result is null");
639                 ret = MM_ERROR_CAMCORDER_INTERNAL;
640         }
641         return ret;
642 }
643
644 int _mmcamcorder_get_device_flash_brightness(int *brightness)
645 {
646         int get_value = 0;
647         int ret = MM_ERROR_NONE;
648         GVariant *params = NULL, *result = NULL;
649         const char *param_type = "(i)";
650
651         if ((ret = __gdbus_method_call_sync("org.tizen.system.deviced",
652                                             "/Org/Tizen/System/DeviceD/Led",
653                                             "org.tizen.system.deviced.Led",
654                                             "GetBrightnessForCamera",
655                                             params,
656                                             &result,
657                                             TRUE)) != MM_ERROR_NONE) {
658                 _mmcam_dbg_err("Dbus Call on Client Error");
659                 return ret;
660         }
661
662         if (result) {
663                 g_variant_get(result, param_type, &get_value);
664                 *brightness = get_value;
665                 _mmcam_dbg_log("flash brightness : %d", *brightness);
666         } else {
667                 _mmcam_dbg_err("replied result is null");
668                 ret = MM_ERROR_CAMCORDER_INTERNAL;
669         }
670
671         return ret;
672 }
673
674 int _mmcamcorder_get_file_size(const char *filename, guint64 *size)
675 {
676         struct stat buf;
677
678         if (stat(filename, &buf) != 0)
679                 return -1;
680         *size = (guint64)buf.st_size;
681         return 1;
682 }
683
684
685 void _mmcamcorder_remove_buffer_probe(MMHandleType handle, _MMCamcorderHandlerCategory category)
686 {
687         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
688         GList *list = NULL;
689         MMCamcorderHandlerItem *item = NULL;
690
691         mmf_return_if_fail(hcamcorder);
692
693         if (!hcamcorder->buffer_probes) {
694                 _mmcam_dbg_warn("list for buffer probe is NULL");
695                 return;
696         }
697
698         _mmcam_dbg_log("start - category : 0x%x", category);
699
700         list = hcamcorder->buffer_probes;
701         while (list) {
702                 item = list->data;
703                 if (!item) {
704                         _mmcam_dbg_err("Remove buffer probe faild, the item is NULL");
705                         list = g_list_next(list);
706                         continue;
707                 }
708
709                 if (item->category & category) {
710                         if (item->object && GST_IS_PAD(item->object)) {
711                                 _mmcam_dbg_log("Remove buffer probe on [%s:%s] - [ID : %lu], [Category : %x]",
712                                                GST_DEBUG_PAD_NAME(item->object), item->handler_id,  item->category);
713                                 gst_pad_remove_probe(GST_PAD(item->object), item->handler_id);
714                         } else {
715                                 _mmcam_dbg_warn("Remove buffer probe faild, the pad is null or not pad, just remove item from list and free it");
716                         }
717
718                         list = g_list_next(list);
719                         hcamcorder->buffer_probes = g_list_remove(hcamcorder->buffer_probes, item);
720                         SAFE_FREE(item);
721                 } else {
722                         _mmcam_dbg_log("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
723                         list = g_list_next(list);
724                 }
725         }
726
727         if (category == _MMCAMCORDER_HANDLER_CATEGORY_ALL) {
728                 g_list_free(hcamcorder->buffer_probes);
729                 hcamcorder->buffer_probes = NULL;
730         }
731
732         _mmcam_dbg_log("done");
733
734         return;
735 }
736
737
738 void _mmcamcorder_remove_one_buffer_probe(MMHandleType handle, void *object)
739 {
740         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
741         GList *list = NULL;
742         MMCamcorderHandlerItem *item = NULL;
743
744         mmf_return_if_fail(hcamcorder);
745
746         if (!hcamcorder->buffer_probes) {
747                 _mmcam_dbg_warn("list for buffer probe is NULL");
748                 return;
749         }
750
751         _mmcam_dbg_log("start - object : %p", object);
752
753         list = hcamcorder->buffer_probes;
754         while (list) {
755                 item = list->data;
756                 if (!item) {
757                         _mmcam_dbg_err("Remove buffer probe faild, the item is NULL");
758                         list = g_list_next(list);
759                         continue;
760                 }
761
762                 if (item->object && item->object == object) {
763                         if (GST_IS_PAD(item->object)) {
764                                 _mmcam_dbg_log("Remove buffer probe on [%s:%s] - [ID : %lu], [Category : %x]",
765                                                GST_DEBUG_PAD_NAME(item->object), item->handler_id,  item->category);
766                                 gst_pad_remove_probe(GST_PAD(item->object), item->handler_id);
767                         } else {
768                                 _mmcam_dbg_warn("Remove buffer probe faild, the pad is null or not pad, just remove item from list and free it");
769                         }
770
771                         list = g_list_next(list);
772                         hcamcorder->buffer_probes = g_list_remove(hcamcorder->buffer_probes, item);
773                         SAFE_FREE(item);
774
775                         break;
776                 } else {
777                         _mmcam_dbg_log("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
778                         list = g_list_next(list);
779                 }
780         }
781
782         _mmcam_dbg_log("done");
783
784         return;
785 }
786
787
788 void _mmcamcorder_remove_event_probe(MMHandleType handle, _MMCamcorderHandlerCategory category)
789 {
790         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
791         GList *list = NULL;
792         MMCamcorderHandlerItem *item = NULL;
793
794         mmf_return_if_fail(hcamcorder);
795
796         if (!hcamcorder->event_probes) {
797                 _mmcam_dbg_warn("list for event probe is NULL");
798                 return;
799         }
800
801         _mmcam_dbg_log("start - category : 0x%x", category);
802
803         list = hcamcorder->event_probes;
804         while (list) {
805                 item = list->data;
806                 if (!item) {
807                         _mmcam_dbg_err("Remove event probe faild, the item is NULL");
808                         list = g_list_next(list);
809                         continue;
810                 }
811
812                 if (item->category & category) {
813                         if (item->object && GST_IS_PAD(item->object)) {
814                                 _mmcam_dbg_log("Remove event probe on [%s:%s] - [ID : %lu], [Category : %x]",
815                                                GST_DEBUG_PAD_NAME(item->object), item->handler_id,  item->category);
816                                 gst_pad_remove_probe(GST_PAD(item->object), item->handler_id);
817                         } else {
818                                 _mmcam_dbg_warn("Remove event probe faild, the pad is null or not pad, just remove item from list and free it");
819                         }
820
821                         list = g_list_next(list);
822                         hcamcorder->event_probes = g_list_remove(hcamcorder->event_probes, item);
823                         SAFE_FREE(item);
824                 } else {
825                         _mmcam_dbg_log("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
826                         list = g_list_next(list);
827                 }
828         }
829
830         if (category == _MMCAMCORDER_HANDLER_CATEGORY_ALL) {
831                 g_list_free(hcamcorder->event_probes);
832                 hcamcorder->event_probes = NULL;
833         }
834
835         _mmcam_dbg_log("done");
836
837         return;
838 }
839
840
841 void _mmcamcorder_disconnect_signal(MMHandleType handle, _MMCamcorderHandlerCategory category)
842 {
843         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
844         GList *list = NULL;
845         MMCamcorderHandlerItem *item = NULL;
846
847         mmf_return_if_fail(hcamcorder);
848
849         if (!hcamcorder->signals) {
850                 _mmcam_dbg_warn("list for signal is NULL");
851                 return;
852         }
853
854         _mmcam_dbg_log("start - category : 0x%x", category);
855
856         list = hcamcorder->signals;
857         while (list) {
858                 item = list->data;
859                 if (!item) {
860                         _mmcam_dbg_err("Fail to Disconnecting signal, the item is NULL");
861                         list = g_list_next(list);
862                         continue;
863                 }
864
865                 if (item->category & category) {
866                         if (item->object && GST_IS_ELEMENT(item->object)) {
867                                 if (g_signal_handler_is_connected(item->object, item->handler_id)) {
868                                         _mmcam_dbg_log("Disconnect signal from [%s] : [ID : %lu], [Category : %x]",
869                                                        GST_OBJECT_NAME(item->object), item->handler_id,  item->category);
870                                         g_signal_handler_disconnect(item->object, item->handler_id);
871                                 } else {
872                                         _mmcam_dbg_warn("Signal was not connected, cannot disconnect it :  [%s]  [ID : %lu], [Category : %x]",
873                                                         GST_OBJECT_NAME(item->object), item->handler_id,  item->category);
874                                 }
875                         } else {
876                                 _mmcam_dbg_err("Fail to Disconnecting signal, the element is null or not element, just remove item from list and free it");
877                         }
878
879                         list = g_list_next(list);
880                         hcamcorder->signals = g_list_remove(hcamcorder->signals, item);
881                         SAFE_FREE(item);
882                 } else {
883                         _mmcam_dbg_log("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
884                         list = g_list_next(list);
885                 }
886         }
887
888         if (category == _MMCAMCORDER_HANDLER_CATEGORY_ALL) {
889                 g_list_free(hcamcorder->signals);
890                 hcamcorder->signals = NULL;
891         }
892
893         _mmcam_dbg_log("done");
894
895         return;
896 }
897
898
899 void _mmcamcorder_remove_all_handlers(MMHandleType handle,  _MMCamcorderHandlerCategory category)
900 {
901         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
902
903         _mmcam_dbg_log("ENTER");
904
905         if(hcamcorder->signals)
906                 _mmcamcorder_disconnect_signal((MMHandleType)hcamcorder, category);
907         if(hcamcorder->event_probes)
908                 _mmcamcorder_remove_event_probe((MMHandleType)hcamcorder, category);
909         if(hcamcorder->buffer_probes)
910                 _mmcamcorder_remove_buffer_probe((MMHandleType)hcamcorder, category);
911
912         _mmcam_dbg_log("LEAVE");
913 }
914
915
916 void _mmcamcorder_element_release_noti(gpointer data, GObject *where_the_object_was)
917 {
918         int i=0;
919         _MMCamcorderSubContext *sc = (_MMCamcorderSubContext *)data;
920
921         mmf_return_if_fail(sc);
922         mmf_return_if_fail(sc->element);
923
924         for (i = 0 ; i < _MMCAMCORDER_PIPELINE_ELEMENT_NUM ; i++) {
925                 if (sc->element[i].gst && (G_OBJECT(sc->element[i].gst) == where_the_object_was)) {
926                         _mmcam_dbg_warn("The element[%d][%p] is finalized",
927                                         sc->element[i].id, sc->element[i].gst);
928                         sc->element[i].gst = NULL;
929                         sc->element[i].id = _MMCAMCORDER_NONE;
930                         return;
931                 }
932         }
933
934         mmf_return_if_fail(sc->encode_element);
935
936         for (i = 0 ; i < _MMCAMCORDER_ENCODE_PIPELINE_ELEMENT_NUM ; i++) {
937                 if (sc->encode_element[i].gst && (G_OBJECT(sc->encode_element[i].gst) == where_the_object_was)) {
938                         _mmcam_dbg_warn("The encode element[%d][%p] is finalized",
939                                         sc->encode_element[i].id, sc->encode_element[i].gst);
940                         sc->encode_element[i].gst = NULL;
941                         sc->encode_element[i].id = _MMCAMCORDER_ENCODE_NONE;
942                         return;
943                 }
944         }
945
946         _mmcam_dbg_warn("there is no matching element %p", where_the_object_was);
947
948         return;
949 }
950
951
952 gboolean _mmcamcorder_msg_callback(void *data)
953 {
954         _MMCamcorderMsgItem *item = (_MMCamcorderMsgItem*)data;
955         mmf_camcorder_t *hcamcorder = NULL;
956         mmf_return_val_if_fail(item, FALSE);
957
958         pthread_mutex_lock(&(item->lock));
959
960         hcamcorder = MMF_CAMCORDER(item->handle);
961         if (hcamcorder == NULL) {
962                 _mmcam_dbg_warn("msg id:0x%x, item:%p, handle is NULL", item->id, item);
963                 goto MSG_CALLBACK_DONE;
964         }
965
966         /*_mmcam_dbg_log("msg id:%x, msg_cb:%p, msg_data:%p, item:%p", item->id, hcamcorder->msg_cb, hcamcorder->msg_data, item);*/
967
968         _MMCAMCORDER_LOCK((MMHandleType)hcamcorder);
969
970         /* remove item from msg data */
971         if (hcamcorder->msg_data) {
972                 hcamcorder->msg_data = g_list_remove(hcamcorder->msg_data, item);
973         } else {
974                 _mmcam_dbg_warn("msg_data is NULL but item[%p] will be removed", item);
975         }
976
977         _MMCAMCORDER_UNLOCK((MMHandleType)hcamcorder);
978
979         _MMCAMCORDER_LOCK_MESSAGE_CALLBACK(hcamcorder);
980
981         if ((hcamcorder) && (hcamcorder->msg_cb)) {
982                 hcamcorder->msg_cb(item->id, (MMMessageParamType*)(&(item->param)), hcamcorder->msg_cb_param);
983         }
984
985         _MMCAMCORDER_UNLOCK_MESSAGE_CALLBACK(hcamcorder);
986
987         _MMCAMCORDER_SIGNAL(hcamcorder);
988
989 MSG_CALLBACK_DONE:
990         /* release allocated memory */
991         if (item->id == MM_MESSAGE_CAMCORDER_FACE_DETECT_INFO) {
992                 MMCamFaceDetectInfo *cam_fd_info = (MMCamFaceDetectInfo *)item->param.data;
993                 if (cam_fd_info) {
994                         SAFE_FREE(cam_fd_info->face_info);
995                         free(cam_fd_info);
996                         cam_fd_info = NULL;
997                 }
998
999                 item->param.data = NULL;
1000                 item->param.size = 0;
1001         }
1002
1003         pthread_mutex_unlock(&(item->lock));
1004         pthread_mutex_destroy(&(item->lock));
1005
1006         free(item);
1007         item = NULL;
1008
1009         /* For not being called again */
1010         return FALSE;
1011 }
1012
1013
1014 gboolean _mmcamcorder_send_message(MMHandleType handle, _MMCamcorderMsgItem *data)
1015 {
1016         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
1017         _MMCamcorderMsgItem *item = NULL;
1018
1019         mmf_return_val_if_fail(hcamcorder, FALSE);
1020         mmf_return_val_if_fail(data, FALSE);
1021
1022         switch (data->id)
1023         {
1024                 case MM_MESSAGE_CAMCORDER_STATE_CHANGED:
1025                 case MM_MESSAGE_CAMCORDER_STATE_CHANGED_BY_ASM:
1026                         data->param.union_type = MM_MSG_UNION_STATE;
1027                         break;
1028                 case MM_MESSAGE_CAMCORDER_RECORDING_STATUS:
1029                         data->param.union_type = MM_MSG_UNION_RECORDING_STATUS;
1030                         break;
1031                 case MM_MESSAGE_CAMCORDER_FIRMWARE_UPDATE:
1032                         data->param.union_type = MM_MSG_UNION_FIRMWARE;
1033                         break;
1034                 case MM_MESSAGE_CAMCORDER_CURRENT_VOLUME:
1035                         data->param.union_type = MM_MSG_UNION_REC_VOLUME_DB;
1036                         break;
1037                 case MM_MESSAGE_CAMCORDER_TIME_LIMIT:
1038                 case MM_MESSAGE_CAMCORDER_MAX_SIZE:
1039                 case MM_MESSAGE_CAMCORDER_NO_FREE_SPACE:
1040                 case MM_MESSAGE_CAMCORDER_ERROR:
1041                 case MM_MESSAGE_CAMCORDER_FOCUS_CHANGED:
1042                 case MM_MESSAGE_CAMCORDER_CAPTURED:
1043                 case MM_MESSAGE_CAMCORDER_VIDEO_CAPTURED:
1044                 case MM_MESSAGE_CAMCORDER_AUDIO_CAPTURED:
1045                 case MM_MESSAGE_READY_TO_RESUME:
1046                 default:
1047                         data->param.union_type = MM_MSG_UNION_CODE;
1048                         break;
1049         }
1050
1051         item = g_malloc(sizeof(_MMCamcorderMsgItem));
1052         if (item) {
1053                 memcpy(item, data, sizeof(_MMCamcorderMsgItem));
1054                 item->handle = handle;
1055                 pthread_mutex_init(&(item->lock), NULL);
1056
1057                 _MMCAMCORDER_LOCK(handle);
1058                 hcamcorder->msg_data = g_list_append(hcamcorder->msg_data, item);
1059 //              _mmcam_dbg_log("item[%p]", item);
1060
1061                 /* Use DEFAULT priority */
1062                 g_idle_add_full(G_PRIORITY_DEFAULT, _mmcamcorder_msg_callback, item, NULL);
1063
1064                 _MMCAMCORDER_UNLOCK(handle);
1065         } else {
1066                 _mmcam_dbg_err("item[id:0x%x] malloc failed : %d", data->id, sizeof(_MMCamcorderMsgItem));
1067         }
1068
1069         return TRUE;
1070 }
1071
1072
1073 void _mmcamcorder_remove_message_all(MMHandleType handle)
1074 {
1075         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
1076         _MMCamcorderMsgItem *item = NULL;
1077         gboolean ret = TRUE;
1078         GList *list = NULL;
1079         struct timespec timeout;
1080         struct timeval tv;
1081         struct timeval tv_to_add;
1082         struct timeval tv_result;
1083
1084         mmf_return_if_fail(hcamcorder);
1085
1086         _MMCAMCORDER_LOCK(handle);
1087
1088         if (!hcamcorder->msg_data) {
1089                 _mmcam_dbg_log("No message data is remained.");
1090         } else {
1091                 tv_to_add.tv_sec = 0;
1092                 tv_to_add.tv_usec = 1000 * 100; /* 100 ms */
1093
1094                 list = hcamcorder->msg_data;
1095
1096                 while (list) {
1097                         item = list->data;
1098                         list = g_list_next(list);
1099
1100                         if (!item) {
1101                                 _mmcam_dbg_err("Fail to remove message. The item is NULL");
1102                         } else {
1103                                 if (pthread_mutex_trylock(&(item->lock))) {
1104                                         ret = g_idle_remove_by_data(item);
1105
1106                                         _mmcam_dbg_log("remove msg item[%p], ret[%d]", item, ret);
1107
1108                                         if (ret == FALSE) {
1109                                                 item->handle = 0;
1110                                                 _mmcam_dbg_warn("failed to remove msg cb for item %p, it will be called later with NULL handle", item);
1111                                         }
1112
1113                                         /* release allocated memory */
1114                                         if (item->id == MM_MESSAGE_CAMCORDER_FACE_DETECT_INFO) {
1115                                                 MMCamFaceDetectInfo *cam_fd_info = (MMCamFaceDetectInfo *)item->param.data;
1116                                                 if (cam_fd_info) {
1117                                                         SAFE_FREE(cam_fd_info->face_info);
1118                                                         free(cam_fd_info);
1119                                                         cam_fd_info = NULL;
1120                                                 }
1121
1122                                                 item->param.data = NULL;
1123                                                 item->param.size = 0;
1124                                         }
1125
1126                                         hcamcorder->msg_data = g_list_remove(hcamcorder->msg_data, item);
1127
1128                                         pthread_mutex_unlock(&(item->lock));
1129
1130                                         if (ret == TRUE) {
1131                                                 pthread_mutex_destroy(&(item->lock));
1132
1133                                                 free(item);
1134                                                 item = NULL;
1135
1136                                                 _mmcam_dbg_log("remove msg done");
1137                                         }
1138                                 } else {
1139                                         _mmcam_dbg_warn("item lock failed. it's being called...");
1140
1141                                         gettimeofday(&tv, NULL);
1142                                         timeradd(&tv, &tv_to_add, &tv_result);
1143                                         timeout.tv_sec = tv_result.tv_sec;
1144                                         timeout.tv_nsec = tv_result.tv_usec * 1000;
1145
1146                                         if (_MMCAMCORDER_TIMED_WAIT(handle, timeout)) {
1147                                                 _mmcam_dbg_warn("signal received");
1148                                         } else {
1149                                                 _mmcam_dbg_warn("timeout");
1150                                         }
1151                                 }
1152                         }
1153                 }
1154
1155                 g_list_free(hcamcorder->msg_data);
1156                 hcamcorder->msg_data = NULL;
1157         }
1158
1159         /* remove idle function for playing capture sound */
1160         do {
1161                 ret = g_idle_remove_by_data(hcamcorder);
1162                 _mmcam_dbg_log("remove idle function for playing capture sound. ret[%d]", ret);
1163         } while (ret);
1164
1165         _MMCAMCORDER_UNLOCK(handle);
1166
1167         return;
1168 }
1169
1170
1171 int _mmcamcorder_get_pixel_format(GstCaps *caps)
1172 {
1173         const GstStructure *structure;
1174         const char *media_type;
1175         GstVideoInfo media_info;
1176         MMPixelFormatType type = 0;
1177         unsigned int fourcc = 0;
1178
1179         mmf_return_val_if_fail( caps != NULL, MM_PIXEL_FORMAT_INVALID );
1180
1181         structure = gst_caps_get_structure (caps, 0);
1182         media_type = gst_structure_get_name (structure);
1183         if (media_type == NULL) {
1184                 _mmcam_dbg_err("failed to get media_type");
1185                 return MM_PIXEL_FORMAT_INVALID;
1186         }
1187
1188         gst_video_info_init (&media_info);
1189
1190         if (!strcmp (media_type, "image/jpeg") ) {
1191                 _mmcam_dbg_log("It is jpeg.");
1192                 type = MM_PIXEL_FORMAT_ENCODED;
1193         } else if (!strcmp (media_type, "video/x-raw") &&
1194                    gst_video_info_from_caps(&media_info, caps) &&
1195                    GST_VIDEO_INFO_IS_YUV(&media_info)) {
1196                 _mmcam_dbg_log("It is yuv.");
1197                 fourcc = gst_video_format_to_fourcc(GST_VIDEO_INFO_FORMAT(&media_info));
1198                 type = _mmcamcorder_get_pixtype(fourcc);
1199         } else if (!strcmp (media_type, "video/x-raw") &&
1200                    gst_video_info_from_caps(&media_info, caps) &&
1201                    GST_VIDEO_INFO_IS_RGB(&media_info)) {
1202                 _mmcam_dbg_log("It is rgb.");
1203                 type = MM_PIXEL_FORMAT_RGB888;
1204         } else if (!strcmp (media_type, "video/x-h264")) {
1205                 _mmcam_dbg_log("It is H264");
1206                 type = MM_PIXEL_FORMAT_ENCODED_H264;
1207         } else {
1208                 _mmcam_dbg_err("Not supported format [%s]",media_type);
1209                 type = MM_PIXEL_FORMAT_INVALID;
1210         }
1211
1212         /*_mmcam_dbg_log( "Type [%d]", type );*/
1213
1214         return type;
1215 }
1216
1217 unsigned int _mmcamcorder_get_fourcc(int pixtype, int codectype, int use_zero_copy_format)
1218 {
1219         unsigned int fourcc = 0;
1220
1221         /*_mmcam_dbg_log("pixtype(%d)", pixtype);*/
1222
1223         switch (pixtype) {
1224         case MM_PIXEL_FORMAT_NV12:
1225                 if (use_zero_copy_format) {
1226                         fourcc = GST_MAKE_FOURCC ('S', 'N', '1', '2');
1227                 } else {
1228                         fourcc = GST_MAKE_FOURCC ('N', 'V', '1', '2');
1229                 }
1230                 break;
1231         case MM_PIXEL_FORMAT_NV21:
1232                 if (use_zero_copy_format) {
1233                         fourcc = GST_MAKE_FOURCC ('S', 'N', '2', '1');
1234                 } else {
1235                         fourcc = GST_MAKE_FOURCC ('N', 'V', '2', '1');
1236                 }
1237                 break;
1238         case MM_PIXEL_FORMAT_YUYV:
1239                 if (use_zero_copy_format) {
1240                         fourcc = GST_MAKE_FOURCC ('S', 'U', 'Y', 'V');
1241                 } else {
1242                         fourcc = GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
1243                 }
1244                 break;
1245         case MM_PIXEL_FORMAT_UYVY:
1246                 if (use_zero_copy_format) {
1247                         fourcc = GST_MAKE_FOURCC ('S', 'Y', 'V', 'Y');
1248                 } else {
1249                         fourcc = GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
1250                 }
1251                 break;
1252         case MM_PIXEL_FORMAT_I420:
1253                 if (use_zero_copy_format) {
1254                         fourcc = GST_MAKE_FOURCC ('S', '4', '2', '0');
1255                 } else {
1256                         fourcc = GST_MAKE_FOURCC ('I', '4', '2', '0');
1257                 }
1258                 break;
1259         case MM_PIXEL_FORMAT_YV12:
1260                 fourcc = GST_MAKE_FOURCC ('Y', 'V', '1', '2');
1261                 break;
1262         case MM_PIXEL_FORMAT_422P:
1263                 fourcc = GST_MAKE_FOURCC ('4', '2', '2', 'P');
1264                 break;
1265         case MM_PIXEL_FORMAT_RGB565:
1266                 fourcc = GST_MAKE_FOURCC ('R', 'G', 'B', 'P');
1267                 break;
1268         case MM_PIXEL_FORMAT_RGB888:
1269                 fourcc = GST_MAKE_FOURCC ('R', 'G', 'B', ' ');
1270                 break;
1271         case MM_PIXEL_FORMAT_ENCODED:
1272                 if (codectype == MM_IMAGE_CODEC_JPEG) {
1273                         fourcc = GST_MAKE_FOURCC ('J', 'P', 'E', 'G');
1274                 } else if (codectype == MM_IMAGE_CODEC_JPEG_SRW) {
1275                         fourcc = GST_MAKE_FOURCC ('J', 'P', 'E', 'G'); /*TODO: JPEG+SamsungRAW format */
1276                 } else if (codectype == MM_IMAGE_CODEC_SRW) {
1277                         fourcc = GST_MAKE_FOURCC ('J', 'P', 'E', 'G'); /*TODO: SamsungRAW format */
1278                 } else if (codectype == MM_IMAGE_CODEC_PNG) {
1279                         fourcc = GST_MAKE_FOURCC ('P', 'N', 'G', ' ');
1280                 } else {
1281                         /* Please let us know what other fourcces are. ex) BMP, GIF?*/
1282                         fourcc = GST_MAKE_FOURCC ('J', 'P', 'E', 'G');
1283                 }
1284                 break;
1285         case MM_PIXEL_FORMAT_ITLV_JPEG_UYVY:
1286                 fourcc = GST_MAKE_FOURCC('I','T','L','V');
1287                 break;
1288         case MM_PIXEL_FORMAT_ENCODED_H264:
1289                 fourcc = GST_MAKE_FOURCC('H','2','6','4');
1290                 break;
1291         default:
1292                 _mmcam_dbg_log("Not proper pixel type[%d]. Set default - I420", pixtype);
1293                 if (use_zero_copy_format) {
1294                         fourcc = GST_MAKE_FOURCC ('S', '4', '2', '0');
1295                 } else {
1296                         fourcc = GST_MAKE_FOURCC ('I', '4', '2', '0');
1297                 }
1298                 break;
1299         }
1300
1301         return fourcc;
1302 }
1303
1304
1305 int _mmcamcorder_get_pixtype(unsigned int fourcc)
1306 {
1307         int pixtype = MM_PIXEL_FORMAT_INVALID;
1308         /*
1309         char *pfourcc = (char*)&fourcc;
1310
1311         _mmcam_dbg_log("fourcc(%c%c%c%c)",
1312                          pfourcc[0], pfourcc[1], pfourcc[2], pfourcc[3]);
1313         */
1314
1315         switch (fourcc) {
1316         case GST_MAKE_FOURCC ('S', 'N', '1', '2'):
1317         case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
1318                 pixtype = MM_PIXEL_FORMAT_NV12;
1319                 break;
1320         case GST_MAKE_FOURCC ('S', 'N', '2', '1'):
1321         case GST_MAKE_FOURCC ('N', 'V', '2', '1'):
1322                 pixtype = MM_PIXEL_FORMAT_NV21;
1323                 break;
1324         case GST_MAKE_FOURCC ('S', 'U', 'Y', 'V'):
1325         case GST_MAKE_FOURCC ('Y', 'U', 'Y', 'V'):
1326         case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
1327                 pixtype = MM_PIXEL_FORMAT_YUYV;
1328                 break;
1329         case GST_MAKE_FOURCC ('S', 'Y', 'V', 'Y'):
1330         case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
1331                 pixtype = MM_PIXEL_FORMAT_UYVY;
1332                 break;
1333         case GST_MAKE_FOURCC ('S', '4', '2', '0'):
1334         case GST_MAKE_FOURCC ('I', '4', '2', '0'):
1335                 pixtype = MM_PIXEL_FORMAT_I420;
1336                 break;
1337         case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
1338                 pixtype = MM_PIXEL_FORMAT_YV12;
1339                 break;
1340         case GST_MAKE_FOURCC ('4', '2', '2', 'P'):
1341                 pixtype = MM_PIXEL_FORMAT_422P;
1342                 break;
1343         case GST_MAKE_FOURCC ('R', 'G', 'B', 'P'):
1344                 pixtype = MM_PIXEL_FORMAT_RGB565;
1345                 break;
1346         case GST_MAKE_FOURCC ('R', 'G', 'B', '3'):
1347                 pixtype = MM_PIXEL_FORMAT_RGB888;
1348                 break;
1349         case GST_MAKE_FOURCC ('A', 'R', 'G', 'B'):
1350         case GST_MAKE_FOURCC ('x', 'R', 'G', 'B'):
1351                 pixtype = MM_PIXEL_FORMAT_ARGB;
1352                 break;
1353         case GST_MAKE_FOURCC ('B', 'G', 'R', 'A'):
1354         case GST_MAKE_FOURCC ('B', 'G', 'R', 'x'):
1355         case GST_MAKE_FOURCC ('S', 'R', '3', '2'):
1356                 pixtype = MM_PIXEL_FORMAT_RGBA;
1357                 break;
1358         case GST_MAKE_FOURCC ('J', 'P', 'E', 'G'):
1359         case GST_MAKE_FOURCC ('P', 'N', 'G', ' '):
1360                 pixtype = MM_PIXEL_FORMAT_ENCODED;
1361                 break;
1362         /*FIXME*/
1363         case GST_MAKE_FOURCC ('I', 'T', 'L', 'V'):
1364                 pixtype = MM_PIXEL_FORMAT_ITLV_JPEG_UYVY;
1365                 break;
1366         case GST_MAKE_FOURCC ('H', '2', '6', '4'):
1367                 pixtype = MM_PIXEL_FORMAT_ENCODED_H264;
1368                 break;
1369         default:
1370                 _mmcam_dbg_log("Not supported fourcc type(%c%c%c%c)",
1371                                fourcc, fourcc>>8, fourcc>>16, fourcc>>24);
1372                 pixtype = MM_PIXEL_FORMAT_INVALID;
1373                 break;
1374         }
1375
1376         return pixtype;
1377 }
1378
1379
1380 gboolean _mmcamcorder_add_elements_to_bin(GstBin *bin, GList *element_list)
1381 {
1382         GList *local_list = element_list;
1383         _MMCamcorderGstElement *element = NULL;
1384
1385         mmf_return_val_if_fail(bin && local_list, FALSE);
1386
1387         while (local_list) {
1388                 element = (_MMCamcorderGstElement*)local_list->data;
1389                 if (element && element->gst) {
1390                         if (!gst_bin_add(bin, GST_ELEMENT(element->gst))) {
1391                                 _mmcam_dbg_err( "Add element [%s] to bin [%s] FAILED",
1392                                                 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
1393                                                 GST_ELEMENT_NAME(GST_ELEMENT(bin)) );
1394                                 return FALSE;
1395                         } else {
1396                                 _mmcam_dbg_log("Add element [%s] to bin [%s] OK",
1397                                                GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
1398                                                GST_ELEMENT_NAME(GST_ELEMENT(bin)));
1399                         }
1400                 }
1401                 local_list = local_list->next;
1402         }
1403
1404         return TRUE;
1405 }
1406
1407 gboolean _mmcamcorder_link_elements(GList *element_list)
1408 {
1409         GList                  *local_list  = element_list;
1410         _MMCamcorderGstElement *element     = NULL;
1411         _MMCamcorderGstElement *pre_element = NULL;
1412
1413         mmf_return_val_if_fail(local_list, FALSE);
1414
1415         pre_element = (_MMCamcorderGstElement*)local_list->data;
1416         local_list = local_list->next;
1417
1418         while (local_list) {
1419                 element = (_MMCamcorderGstElement*)local_list->data;
1420                 if (element && element->gst) {
1421                         if (_MM_GST_ELEMENT_LINK(GST_ELEMENT(pre_element->gst), GST_ELEMENT(element->gst))) {
1422                                 _mmcam_dbg_log("Link [%s] to [%s] OK",
1423                                                GST_ELEMENT_NAME(GST_ELEMENT(pre_element->gst)),
1424                                                GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
1425                         } else {
1426                                 _mmcam_dbg_err("Link [%s] to [%s] FAILED",
1427                                                GST_ELEMENT_NAME(GST_ELEMENT(pre_element->gst)),
1428                                                GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
1429                                 return FALSE;
1430                         }
1431                 }
1432
1433                 pre_element = element;
1434                 local_list = local_list->next;
1435         }
1436
1437         return TRUE;
1438 }
1439
1440
1441 gboolean _mmcamcorder_resize_frame(unsigned char *src_data, unsigned int src_width, unsigned int src_height, unsigned int src_length, int src_format,
1442                                    unsigned char **dst_data, unsigned int *dst_width, unsigned int *dst_height, unsigned int *dst_length)
1443 {
1444         int ret = TRUE;
1445         int mm_ret = MM_ERROR_NONE;
1446         int input_format = MM_UTIL_IMG_FMT_YUV420;
1447         unsigned char *dst_tmp_data = NULL;
1448
1449         if (!src_data || !dst_data || !dst_width || !dst_height || !dst_length) {
1450                 _mmcam_dbg_err("something is NULL %p,%p,%p,%p,%p",
1451                                src_data, dst_data, dst_width, dst_height, dst_length);
1452                 return FALSE;
1453         }
1454
1455         /* set input format for mm-util */
1456         switch (src_format) {
1457         case MM_PIXEL_FORMAT_I420:
1458                 input_format = MM_UTIL_IMG_FMT_I420;
1459                 break;
1460         case MM_PIXEL_FORMAT_YV12:
1461                 input_format = MM_UTIL_IMG_FMT_YUV420;
1462                 break;
1463         case MM_PIXEL_FORMAT_NV12:
1464                 input_format = MM_UTIL_IMG_FMT_NV12;
1465                 break;
1466         case MM_PIXEL_FORMAT_YUYV:
1467                 input_format = MM_UTIL_IMG_FMT_YUYV;
1468                 break;
1469         case MM_PIXEL_FORMAT_UYVY:
1470                 input_format = MM_UTIL_IMG_FMT_UYVY;
1471                 break;
1472         case MM_PIXEL_FORMAT_RGB888:
1473                 input_format = MM_UTIL_IMG_FMT_RGB888;
1474                 break;
1475         default:
1476                 _mmcam_dbg_err("NOT supported format", src_format);
1477                 return FALSE;
1478         }
1479
1480         _mmcam_dbg_log("src size %dx%d -> dst size %dx%d",
1481                         src_width, src_height, *dst_width, *dst_height);
1482
1483         /* get length of resized image */
1484         mm_ret = mm_util_get_image_size(input_format, *dst_width, *dst_height, dst_length);
1485         if (mm_ret != MM_ERROR_NONE) {
1486                 GST_ERROR("mm_util_get_image_size failed 0x%x", ret);
1487                 return FALSE;
1488         }
1489
1490         _mmcam_dbg_log("dst_length : %d", *dst_length);
1491
1492         dst_tmp_data = (unsigned char *)malloc(*dst_length);
1493         if (dst_tmp_data == NULL) {
1494                 _mmcam_dbg_err("failed to alloc dst_thumb_size(size %d)", *dst_length);
1495                 return FALSE;
1496         }
1497
1498         mm_ret = mm_util_resize_image(src_data, src_width, src_height, input_format,
1499                                       dst_tmp_data, dst_width, dst_height);
1500         if (mm_ret != MM_ERROR_NONE) {
1501                 GST_ERROR("mm_util_resize_image failed 0x%x", ret);
1502                 free(dst_tmp_data);
1503                 return FALSE;
1504         }
1505
1506         *dst_data = dst_tmp_data;
1507
1508         _mmcam_dbg_log("resize done %p, %dx%d", *dst_data, *dst_width, *dst_height);
1509
1510         return TRUE;
1511 }
1512
1513
1514 gboolean _mmcamcorder_encode_jpeg(void *src_data, unsigned int src_width, unsigned int src_height,
1515                                   int src_format, unsigned int src_length, unsigned int jpeg_quality,
1516                                   void **result_data, unsigned int *result_length)
1517 {
1518         int ret = 0;
1519         gboolean ret_conv = TRUE;
1520         guint32 src_fourcc = 0;
1521         int jpeg_format = 0;
1522         unsigned char *converted_src = NULL;
1523         unsigned int converted_src_size = 0;
1524
1525         mmf_return_val_if_fail(src_data && result_data && result_length, FALSE);
1526
1527         src_fourcc = _mmcamcorder_get_fourcc(src_format, 0, FALSE);
1528
1529         switch (src_format) {
1530                 case MM_PIXEL_FORMAT_NV12:
1531                         //jpeg_format = MM_UTIL_JPEG_FMT_NV12;
1532                         ret_conv = _mmcamcorder_convert_NV12_to_I420(src_data,src_width,src_height,&converted_src,&converted_src_size);
1533                         jpeg_format = MM_UTIL_JPEG_FMT_YUV420;
1534                         break;
1535                 case MM_PIXEL_FORMAT_NV16:
1536                         jpeg_format = MM_UTIL_JPEG_FMT_NV16;
1537                         converted_src = src_data;
1538                         break;
1539                 case MM_PIXEL_FORMAT_NV21:
1540                         jpeg_format = MM_UTIL_JPEG_FMT_NV21;
1541                         converted_src = src_data;
1542                         break;
1543                 case MM_PIXEL_FORMAT_YUYV:
1544                         //jpeg_format = MM_UTIL_JPEG_FMT_YUYV;
1545                         ret_conv = _mmcamcorder_convert_YUYV_to_I420(src_data,src_width,src_height,&converted_src,&converted_src_size);
1546                         jpeg_format = MM_UTIL_JPEG_FMT_YUV420;
1547                         break;
1548                 case MM_PIXEL_FORMAT_UYVY:
1549                         //jpeg_format = MM_UTIL_JPEG_FMT_UYVY;
1550                         ret_conv = _mmcamcorder_convert_UYVY_to_I420(src_data,src_width,src_height,&converted_src,&converted_src_size);
1551                         jpeg_format = MM_UTIL_JPEG_FMT_YUV420;
1552                         break;
1553                 case MM_PIXEL_FORMAT_I420:
1554                         jpeg_format = MM_UTIL_JPEG_FMT_YUV420;
1555                         converted_src = src_data;
1556                         break;
1557                 case MM_PIXEL_FORMAT_RGB888:
1558                         jpeg_format = MM_UTIL_JPEG_FMT_RGB888;
1559                         converted_src = src_data;
1560                         break;
1561                 case MM_PIXEL_FORMAT_RGBA:
1562                         jpeg_format = MM_UTIL_JPEG_FMT_RGBA8888;
1563                         converted_src = src_data;
1564                         break;
1565                 case MM_PIXEL_FORMAT_ARGB:
1566                         jpeg_format = MM_UTIL_JPEG_FMT_ARGB8888;
1567                         converted_src = src_data;
1568                         break;
1569                 case MM_PIXEL_FORMAT_422P:
1570                         jpeg_format = MM_UTIL_JPEG_FMT_YUV422;  // not supported
1571                         return FALSE;
1572                 case MM_PIXEL_FORMAT_NV12T:
1573                 case MM_PIXEL_FORMAT_YV12:
1574                 case MM_PIXEL_FORMAT_RGB565:
1575                 case MM_PIXEL_FORMAT_ENCODED:
1576                 case MM_PIXEL_FORMAT_ITLV_JPEG_UYVY:
1577                 default:
1578                         return FALSE;
1579
1580         }
1581
1582         if (ret_conv == FALSE) {
1583                 if (converted_src &&
1584                     converted_src != src_data) {
1585                         free(converted_src);
1586                         converted_src = NULL;
1587                 }
1588                 _mmcam_dbg_err("color convert error source format[%d], jpeg format[%d]", src_format, jpeg_format);
1589                 return FALSE;
1590         }
1591
1592         ret = mm_util_jpeg_encode_to_memory(result_data, (int *)result_length,
1593                                             converted_src, src_width, src_height,
1594                                             jpeg_format, jpeg_quality);
1595
1596         if (converted_src && (converted_src != src_data)) {
1597                 free(converted_src);
1598                 converted_src = NULL;
1599         }
1600
1601         if (ret != MM_ERROR_NONE) {
1602                 _mmcam_dbg_err("No encoder supports %d format, error code %x", src_format, ret);
1603                 return FALSE;
1604         }
1605
1606         return TRUE;
1607 }
1608
1609
1610 /* make UYVY smaller as multiple size. ex: 640x480 -> 320x240 or 160x120 ... */
1611 gboolean _mmcamcorder_downscale_UYVYorYUYV(unsigned char *src, unsigned int src_width, unsigned int src_height,
1612                                            unsigned char **dst, unsigned int dst_width, unsigned int dst_height)
1613 {
1614         unsigned int i = 0;
1615         int j = 0;
1616         int k = 0;
1617         int src_index = 0;
1618         int ratio_width = 0;
1619         int ratio_height = 0;
1620         int line_base = 0;
1621         int line_width = 0;
1622         int jump_width = 0;
1623         unsigned char *result = NULL;
1624
1625         if (src == NULL || dst == NULL) {
1626                 _mmcam_dbg_err("src[%p] or dst[%p] is NULL", src, dst);
1627                 return FALSE;
1628         }
1629
1630         result = (unsigned char *)malloc((dst_width * dst_height)<<1);
1631         if (!result) {
1632                 _mmcam_dbg_err("failed to alloc dst data");
1633                 return FALSE;
1634         }
1635
1636         ratio_width = src_width / dst_width;
1637         ratio_height = src_height / dst_height;
1638         line_width = src_width << 1;
1639         jump_width = ratio_width << 1;
1640
1641         _mmcam_dbg_warn("[src %dx%d] [dst %dx%d] [line width %d] [ratio width %d, height %d]",
1642                         src_width, src_height, dst_width, dst_height,
1643                         line_width, ratio_width, ratio_height);
1644
1645         for (i = 0 ; i < src_height ; i += ratio_height) {
1646                 line_base = i * line_width;
1647                 for (j = 0 ; j < line_width ; j += jump_width) {
1648                         src_index = line_base + j;
1649                         result[k++] = src[src_index];
1650                         result[k++] = src[src_index+1];
1651
1652                         j += jump_width;
1653                         src_index = line_base + j;
1654                         if (src_index % 4 == 0) {
1655                                 result[k++] = src[src_index+2];
1656                         } else {
1657                                 result[k++] = src[src_index];
1658                         }
1659                         result[k++] = src[src_index+1];
1660                 }
1661         }
1662
1663         *dst = result;
1664
1665         _mmcam_dbg_warn("converting done - result %p", result);
1666
1667         return TRUE;
1668 }
1669
1670 gboolean _mmcamcorder_check_file_path(const gchar *path)
1671 {
1672         if(strstr(path, "/opt/usr") != NULL) {
1673                 return TRUE;
1674         }
1675         return FALSE;
1676 }
1677
1678 static guint16 get_language_code(const char *str)
1679 {
1680     return (guint16) (((str[0]-0x60) & 0x1F) << 10) + (((str[1]-0x60) & 0x1F) << 5) + ((str[2]-0x60) & 0x1F);
1681 }
1682
1683 static gchar * str_to_utf8(const gchar *str)
1684 {
1685         return g_convert (str, -1, "UTF-8", "ASCII", NULL, NULL, NULL);
1686 }
1687
1688 static inline gboolean write_tag(FILE *f, const gchar *tag)
1689 {
1690         while(*tag)
1691                 FPUTC_CHECK(*tag++, f);
1692
1693         return TRUE;
1694 }
1695
1696 static inline gboolean write_to_32(FILE *f, guint val)
1697 {
1698         FPUTC_CHECK(val >> 24, f);
1699         FPUTC_CHECK(val >> 16, f);
1700         FPUTC_CHECK(val >> 8, f);
1701         FPUTC_CHECK(val, f);
1702         return TRUE;
1703 }
1704
1705 static inline gboolean write_to_16(FILE *f, guint val)
1706 {
1707         FPUTC_CHECK(val >> 8, f);
1708         FPUTC_CHECK(val, f);
1709         return TRUE;
1710 }
1711
1712 static inline gboolean write_to_24(FILE *f, guint val)
1713 {
1714         write_to_16(f, val >> 8);
1715         FPUTC_CHECK(val, f);
1716         return TRUE;
1717 }
1718
1719 void *_mmcamcorder_util_task_thread_func(void *data)
1720 {
1721         int ret = MM_ERROR_NONE;
1722         mmf_camcorder_t *hcamcorder = (mmf_camcorder_t *)data;
1723
1724         if (!hcamcorder) {
1725                 _mmcam_dbg_err("handle is NULL");
1726                 return NULL;
1727         }
1728
1729         _mmcam_dbg_warn("start thread");
1730
1731         pthread_mutex_lock(&(hcamcorder->task_thread_lock));
1732
1733         while (hcamcorder->task_thread_state != _MMCAMCORDER_TASK_THREAD_STATE_EXIT) {
1734                 switch (hcamcorder->task_thread_state) {
1735                 case _MMCAMCORDER_TASK_THREAD_STATE_NONE:
1736                         _mmcam_dbg_warn("wait for task signal");
1737                         pthread_cond_wait(&(hcamcorder->task_thread_cond), &(hcamcorder->task_thread_lock));
1738                         _mmcam_dbg_warn("task signal received : state %d", hcamcorder->task_thread_state);
1739                         break;
1740                 case _MMCAMCORDER_TASK_THREAD_STATE_SOUND_PLAY_START:
1741                         _mmcamcorder_sound_play((MMHandleType)hcamcorder, _MMCAMCORDER_SAMPLE_SOUND_NAME_CAPTURE, FALSE);
1742                         hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_NONE;
1743                         break;
1744                 case _MMCAMCORDER_TASK_THREAD_STATE_ENCODE_PIPE_CREATE:
1745                         ret = _mmcamcorder_video_prepare_record((MMHandleType)hcamcorder);
1746
1747                         /* Play record start sound */
1748                         _mmcamcorder_sound_solo_play((MMHandleType)hcamcorder, _MMCAMCORDER_FILEPATH_REC_START_SND, FALSE);
1749
1750                         _mmcam_dbg_log("_mmcamcorder_video_prepare_record return 0x%x", ret);
1751                         hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_NONE;
1752                         break;
1753                 default:
1754                         _mmcam_dbg_warn("invalid task thread state %d", hcamcorder->task_thread_state);
1755                         hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_EXIT;
1756                         break;
1757                 }
1758         }
1759
1760         pthread_mutex_unlock(&(hcamcorder->task_thread_lock));
1761
1762         _mmcam_dbg_warn("exit thread");
1763
1764         return NULL;
1765 }
1766
1767 #ifdef _USE_YUV_TO_RGB888_
1768 static gboolean
1769 _mmcamcorder_convert_YUV_to_RGB888(unsigned char *src, int src_fmt, guint width, guint height, unsigned char **dst, unsigned int *dst_len)
1770 {
1771         int ret = 0;
1772         int src_cs = MM_UTIL_IMG_FMT_UYVY;
1773         int dst_cs = MM_UTIL_IMG_FMT_RGB888;
1774         unsigned int dst_size = 0;
1775
1776         if (src_fmt == COLOR_FORMAT_YUYV)
1777         {
1778                 _mmcam_dbg_log("Convert YUYV to RGB888\n");
1779                 src_cs = MM_UTIL_IMG_FMT_YUYV;
1780         }
1781         else if (src_fmt == COLOR_FORMAT_UYVY)
1782         {
1783                 _mmcam_dbg_log("Convert UYVY to RGB888\n");
1784                 src_cs = MM_UTIL_IMG_FMT_UYVY;
1785         }
1786         else if (src_fmt == COLOR_FORMAT_NV12)
1787         {
1788                 _mmcam_dbg_log("Convert NV12 to RGB888\n");
1789                 src_cs = MM_UTIL_IMG_FMT_NV12;
1790         }
1791         else
1792         {
1793                 _mmcam_dbg_err("NOT supported format [%d]\n", src_fmt);
1794                 return FALSE;
1795         }
1796
1797         ret = mm_util_get_image_size(dst_cs, width, height, &dst_size);
1798         if (ret != 0) {
1799                 _mmcam_dbg_err("mm_util_get_image_size failed [%x]\n", ret);
1800                 return FALSE;
1801         }
1802
1803         *dst = malloc(dst_size);
1804         if (*dst == NULL)
1805         {
1806                 _mmcam_dbg_err("malloc failed\n");
1807                 return FALSE;
1808         }
1809
1810         *dst_len = dst_size;
1811         ret = mm_util_convert_colorspace(src, width, height, src_cs, *dst, dst_cs);
1812         if(ret == 0)
1813         {
1814                 _mmcam_dbg_log("Convert [dst_size:%d] OK.\n", dst_size);
1815                 return TRUE;
1816         }
1817         else
1818         {
1819                 free(*dst);
1820                 *dst = NULL;
1821
1822                 _mmcam_dbg_err("Convert [size:%d] FAILED.\n", dst_size);
1823                 return FALSE;
1824         }
1825 }
1826 #endif /* _USE_YUV_TO_RGB888_ */
1827
1828
1829 static gboolean _mmcamcorder_convert_YUYV_to_I420(unsigned char *src, guint width, guint height, unsigned char **dst, unsigned int *dst_len)
1830 {
1831         unsigned int i = 0;
1832         int j = 0;
1833         int src_offset = 0;
1834         int dst_y_offset = 0;
1835         int dst_u_offset = 0;
1836         int dst_v_offset = 0;
1837         int loop_length = 0;
1838         unsigned int dst_size = 0;
1839         unsigned char *dst_data = NULL;
1840
1841         if (!src || !dst || !dst_len) {
1842                 _mmcam_dbg_err("NULL pointer %p, %p, %p", src, dst, dst_len);
1843                 return FALSE;
1844         }
1845
1846         dst_size = (width * height * 3) >> 1;
1847
1848         _mmcam_dbg_log("YUVY -> I420 : %dx%d, dst size %d", width, height, dst_size);
1849
1850         dst_data = (unsigned char *)malloc(dst_size);
1851         if (!dst_data) {
1852                 _mmcam_dbg_err("failed to alloc dst_data. size %d", dst_size);
1853                 return FALSE;
1854         }
1855
1856         loop_length = width << 1;
1857         dst_u_offset = width * height;
1858         dst_v_offset = dst_u_offset + (dst_u_offset >> 2);
1859
1860         _mmcam_dbg_log("offset y %d, u %d, v %d", dst_y_offset, dst_u_offset, dst_v_offset);
1861
1862         for (i = 0 ; i < height ; i++) {
1863                 for (j = 0 ; j < loop_length ; j += 2) {
1864                         dst_data[dst_y_offset++] = src[src_offset++]; /*Y*/
1865
1866                         if (i % 2 == 0) {
1867                                 if (j % 4 == 0) {
1868                                         dst_data[dst_u_offset++] = src[src_offset++]; /*U*/
1869                                 } else {
1870                                         dst_data[dst_v_offset++] = src[src_offset++]; /*V*/
1871                                 }
1872                         } else {
1873                                 src_offset++;
1874                         }
1875                 }
1876         }
1877
1878         *dst = dst_data;
1879         *dst_len = dst_size;
1880
1881         _mmcam_dbg_log("DONE: YUVY -> I420 : %dx%d, dst data %p, size %d",
1882                                 width, height, *dst, dst_size);
1883
1884         return TRUE;
1885 }
1886
1887
1888 static gboolean _mmcamcorder_convert_UYVY_to_I420(unsigned char *src, guint width, guint height, unsigned char **dst, unsigned int *dst_len)
1889 {
1890         unsigned int i = 0;
1891         int j = 0;
1892         int src_offset = 0;
1893         int dst_y_offset = 0;
1894         int dst_u_offset = 0;
1895         int dst_v_offset = 0;
1896         int loop_length = 0;
1897         unsigned int dst_size = 0;
1898         unsigned char *dst_data = NULL;
1899
1900         if (!src || !dst || !dst_len) {
1901                 _mmcam_dbg_err("NULL pointer %p, %p, %p", src, dst, dst_len);
1902                 return FALSE;
1903         }
1904
1905         dst_size = (width * height * 3) >> 1;
1906
1907         _mmcam_dbg_log("UYVY -> I420 : %dx%d, dst size %d", width, height, dst_size);
1908
1909         dst_data = (unsigned char *)malloc(dst_size);
1910         if (!dst_data) {
1911                 _mmcam_dbg_err("failed to alloc dst_data. size %d", dst_size);
1912                 return FALSE;
1913         }
1914
1915         loop_length = width << 1;
1916         dst_u_offset = width * height;
1917         dst_v_offset = dst_u_offset + (dst_u_offset >> 2);
1918
1919         _mmcam_dbg_log("offset y %d, u %d, v %d", dst_y_offset, dst_u_offset, dst_v_offset);
1920
1921         for (i = 0 ; i < height ; i++) {
1922                 for (j = 0 ; j < loop_length ; j += 2) {
1923                         if (i % 2 == 0) {
1924                                 if (j % 4 == 0) {
1925                                         dst_data[dst_u_offset++] = src[src_offset++]; /*U*/
1926                                 } else {
1927                                         dst_data[dst_v_offset++] = src[src_offset++]; /*V*/
1928                                 }
1929                         } else {
1930                                 src_offset++;
1931                         }
1932
1933                         dst_data[dst_y_offset++] = src[src_offset++]; /*Y*/
1934                 }
1935         }
1936
1937         *dst = dst_data;
1938         *dst_len = dst_size;
1939
1940         _mmcam_dbg_log("DONE: UYVY -> I420 : %dx%d, dst data %p, size %d",
1941                                 width, height, *dst, dst_size);
1942
1943         return TRUE;
1944 }
1945
1946
1947 static gboolean _mmcamcorder_convert_NV12_to_I420(unsigned char *src, guint width, guint height, unsigned char **dst, unsigned int *dst_len)
1948 {
1949         int i = 0;
1950         int src_offset = 0;
1951         int dst_y_offset = 0;
1952         int dst_u_offset = 0;
1953         int dst_v_offset = 0;
1954         int loop_length = 0;
1955         unsigned int dst_size = 0;
1956         unsigned char *dst_data = NULL;
1957
1958         if (!src || !dst || !dst_len) {
1959                 _mmcam_dbg_err("NULL pointer %p, %p, %p", src, dst, dst_len);
1960                 return FALSE;
1961         }
1962
1963         dst_size = (width * height * 3) >> 1;
1964
1965         _mmcam_dbg_log("NV12 -> I420 : %dx%d, dst size %d", width, height, dst_size);
1966
1967         dst_data = (unsigned char *)malloc(dst_size);
1968         if (!dst_data) {
1969                 _mmcam_dbg_err("failed to alloc dst_data. size %d", dst_size);
1970                 return FALSE;
1971         }
1972
1973         loop_length = width << 1;
1974         dst_u_offset = width * height;
1975         dst_v_offset = dst_u_offset + (dst_u_offset >> 2);
1976
1977         _mmcam_dbg_log("offset y %d, u %d, v %d", dst_y_offset, dst_u_offset, dst_v_offset);
1978
1979         /* memcpy Y */
1980         memcpy(dst_data, src, dst_u_offset);
1981
1982         loop_length = dst_u_offset >> 1;
1983         src_offset = dst_u_offset;
1984
1985         /* set U and V */
1986         for (i = 0 ; i < loop_length ; i++) {
1987                 if (i % 2 == 0) {
1988                         dst_data[dst_u_offset++] = src[src_offset++];
1989                 } else {
1990                         dst_data[dst_v_offset++] = src[src_offset++];
1991                 }
1992         }
1993
1994         *dst = dst_data;
1995         *dst_len = dst_size;
1996
1997         _mmcam_dbg_log("DONE: NV12 -> I420 : %dx%d, dst data %p, size %d",
1998                                 width, height, *dst, dst_size);
1999
2000         return TRUE;
2001 }
2002