1. Seperate preview pipeline and encoding pipeline
[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 <sys/vfs.h> /* struct statfs */
28 #include <sys/stat.h>
29 #include <gst/video/video-info.h>
30
31 #include "mm_camcorder_internal.h"
32 #include "mm_camcorder_util.h"
33 #include "mm_camcorder_sound.h"
34 #include <mm_util_imgp.h>
35
36 /*-----------------------------------------------------------------------
37 |    GLOBAL VARIABLE DEFINITIONS for internal                           |
38 -----------------------------------------------------------------------*/
39
40 /*-----------------------------------------------------------------------
41 |    LOCAL VARIABLE DEFINITIONS for internal                            |
42 -----------------------------------------------------------------------*/
43 #define TIME_STRING_MAX_LEN     64
44
45 #define FPUTC_CHECK(x_char, x_file)\
46 {\
47         if (fputc(x_char, x_file) == EOF) \
48         {\
49                 _mmcam_dbg_err("[Critical] fputc() returns fail.\n");   \
50                 return FALSE;\
51         }\
52 }
53 #define FPUTS_CHECK(x_str, x_file)\
54 {\
55         if (fputs(x_str, x_file) == EOF) \
56         {\
57                 _mmcam_dbg_err("[Critical] fputs() returns fail.\n");\
58                 SAFE_FREE(str); \
59                 return FALSE;\
60         }\
61 }
62
63 /*---------------------------------------------------------------------------
64 |    LOCAL FUNCTION PROTOTYPES:                                                                                         |
65 ---------------------------------------------------------------------------*/
66 /* STATIC INTERNAL FUNCTION */
67
68 //static gint           skip_mdat(FILE *f);
69 static guint16           get_language_code(const char *str);
70 static gchar*            str_to_utf8(const gchar *str);
71 static inline gboolean   write_tag(FILE *f, const gchar *tag);
72 static inline gboolean   write_to_32(FILE *f, guint val);
73 static inline gboolean   write_to_16(FILE *f, guint val);
74 static inline gboolean   write_to_24(FILE *f, guint val);
75
76 /*===========================================================================================
77 |                                                                                                                                                                                       |
78 |  FUNCTION DEFINITIONS                                                                                                                                         |
79 |                                                                                                                                                                                       |
80 ========================================================================================== */
81 /*---------------------------------------------------------------------------
82 |    GLOBAL FUNCTION DEFINITIONS:                                                                                       |
83 ---------------------------------------------------------------------------*/
84
85 gint32 _mmcamcorder_double_to_fix(gdouble d_number)
86 {
87         return (gint32) (d_number * 65536.0);
88 }
89
90 // find top level tag only, do not use this function for finding sub level tags
91 gint _mmcamcorder_find_tag(FILE *f, guint32 tag_fourcc, gboolean do_rewind)
92 {
93         guchar buf[8];
94
95         if (do_rewind) {
96                 rewind(f);
97         }
98
99         while (fread(&buf, sizeof(guchar), 8, f)>0) {
100                 unsigned long long buf_size = 0;
101                 unsigned int buf_fourcc = MMCAM_FOURCC(buf[4], buf[5], buf[6], buf[7]);
102
103                 if (tag_fourcc == buf_fourcc) {
104                         _mmcam_dbg_log("find tag : %c%c%c%c", MMCAM_FOURCC_ARGS(tag_fourcc));
105                         return TRUE;
106                 } else {
107                         _mmcam_dbg_log("skip [%c%c%c%c] tag", MMCAM_FOURCC_ARGS(buf_fourcc));
108
109                         buf_size = (unsigned long long)_mmcamcorder_get_container_size(buf);
110                         buf_size = buf_size - 8; /* include tag */
111
112                         do {
113                                 if (buf_size > _MMCAMCORDER_MAX_INT) {
114                                         _mmcam_dbg_log("seek %d", _MMCAMCORDER_MAX_INT);
115                                         if (fseek(f, _MMCAMCORDER_MAX_INT, SEEK_CUR) != 0) {
116                                                 _mmcam_dbg_err("fseek() fail");
117                                                 return FALSE;
118                                         }
119
120                                         buf_size -= _MMCAMCORDER_MAX_INT;
121                                 } else {
122                                         _mmcam_dbg_log("seek %d", buf_size);
123                                         if (fseek(f, buf_size, SEEK_CUR) != 0) {
124                                                 _mmcam_dbg_err("fseek() fail");
125                                                 return FALSE;
126                                         }
127                                         break;
128                                 }
129                         } while (TRUE);
130                 }
131         }
132
133         _mmcam_dbg_log("cannot find tag : %c%c%c%c", MMCAM_FOURCC_ARGS(tag_fourcc));
134
135         return FALSE;
136 }
137
138 gboolean _mmcamcorder_update_size(FILE *f, gint64 prev_pos, gint64 curr_pos)
139 {
140         _mmcam_dbg_log("size : %"G_GINT64_FORMAT"", curr_pos-prev_pos);
141         if(fseek(f, prev_pos, SEEK_SET) != 0)
142         {
143                 _mmcam_dbg_err("fseek() fail");
144                 return FALSE;
145         }
146
147         if (!write_to_32(f, curr_pos -prev_pos))
148                 return FALSE;
149         
150         if(fseek(f, curr_pos, SEEK_SET) != 0)
151         {
152                 _mmcam_dbg_err("fseek() fail");
153                 return FALSE;
154         }
155         
156         return TRUE;
157 }
158
159 gboolean _mmcamcorder_write_loci(FILE *f, _MMCamcorderLocationInfo info)
160 {
161         gint64 current_pos, pos;
162         gchar *str = NULL;
163
164         _mmcam_dbg_log("");
165
166         if((pos = ftell(f))<0)
167         {
168                 _mmcam_dbg_err("ftell() returns negative value");       
169                 return FALSE;
170         }
171         
172         if(!write_to_32(f, 0)) //size
173                 return FALSE;
174         
175         if(!write_tag(f, "loci"))       // type
176                 return FALSE;
177
178         FPUTC_CHECK(0, f);              // version
179
180         if(!write_to_24(f, 0))  // flags
181                 return FALSE;
182
183         if(!write_to_16(f, get_language_code("eng"))) // language
184                 return FALSE;
185
186         str = str_to_utf8("location_name");
187
188         FPUTS_CHECK(str, f); // name
189         SAFE_FREE(str);
190
191         FPUTC_CHECK('\0', f);
192         FPUTC_CHECK(0, f);              //role
193
194         if(!write_to_32(f, info.longitude))     // Longitude
195                 return FALSE;
196
197         if(!write_to_32(f, info.latitude)) // Latitude
198                 return FALSE;
199
200         if(! write_to_32(f, info.altitude))     // Altitude
201                 return FALSE;
202
203         str = str_to_utf8("Astronomical_body");
204         FPUTS_CHECK(str, f);//Astronomical_body
205         SAFE_FREE(str);
206
207         FPUTC_CHECK('\0', f);
208
209         str = str_to_utf8("Additional_notes");
210         FPUTS_CHECK(str, f); // Additional_notes
211         SAFE_FREE(str);
212
213         FPUTC_CHECK('\0', f);
214
215         if((current_pos = ftell(f))<0)
216         {
217                 _mmcam_dbg_err("ftell() returns negative value");
218                 return FALSE;
219         }
220
221         if(! _mmcamcorder_update_size(f, pos, current_pos))
222                 return FALSE;
223
224         return TRUE;
225 }
226
227 void _mmcamcorder_write_Latitude(FILE *f,int degreex10000)
228 {
229         bool isNegative = (degreex10000 < 0);
230         char sign = isNegative? '-': '+';
231
232         // Handle the whole part
233         char str[9];
234         int wholePart = 0;
235         int fractionalPart = 0;
236
237         wholePart = degreex10000 / 10000;
238         if (wholePart == 0) {
239                 snprintf(str, 5, "%c%.2d.", sign, wholePart);
240         } else {
241                 snprintf(str, 5, "%+.2d.", wholePart);
242         }
243
244         // Handle the fractional part
245         fractionalPart = degreex10000 - (wholePart * 10000);
246         if (fractionalPart < 0) {
247                 fractionalPart = -fractionalPart;
248         }
249         snprintf(&str[4], 5, "%.4d", fractionalPart);
250
251         // Do not write the null terminator
252         write_tag(f, str);
253
254         return;
255 }
256
257
258 gboolean _mmcamcorder_write_udta(FILE *f, _MMCamcorderLocationInfo info)
259 {
260         gint64 current_pos, pos;
261
262         _mmcam_dbg_log("");
263
264         if((pos = ftell(f))<0)
265         {
266                 _mmcam_dbg_err("ftell() returns negative value");
267                 return FALSE;
268         }
269
270         if(!write_to_32(f, 0))  //size
271                 return FALSE;
272
273         if(!write_tag(f, "udta"))       // type
274                 return FALSE;
275
276         if(! _mmcamcorder_write_loci(f, info))
277                 return FALSE;
278
279         if((current_pos = ftell(f))<0)
280         {
281                 _mmcam_dbg_err("ftell() returns negative value");
282                 return FALSE;
283         }
284
285         if(! _mmcamcorder_update_size(f, pos, current_pos))
286                 return FALSE;
287
288         return TRUE;
289 }
290
291
292 guint64 _mmcamcorder_get_container_size(const guchar *size)
293 {
294         guint64 result = 0;
295         guint64 temp = 0;
296
297         temp = size[0];
298         result = temp << 24;
299         temp = size[1];
300         result = result | (temp << 16);
301         temp = size[2];
302         result = result | (temp << 8);
303         result = result | size[3];
304
305         _mmcam_dbg_log("result : %lld", (unsigned long long)result);
306
307         return result;
308 }
309
310
311 gboolean _mmcamcorder_update_composition_matrix(FILE *f, int orientation)
312 {
313         /* for 0 degree */
314         guint32 a = 0x00010000;
315         guint32 b = 0;
316         guint32 c = 0;
317         guint32 d = 0x00010000;
318
319         switch (orientation) {
320         case MM_CAMCORDER_TAG_VIDEO_ORT_90:/* 90 degree */
321                 a = 0;
322                 b = 0x00010000;
323                 c = 0xffff0000;
324                 d = 0;
325                 break;
326         case MM_CAMCORDER_TAG_VIDEO_ORT_180:/* 180 degree */
327                 a = 0xffff0000;
328                 d = 0xffff0000;
329                 break;
330         case MM_CAMCORDER_TAG_VIDEO_ORT_270:/* 270 degree */
331                 a = 0;
332                 b = 0xffff0000;
333                 c = 0x00010000;
334                 d = 0;
335                 break;
336         case MM_CAMCORDER_TAG_VIDEO_ORT_NONE:/* 0 degree */
337         default:
338                 break;
339         }
340
341         write_to_32(f, a);
342         write_to_32(f, b);
343         write_to_32(f, 0);
344         write_to_32(f, c);
345         write_to_32(f, d);
346         write_to_32(f, 0);
347         write_to_32(f, 0);
348         write_to_32(f, 0);
349         write_to_32(f, 0x40000000);
350
351         _mmcam_dbg_log("orientation : %d, write data 0x%x 0x%x 0x%x 0x%x",
352                        orientation, a, b, c, d);
353
354         return TRUE;
355 }
356
357
358 int _mmcamcorder_get_freespace(const gchar *path, guint64 *free_space)
359 {
360         struct statfs fs;
361
362         g_assert(path);
363
364         if (!g_file_test(path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
365                 _mmcam_dbg_log("File(%s) doesn't exist.", path);
366                 return -2;
367         }
368
369         if (-1 == statfs(path, &fs)) {
370                 _mmcam_dbg_log("Getting free space is failed.(%s)", path);
371                 return -1;
372         }
373
374         *free_space = (guint64)fs.f_bsize * fs.f_bavail;
375         return 1;
376 }
377
378
379 int _mmcamcorder_get_file_system_type(const gchar *path, int *file_system_type)
380 {
381         struct statfs fs;
382
383         g_assert(path);
384
385         if (!g_file_test(path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
386                 _mmcam_dbg_log("File(%s) doesn't exist.", path);
387                 return -2;
388         }
389
390         if (-1 == statfs(path, &fs)) {
391                 _mmcam_dbg_log("statfs failed.(%s)", path);
392                 return -1;
393         }
394
395         *file_system_type = (int)fs.f_type;
396
397         return 0;
398 }
399
400
401 int _mmcamcorder_get_file_size(const char *filename, guint64 *size)
402 {
403         struct stat buf;
404
405         if (stat(filename, &buf) != 0)
406                 return -1;
407         *size = (guint64)buf.st_size;
408         return 1;
409 }
410
411
412 void _mmcamcorder_remove_buffer_probe(MMHandleType handle, _MMCamcorderHandlerCategory category)
413 {
414         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
415         GList *list = NULL;
416         MMCamcorderHandlerItem *item = NULL;
417
418         mmf_return_if_fail(hcamcorder);
419
420         if (!hcamcorder->buffer_probes) {
421                 _mmcam_dbg_warn("list for buffer probe is NULL");
422                 return;
423         }
424
425         _mmcam_dbg_log("start - category : 0x%x", category);
426
427         list = hcamcorder->buffer_probes;
428         while (list) {
429                 item = list->data;
430                 if (!item) {
431                         _mmcam_dbg_err("Remove buffer probe faild, the item is NULL");
432                         list = g_list_next(list);
433                         continue;
434                 }
435
436                 if (item->category & category) {
437                         if (item->object && GST_IS_PAD(item->object)) {
438                                 _mmcam_dbg_log("Remove buffer probe on [%s:%s] - [ID : %lu], [Category : %x]",
439                                                GST_DEBUG_PAD_NAME(item->object), item->handler_id,  item->category);
440                                 gst_pad_remove_probe(GST_PAD(item->object), item->handler_id);
441                         } else {
442                                 _mmcam_dbg_warn("Remove buffer probe faild, the pad is null or not pad, just remove item from list and free it");
443                         }
444
445                         list = g_list_next(list);
446                         hcamcorder->buffer_probes = g_list_remove(hcamcorder->buffer_probes, item);
447                         SAFE_FREE(item);
448                 } else {
449                         _mmcam_dbg_log("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
450                         list = g_list_next(list);
451                 }
452         }
453
454         if (category == _MMCAMCORDER_HANDLER_CATEGORY_ALL) {
455                 g_list_free(hcamcorder->buffer_probes);
456                 hcamcorder->buffer_probes = NULL;
457         }
458
459         _mmcam_dbg_log("done");
460
461         return;
462 }
463
464
465 void _mmcamcorder_remove_one_buffer_probe(MMHandleType handle, void *object)
466 {
467         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
468         GList *list = NULL;
469         MMCamcorderHandlerItem *item = NULL;
470
471         mmf_return_if_fail(hcamcorder);
472
473         if (!hcamcorder->buffer_probes) {
474                 _mmcam_dbg_warn("list for buffer probe is NULL");
475                 return;
476         }
477
478         _mmcam_dbg_log("start - object : %p", object);
479
480         list = hcamcorder->buffer_probes;
481         while (list) {
482                 item = list->data;
483                 if (!item) {
484                         _mmcam_dbg_err("Remove buffer probe faild, the item is NULL");
485                         list = g_list_next(list);
486                         continue;
487                 }
488
489                 if (item->object && item->object == object) {
490                         if (GST_IS_PAD(item->object)) {
491                                 _mmcam_dbg_log("Remove buffer probe on [%s:%s] - [ID : %lu], [Category : %x]",
492                                                GST_DEBUG_PAD_NAME(item->object), item->handler_id,  item->category);
493                                 gst_pad_remove_probe(GST_PAD(item->object), item->handler_id);
494                         } else {
495                                 _mmcam_dbg_warn("Remove buffer probe faild, the pad is null or not pad, just remove item from list and free it");
496                         }
497
498                         list = g_list_next(list);
499                         hcamcorder->buffer_probes = g_list_remove(hcamcorder->buffer_probes, item);
500                         SAFE_FREE(item);
501
502                         break;
503                 } else {
504                         _mmcam_dbg_log("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
505                         list = g_list_next(list);
506                 }
507         }
508
509         _mmcam_dbg_log("done");
510
511         return;
512 }
513
514
515 void _mmcamcorder_remove_event_probe(MMHandleType handle, _MMCamcorderHandlerCategory category)
516 {
517         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
518         GList *list = NULL;
519         MMCamcorderHandlerItem *item = NULL;
520
521         mmf_return_if_fail(hcamcorder);
522
523         if (!hcamcorder->event_probes) {
524                 _mmcam_dbg_warn("list for event probe is NULL");
525                 return;
526         }
527
528         _mmcam_dbg_log("start - category : 0x%x", category);
529
530         list = hcamcorder->event_probes;
531         while (list) {
532                 item = list->data;
533                 if (!item) {
534                         _mmcam_dbg_err("Remove event probe faild, the item is NULL");
535                         list = g_list_next(list);
536                         continue;
537                 }
538
539                 if (item->category & category) {
540                         if (item->object && GST_IS_PAD(item->object)) {
541                                 _mmcam_dbg_log("Remove event probe on [%s:%s] - [ID : %lu], [Category : %x]",
542                                                GST_DEBUG_PAD_NAME(item->object), item->handler_id,  item->category);
543                                 gst_pad_remove_probe(GST_PAD(item->object), item->handler_id);
544                         } else {
545                                 _mmcam_dbg_warn("Remove event probe faild, the pad is null or not pad, just remove item from list and free it");
546                         }
547
548                         list = g_list_next(list);
549                         hcamcorder->event_probes = g_list_remove(hcamcorder->event_probes, item);
550                         SAFE_FREE(item);
551                 } else {
552                         _mmcam_dbg_log("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
553                         list = g_list_next(list);
554                 }
555         }
556
557         if (category == _MMCAMCORDER_HANDLER_CATEGORY_ALL) {
558                 g_list_free(hcamcorder->event_probes);
559                 hcamcorder->event_probes = NULL;
560         }
561
562         _mmcam_dbg_log("done");
563
564         return;
565 }
566
567
568 void _mmcamcorder_disconnect_signal(MMHandleType handle, _MMCamcorderHandlerCategory category)
569 {
570         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
571         GList *list = NULL;
572         MMCamcorderHandlerItem *item = NULL;
573
574         mmf_return_if_fail(hcamcorder);
575
576         if (!hcamcorder->signals) {
577                 _mmcam_dbg_warn("list for signal is NULL");
578                 return;
579         }
580
581         _mmcam_dbg_log("start - category : 0x%x", category);
582
583         list = hcamcorder->signals;
584         while (list) {
585                 item = list->data;
586                 if (!item) {
587                         _mmcam_dbg_err("Fail to Disconnecting signal, the item is NULL");
588                         list = g_list_next(list);
589                         continue;
590                 }
591
592                 if (item->category & category) {
593                         if (item->object && GST_IS_ELEMENT(item->object)) {
594                                 if (g_signal_handler_is_connected(item->object, item->handler_id)) {
595                                         _mmcam_dbg_log("Disconnect signal from [%s] : [ID : %lu], [Category : %x]",
596                                                        GST_OBJECT_NAME(item->object), item->handler_id,  item->category);
597                                         g_signal_handler_disconnect(item->object, item->handler_id);
598                                 } else {
599                                         _mmcam_dbg_warn("Signal was not connected, cannot disconnect it :  [%s]  [ID : %lu], [Category : %x]",
600                                                         GST_OBJECT_NAME(item->object), item->handler_id,  item->category);
601                                 }
602                         } else {
603                                 _mmcam_dbg_err("Fail to Disconnecting signal, the element is null or not element, just remove item from list and free it");
604                         }
605
606                         list = g_list_next(list);
607                         hcamcorder->signals = g_list_remove(hcamcorder->signals, item);
608                         SAFE_FREE(item);
609                 } else {
610                         _mmcam_dbg_log("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
611                         list = g_list_next(list);
612                 }
613         }
614
615         if (category == _MMCAMCORDER_HANDLER_CATEGORY_ALL) {
616                 g_list_free(hcamcorder->signals);
617                 hcamcorder->signals = NULL;
618         }
619
620         _mmcam_dbg_log("done");
621
622         return;
623 }
624
625
626 void _mmcamcorder_remove_all_handlers(MMHandleType handle,  _MMCamcorderHandlerCategory category)
627 {
628         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
629
630         _mmcam_dbg_log("ENTER");
631
632         if(hcamcorder->signals)
633                 _mmcamcorder_disconnect_signal((MMHandleType)hcamcorder, category);
634         if(hcamcorder->event_probes)
635                 _mmcamcorder_remove_event_probe((MMHandleType)hcamcorder, category);
636         if(hcamcorder->buffer_probes)
637                 _mmcamcorder_remove_buffer_probe((MMHandleType)hcamcorder, category);
638
639         _mmcam_dbg_log("LEAVE");
640 }
641
642
643 void _mmcamcorder_element_release_noti(gpointer data, GObject *where_the_object_was)
644 {
645         int i=0;
646         _MMCamcorderSubContext *sc = (_MMCamcorderSubContext *)data;
647
648         mmf_return_if_fail(sc);
649         mmf_return_if_fail(sc->element);
650
651         for (i = 0 ; i < _MMCAMCORDER_PIPELINE_ELEMENT_NUM ; i++) {
652                 if (sc->element[i].gst && (G_OBJECT(sc->element[i].gst) == where_the_object_was)) {
653                         _mmcam_dbg_warn("The element[%d][%p] is finalized",
654                                         sc->element[i].id, sc->element[i].gst);
655                         sc->element[i].gst = NULL;
656                         sc->element[i].id = _MMCAMCORDER_NONE;
657                         return;
658                 }
659         }
660
661         mmf_return_if_fail(sc->encode_element);
662
663         for (i = 0 ; i < _MMCAMCORDER_ENCODE_PIPELINE_ELEMENT_NUM ; i++) {
664                 if (sc->encode_element[i].gst && (G_OBJECT(sc->encode_element[i].gst) == where_the_object_was)) {
665                         _mmcam_dbg_warn("The encode element[%d][%p] is finalized",
666                                         sc->encode_element[i].id, sc->encode_element[i].gst);
667                         sc->encode_element[i].gst = NULL;
668                         sc->encode_element[i].id = _MMCAMCORDER_ENCODE_NONE;
669                         return;
670                 }
671         }
672
673         _mmcam_dbg_warn("there is no matching element %p", where_the_object_was);
674
675         return;
676 }
677
678
679 gboolean
680 _mmcamcroder_msg_callback(void *data)
681 {
682         _MMCamcorderMsgItem *item = (_MMCamcorderMsgItem*)data;
683         mmf_camcorder_t *hcamcorder = NULL;
684         mmf_return_val_if_fail(item, FALSE);
685
686         pthread_mutex_lock(&(item->lock));
687
688         hcamcorder = MMF_CAMCORDER(item->handle);
689         if (hcamcorder == NULL) {
690                 _mmcam_dbg_warn("msg id:%x, item:%p, handle is NULL", item->id, item);
691                 goto MSG_CALLBACK_DONE;
692         }
693
694
695         /*_mmcam_dbg_log("msg id:%x, msg_cb:%p, msg_data:%p, item:%p", item->id, hcamcorder->msg_cb, hcamcorder->msg_data, item);*/
696
697         _MMCAMCORDER_LOCK((MMHandleType)hcamcorder);
698
699         /* remove item from msg data */
700         if (hcamcorder->msg_data) {
701                 hcamcorder->msg_data = g_list_remove(hcamcorder->msg_data, item);
702         } else {
703                 _mmcam_dbg_warn("msg_data is NULL but item[%p] will be removed", item);
704         }
705
706         _MMCAMCORDER_UNLOCK((MMHandleType)hcamcorder);
707
708         _MMCAMCORDER_LOCK_MESSAGE_CALLBACK(hcamcorder);
709
710         if ((hcamcorder) && (hcamcorder->msg_cb)) {
711                 hcamcorder->msg_cb(item->id, (MMMessageParamType*)(&(item->param)), hcamcorder->msg_cb_param);
712         }
713
714         _MMCAMCORDER_UNLOCK_MESSAGE_CALLBACK(hcamcorder);
715
716 MSG_CALLBACK_DONE:
717         /* release allocated memory */
718         if (item->id == MM_MESSAGE_CAMCORDER_FACE_DETECT_INFO) {
719                 MMCamFaceDetectInfo *cam_fd_info = (MMCamFaceDetectInfo *)item->param.data;
720                 if (cam_fd_info) {
721                         SAFE_FREE(cam_fd_info->face_info);
722                         free(cam_fd_info);
723                         cam_fd_info = NULL;
724                 }
725
726                 item->param.data = NULL;
727                 item->param.size = 0;
728         }
729
730         pthread_mutex_unlock(&(item->lock));
731         pthread_mutex_destroy(&(item->lock));
732
733         free(item);
734         item = NULL;
735
736         /* For not being called again */
737         return FALSE;
738 }
739
740
741 gboolean
742 _mmcamcroder_send_message(MMHandleType handle, _MMCamcorderMsgItem *data)
743 {
744         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
745         _MMCamcorderMsgItem *item = NULL;
746
747         mmf_return_val_if_fail(hcamcorder, FALSE);
748         mmf_return_val_if_fail(data, FALSE);
749
750         switch (data->id)
751         {
752                 case MM_MESSAGE_CAMCORDER_STATE_CHANGED:
753                 case MM_MESSAGE_CAMCORDER_STATE_CHANGED_BY_ASM:
754                         data->param.union_type = MM_MSG_UNION_STATE;
755                         break;
756                 case MM_MESSAGE_CAMCORDER_RECORDING_STATUS:
757                         data->param.union_type = MM_MSG_UNION_RECORDING_STATUS;
758                         break;
759                 case MM_MESSAGE_CAMCORDER_FIRMWARE_UPDATE:
760                         data->param.union_type = MM_MSG_UNION_FIRMWARE;
761                         break;
762                 case MM_MESSAGE_CAMCORDER_CURRENT_VOLUME:
763                         data->param.union_type = MM_MSG_UNION_REC_VOLUME_DB;
764                         break;
765                 case MM_MESSAGE_CAMCORDER_TIME_LIMIT:
766                 case MM_MESSAGE_CAMCORDER_MAX_SIZE:
767                 case MM_MESSAGE_CAMCORDER_NO_FREE_SPACE:
768                 case MM_MESSAGE_CAMCORDER_ERROR:
769                 case MM_MESSAGE_CAMCORDER_FOCUS_CHANGED:
770                 case MM_MESSAGE_CAMCORDER_CAPTURED:
771                 case MM_MESSAGE_CAMCORDER_VIDEO_CAPTURED:
772                 case MM_MESSAGE_CAMCORDER_AUDIO_CAPTURED:
773                 case MM_MESSAGE_READY_TO_RESUME:
774                 default:
775                         data->param.union_type = MM_MSG_UNION_CODE;
776                         break;
777         }
778
779         item = g_malloc(sizeof(_MMCamcorderMsgItem));
780         memcpy(item, data, sizeof(_MMCamcorderMsgItem));
781         item->handle = handle;
782         pthread_mutex_init(&(item->lock), NULL);
783
784         _MMCAMCORDER_LOCK(handle);
785         hcamcorder->msg_data = g_list_append(hcamcorder->msg_data, item);
786 //      _mmcam_dbg_log("item[%p]", item);
787
788         /* Use DEFAULT priority */
789         g_idle_add_full(G_PRIORITY_DEFAULT, _mmcamcroder_msg_callback, item, NULL);
790
791         _MMCAMCORDER_UNLOCK(handle);
792
793         return TRUE;
794 }
795
796
797 void
798 _mmcamcroder_remove_message_all(MMHandleType handle)
799 {
800         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
801         _MMCamcorderMsgItem *item = NULL;
802         gboolean ret = TRUE;
803         GList *list = NULL;
804
805         mmf_return_if_fail(hcamcorder);
806
807         _MMCAMCORDER_LOCK(handle);
808
809         if (!hcamcorder->msg_data) {
810                 _mmcam_dbg_log("No message data is remained.");
811         } else {
812                 list = hcamcorder->msg_data;
813
814                 while (list) {
815                         item = list->data;
816                         list = g_list_next(list);
817
818                         if (!item) {
819                                 _mmcam_dbg_err("Fail to remove message. The item is NULL");
820                         } else {
821                                 if (pthread_mutex_trylock(&(item->lock))) {
822                                         ret = g_idle_remove_by_data (item);
823                                         _mmcam_dbg_log("Remove item[%p]. ret[%d]", item, ret);
824
825                                         hcamcorder->msg_data = g_list_remove(hcamcorder->msg_data, item);
826
827                                         if (ret ) {
828                                                 /* release allocated memory */
829                                                 if (item->id == MM_MESSAGE_CAMCORDER_FACE_DETECT_INFO) {
830                                                         MMCamFaceDetectInfo *cam_fd_info = (MMCamFaceDetectInfo *)item->param.data;
831                                                         if (cam_fd_info) {
832                                                                 SAFE_FREE(cam_fd_info->face_info);
833                                                                 free(cam_fd_info);
834                                                                 cam_fd_info = NULL;
835                                                         }
836
837                                                         item->param.data = NULL;
838                                                         item->param.size = 0;
839                                                 }
840
841                                                 pthread_mutex_unlock(&(item->lock));
842                                                 pthread_mutex_destroy(&(item->lock));
843                                                 SAFE_FREE(item);
844                                         } else {
845                                                 item->handle = 0;
846                                                 _mmcam_dbg_warn("Fail to remove item[%p]", item);
847
848                                                 pthread_mutex_unlock(&item->lock);
849                                         }
850                                 } else {
851                                         _mmcam_dbg_warn("item lock failed. it's being called...");
852                                 }
853                         }
854                 }
855
856                 g_list_free(hcamcorder->msg_data);
857                 hcamcorder->msg_data = NULL;
858         }
859
860         /* remove idle function for playing capture sound */
861         do {
862                 ret = g_idle_remove_by_data(hcamcorder);
863                 _mmcam_dbg_log("remove idle function for playing capture sound. ret[%d]", ret);
864         } while (ret);
865
866         _MMCAMCORDER_UNLOCK(handle);
867
868         return;
869 }
870
871
872 int _mmcamcorder_get_pixel_format(GstCaps *caps)
873 {
874         const GstStructure *structure;
875         const char *media_type;
876         GstVideoInfo media_info;
877         MMPixelFormatType type = 0;
878         unsigned int fourcc = 0;
879
880         mmf_return_val_if_fail( caps != NULL, MM_PIXEL_FORMAT_INVALID );
881
882         structure = gst_caps_get_structure (caps, 0);
883         media_type = gst_structure_get_name (structure);
884
885         if (!strcmp (media_type, "image/jpeg") ) {
886                 _mmcam_dbg_log("It is jpeg.");
887                 type = MM_PIXEL_FORMAT_ENCODED;
888         } else if (!strcmp (media_type, "video/x-raw") &&
889                    gst_video_info_from_caps(&media_info, caps) &&
890                    GST_VIDEO_INFO_IS_YUV(&media_info)) {
891                 _mmcam_dbg_log("It is yuv.");
892                 fourcc = gst_video_format_to_fourcc(GST_VIDEO_INFO_FORMAT(&media_info));
893                 type = _mmcamcorder_get_pixtype(fourcc);
894         } else if (!strcmp (media_type, "video/x-raw") &&
895                    GST_VIDEO_INFO_IS_RGB(&media_info)) {
896                 _mmcam_dbg_log("It is rgb.");
897                 type = MM_PIXEL_FORMAT_RGB888;
898         } else if (!strcmp (media_type, "video/x-h264")) {
899                 _mmcam_dbg_log("It is H264");
900                 type = MM_PIXEL_FORMAT_ENCODED_H264;
901         } else {
902                 _mmcam_dbg_err("Not supported format");
903                 type = MM_PIXEL_FORMAT_INVALID;
904         }
905
906         /*_mmcam_dbg_log( "Type [%d]", type );*/
907
908         return type;
909 }
910
911 unsigned int _mmcamcorder_get_fourcc(int pixtype, int codectype, int use_zero_copy_format)
912 {
913         unsigned int fourcc = 0;
914
915         _mmcam_dbg_log("pixtype(%d)", pixtype);
916
917         switch (pixtype) {
918         case MM_PIXEL_FORMAT_NV12:
919                 if (use_zero_copy_format) {
920                         fourcc = GST_MAKE_FOURCC ('S', 'N', '1', '2');
921                 } else {
922                         fourcc = GST_MAKE_FOURCC ('N', 'V', '1', '2');
923                 }
924                 break;
925         case MM_PIXEL_FORMAT_NV21:
926                 if (use_zero_copy_format) {
927                         fourcc = GST_MAKE_FOURCC ('S', 'N', '2', '1');
928                 } else {
929                         fourcc = GST_MAKE_FOURCC ('N', 'V', '2', '1');
930                 }
931                 break;
932         case MM_PIXEL_FORMAT_YUYV:
933                 if (use_zero_copy_format) {
934                         fourcc = GST_MAKE_FOURCC ('S', 'U', 'Y', 'V');
935                 } else {
936                         fourcc = GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
937                 }
938                 break;
939         case MM_PIXEL_FORMAT_UYVY:
940                 if (use_zero_copy_format) {
941                         fourcc = GST_MAKE_FOURCC ('S', 'Y', 'V', 'Y');
942                 } else {
943                         fourcc = GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
944                 }
945                 break;
946         case MM_PIXEL_FORMAT_I420:
947                 if (use_zero_copy_format) {
948                         fourcc = GST_MAKE_FOURCC ('S', '4', '2', '0');
949                 } else {
950                         fourcc = GST_MAKE_FOURCC ('I', '4', '2', '0');
951                 }
952                 break;
953         case MM_PIXEL_FORMAT_YV12:
954                 fourcc = GST_MAKE_FOURCC ('Y', 'V', '1', '2');
955                 break;
956         case MM_PIXEL_FORMAT_422P:
957                 fourcc = GST_MAKE_FOURCC ('4', '2', '2', 'P');
958                 break;
959         case MM_PIXEL_FORMAT_RGB565:
960                 fourcc = GST_MAKE_FOURCC ('R', 'G', 'B', 'P');
961                 break;
962         case MM_PIXEL_FORMAT_RGB888:
963                 fourcc = GST_MAKE_FOURCC ('R', 'G', 'B', ' ');
964                 break;
965         case MM_PIXEL_FORMAT_ENCODED:
966                 if (codectype == MM_IMAGE_CODEC_JPEG) {
967                         fourcc = GST_MAKE_FOURCC ('J', 'P', 'E', 'G');
968                 } else if (codectype == MM_IMAGE_CODEC_JPEG_SRW) {
969                         fourcc = GST_MAKE_FOURCC ('J', 'P', 'E', 'G'); /*TODO: JPEG+SamsungRAW format */
970                 } else if (codectype == MM_IMAGE_CODEC_SRW) {
971                         fourcc = GST_MAKE_FOURCC ('J', 'P', 'E', 'G'); /*TODO: SamsungRAW format */
972                 } else if (codectype == MM_IMAGE_CODEC_PNG) {
973                         fourcc = GST_MAKE_FOURCC ('P', 'N', 'G', ' ');
974                 } else {
975                         /* Please let us know what other fourcces are. ex) BMP, GIF?*/
976                         fourcc = GST_MAKE_FOURCC ('J', 'P', 'E', 'G');
977                 }
978                 break;
979         case MM_PIXEL_FORMAT_ITLV_JPEG_UYVY:
980                 fourcc = GST_MAKE_FOURCC('I','T','L','V');
981                 break;
982         case MM_PIXEL_FORMAT_ENCODED_H264:
983                 fourcc = GST_MAKE_FOURCC('H','2','6','4');
984                 break;
985         default:
986                 _mmcam_dbg_log("Not proper pixel type[%d]. Set default - I420", pixtype);
987                 if (use_zero_copy_format) {
988                         fourcc = GST_MAKE_FOURCC ('S', '4', '2', '0');
989                 } else {
990                         fourcc = GST_MAKE_FOURCC ('I', '4', '2', '0');
991                 }
992                 break;
993         }
994
995         return fourcc;
996 }
997
998
999 int _mmcamcorder_get_pixtype(unsigned int fourcc)
1000 {
1001         int pixtype = MM_PIXEL_FORMAT_INVALID;
1002         char *pfourcc = (char*)&fourcc;
1003         _mmcam_dbg_log("fourcc(%c%c%c%c)", pfourcc[0], pfourcc[1], pfourcc[2], pfourcc[3]);
1004
1005         switch (fourcc) {
1006         case GST_MAKE_FOURCC ('S', 'N', '1', '2'):
1007         case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
1008                 pixtype = MM_PIXEL_FORMAT_NV12;
1009                 break;
1010         case GST_MAKE_FOURCC ('S', 'N', '2', '1'):
1011         case GST_MAKE_FOURCC ('N', 'V', '2', '1'):
1012                 pixtype = MM_PIXEL_FORMAT_NV21;
1013                 break;
1014         case GST_MAKE_FOURCC ('S', 'U', 'Y', 'V'):
1015         case GST_MAKE_FOURCC ('Y', 'U', 'Y', 'V'):
1016         case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
1017                 pixtype = MM_PIXEL_FORMAT_YUYV;
1018                 break;
1019         case GST_MAKE_FOURCC ('S', 'Y', 'V', 'Y'):
1020         case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
1021                 pixtype = MM_PIXEL_FORMAT_UYVY;
1022                 break;
1023         case GST_MAKE_FOURCC ('S', '4', '2', '0'):
1024         case GST_MAKE_FOURCC ('I', '4', '2', '0'):
1025                 pixtype = MM_PIXEL_FORMAT_I420;
1026                 break;
1027         case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
1028                 pixtype = MM_PIXEL_FORMAT_YV12;
1029                 break;
1030         case GST_MAKE_FOURCC ('4', '2', '2', 'P'):
1031                 pixtype = MM_PIXEL_FORMAT_422P;
1032                 break;
1033         case GST_MAKE_FOURCC ('R', 'G', 'B', 'P'):
1034                 pixtype = MM_PIXEL_FORMAT_RGB565;
1035                 break;
1036         case GST_MAKE_FOURCC ('R', 'G', 'B', '3'):
1037                 pixtype = MM_PIXEL_FORMAT_RGB888;
1038                 break;
1039         case GST_MAKE_FOURCC ('A', 'R', 'G', 'B'):
1040         case GST_MAKE_FOURCC ('x', 'R', 'G', 'B'):
1041                 pixtype = MM_PIXEL_FORMAT_ARGB;
1042                 break;
1043         case GST_MAKE_FOURCC ('B', 'G', 'R', 'A'):
1044         case GST_MAKE_FOURCC ('B', 'G', 'R', 'x'):
1045         case GST_MAKE_FOURCC ('S', 'R', '3', '2'):
1046                 pixtype = MM_PIXEL_FORMAT_RGBA;
1047                 break;
1048         case GST_MAKE_FOURCC ('J', 'P', 'E', 'G'):
1049         case GST_MAKE_FOURCC ('P', 'N', 'G', ' '):
1050                 pixtype = MM_PIXEL_FORMAT_ENCODED;
1051                 break;
1052         /*FIXME*/
1053         case GST_MAKE_FOURCC ('I', 'T', 'L', 'V'):
1054                 pixtype = MM_PIXEL_FORMAT_ITLV_JPEG_UYVY;
1055                 break;
1056         case GST_MAKE_FOURCC ('H', '2', '6', '4'):
1057                 pixtype = MM_PIXEL_FORMAT_ENCODED_H264;
1058                 break;
1059         default:
1060                 _mmcam_dbg_log("Not supported fourcc type(%c%c%c%c)",
1061                                fourcc, fourcc>>8, fourcc>>16, fourcc>>24);
1062                 pixtype = MM_PIXEL_FORMAT_INVALID;
1063                 break;
1064         }
1065
1066         return pixtype;
1067 }
1068
1069
1070 gboolean _mmcamcorder_add_elements_to_bin(GstBin *bin, GList *element_list)
1071 {
1072         GList *local_list = element_list;
1073         _MMCamcorderGstElement *element = NULL;
1074
1075         mmf_return_val_if_fail(bin && local_list, FALSE);
1076
1077         while (local_list) {
1078                 element = (_MMCamcorderGstElement*)local_list->data;
1079                 if (element && element->gst) {
1080                         if (!gst_bin_add(bin, GST_ELEMENT(element->gst))) {
1081                                 _mmcam_dbg_err( "Add element [%s] to bin [%s] FAILED",
1082                                                 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
1083                                                 GST_ELEMENT_NAME(GST_ELEMENT(bin)) );
1084                                 return FALSE;
1085                         } else {
1086                                 _mmcam_dbg_log("Add element [%s] to bin [%s] OK",
1087                                                GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
1088                                                GST_ELEMENT_NAME(GST_ELEMENT(bin)));
1089                         }
1090                 }
1091                 local_list = local_list->next;
1092         }
1093
1094         return TRUE;
1095 }
1096
1097 gboolean _mmcamcorder_link_elements(GList *element_list)
1098 {
1099         GList                  *local_list  = element_list;
1100         _MMCamcorderGstElement *element     = NULL;
1101         _MMCamcorderGstElement *pre_element = NULL;
1102
1103         mmf_return_val_if_fail(local_list, FALSE);
1104
1105         pre_element = (_MMCamcorderGstElement*)local_list->data;
1106         local_list = local_list->next;
1107
1108         while (local_list) {
1109                 element = (_MMCamcorderGstElement*)local_list->data;
1110                 if (element && element->gst) {
1111                         if (_MM_GST_ELEMENT_LINK(GST_ELEMENT(pre_element->gst), GST_ELEMENT(element->gst))) {
1112                                 _mmcam_dbg_log("Link [%s] to [%s] OK",
1113                                                GST_ELEMENT_NAME(GST_ELEMENT(pre_element->gst)),
1114                                                GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
1115                         } else {
1116                                 _mmcam_dbg_err("Link [%s] to [%s] FAILED",
1117                                                GST_ELEMENT_NAME(GST_ELEMENT(pre_element->gst)),
1118                                                GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
1119                                 return FALSE;
1120                         }
1121                 }
1122
1123                 pre_element = element;
1124                 local_list = local_list->next;
1125         }
1126
1127         return TRUE;
1128 }
1129
1130
1131 gboolean _mmcamcorder_resize_frame(unsigned char *src_data, unsigned int src_width, unsigned int src_height, unsigned int src_length, int src_format,
1132                                    unsigned char **dst_data, unsigned int *dst_width, unsigned int *dst_height, unsigned int *dst_length)
1133 {
1134         int ret = TRUE;
1135         int mm_ret = MM_ERROR_NONE;
1136         int input_format = MM_UTIL_IMG_FMT_YUV420;
1137         unsigned char *dst_tmp_data = NULL;
1138
1139         if (!src_data || !dst_data || !dst_width || !dst_height || !dst_length) {
1140                 _mmcam_dbg_err("something is NULL %p,%p,%p,%p,%p",
1141                                src_data, dst_data, dst_width, dst_height, dst_length);
1142                 return FALSE;
1143         }
1144
1145         /* set input format for mm-util */
1146         switch (src_format) {
1147         case MM_PIXEL_FORMAT_I420:
1148                 input_format = MM_UTIL_IMG_FMT_I420;
1149                 break;
1150         case MM_PIXEL_FORMAT_YV12:
1151                 input_format = MM_UTIL_IMG_FMT_YUV420;
1152                 break;
1153         case MM_PIXEL_FORMAT_NV12:
1154                 input_format = MM_UTIL_IMG_FMT_NV12;
1155                 break;
1156         case MM_PIXEL_FORMAT_YUYV:
1157                 input_format = MM_UTIL_IMG_FMT_YUYV;
1158                 break;
1159         case MM_PIXEL_FORMAT_UYVY:
1160                 input_format = MM_UTIL_IMG_FMT_UYVY;
1161                 break;
1162         case MM_PIXEL_FORMAT_RGB888:
1163                 input_format = MM_UTIL_IMG_FMT_RGB888;
1164                 break;
1165         default:
1166                 _mmcam_dbg_err("NOT supported format", src_format);
1167                 return FALSE;
1168         }
1169
1170         _mmcam_dbg_log("src size %dx%d -> dst size %dx%d",
1171                         src_width, src_height, *dst_width, *dst_height);
1172
1173         /* get length of resized image */
1174         mm_ret = mm_util_get_image_size(input_format, *dst_width, *dst_height, dst_length);
1175         if (mm_ret != MM_ERROR_NONE) {
1176                 GST_ERROR("mm_util_get_image_size failed 0x%x", ret);
1177                 return FALSE;
1178         }
1179
1180         _mmcam_dbg_log("dst_length : %d", *dst_length);
1181
1182         dst_tmp_data = (unsigned char *)malloc(*dst_length);
1183         if (dst_tmp_data == NULL) {
1184                 _mmcam_dbg_err("failed to alloc dst_thumb_size(size %d)", *dst_length);
1185                 return FALSE;
1186         }
1187
1188         mm_ret = mm_util_resize_image(src_data, src_width, src_height, input_format,
1189                                       dst_tmp_data, dst_width, dst_height);
1190         if (mm_ret != MM_ERROR_NONE) {
1191                 GST_ERROR("mm_util_resize_image failed 0x%x", ret);
1192                 free(dst_tmp_data);
1193                 return FALSE;
1194         }
1195
1196         *dst_data = dst_tmp_data;
1197
1198         _mmcam_dbg_log("resize done %p, %dx%d", *dst_data, *dst_width, *dst_height);
1199
1200         return TRUE;
1201 }
1202
1203
1204 gboolean _mmcamcorder_encode_jpeg(void *src_data, unsigned int src_width, unsigned int src_height,
1205                                   int src_format, unsigned int src_length, unsigned int jpeg_quality,
1206                                   void **result_data, unsigned int *result_length, int enc_type)
1207 {
1208         int ret = 0;
1209         int i = 0;
1210         guint32 src_fourcc = 0;
1211         gboolean do_encode = FALSE;
1212         jpegenc_parameter enc_param;
1213         jpegenc_info enc_info;
1214
1215         _mmcam_dbg_log("START - enc_type [%d]", enc_type);
1216
1217         mmf_return_val_if_fail(src_data && result_data && result_length, FALSE);
1218
1219         CLEAR(enc_param);
1220         CLEAR(enc_info);
1221
1222         camsrcjpegenc_get_info(&enc_info);
1223
1224         src_fourcc = _mmcamcorder_get_fourcc(src_format, 0, FALSE);
1225         camsrcjpegenc_get_src_fmt(src_fourcc, &(enc_param.src_fmt));
1226
1227         if (enc_param.src_fmt == COLOR_FORMAT_NOT_SUPPORT) {
1228                 _mmcam_dbg_err("Not Supported FOURCC(format:%d)", src_format);
1229                 return FALSE;
1230         }
1231
1232         /* check H/W encoder */
1233         if (enc_info.hw_support && enc_type == JPEG_ENCODER_HARDWARE) {
1234                 _mmcam_dbg_log("check H/W encoder supported format list");
1235                 /* Check supported format */
1236                 for (i = 0 ; i < enc_info.hw_enc.input_fmt_num ; i++) {
1237                         if (enc_param.src_fmt == enc_info.hw_enc.input_fmt_list[i]) {
1238                                 do_encode = TRUE;
1239                                 break;
1240                         }
1241                 }
1242
1243                 if (do_encode) {
1244                         enc_type = JPEG_ENCODER_HARDWARE;
1245                 }
1246         }
1247
1248         /* check S/W encoder */
1249         if (!do_encode && enc_info.sw_support) {
1250                 _mmcam_dbg_log("check S/W encoder supported format list");
1251                 /* Check supported format */
1252                 for (i = 0 ; i < enc_info.sw_enc.input_fmt_num ; i++) {
1253                         if (enc_param.src_fmt == enc_info.sw_enc.input_fmt_list[i]) {
1254                                 do_encode = TRUE;
1255                                 break;
1256                         }
1257                 }
1258
1259                 if (do_encode) {
1260                         enc_type = JPEG_ENCODER_SOFTWARE;
1261                 }
1262         }
1263
1264         if (do_encode) {
1265                 enc_param.src_data = src_data;
1266                 enc_param.width = src_width;
1267                 enc_param.height = src_height;
1268                 enc_param.src_len = src_length;
1269                 enc_param.jpeg_mode = JPEG_MODE_BASELINE;
1270                 enc_param.jpeg_quality = jpeg_quality;
1271
1272                 _mmcam_dbg_log("%ux%u, size %u, quality %u, type %d",
1273                                src_width, src_height, src_length,
1274                                jpeg_quality, enc_type);
1275
1276                 ret = camsrcjpegenc_encode(&enc_info, enc_type, &enc_param );
1277                 if (ret == CAMSRC_JPEGENC_ERROR_NONE) {
1278                         *result_data = enc_param.result_data;
1279                         *result_length = enc_param.result_len;
1280
1281                         _mmcam_dbg_log("JPEG encode length(%d)", *result_length);
1282
1283                         return TRUE;
1284                 } else {
1285                         _mmcam_dbg_err("camsrcjpegenc_encode failed(%x)", ret);
1286                         return FALSE;
1287                 }
1288         }
1289
1290         _mmcam_dbg_err("No encoder supports %d format", src_format);
1291
1292         return FALSE;
1293 }
1294
1295
1296 /* make UYVY smaller as multiple size. ex: 640x480 -> 320x240 or 160x120 ... */
1297 gboolean _mmcamcorder_downscale_UYVYorYUYV(unsigned char *src, unsigned int src_width, unsigned int src_height,
1298                                            unsigned char **dst, unsigned int dst_width, unsigned int dst_height)
1299 {
1300         unsigned int i = 0;
1301         int j = 0;
1302         int k = 0;
1303         int src_index = 0;
1304         int ratio_width = 0;
1305         int ratio_height = 0;
1306         int line_base = 0;
1307         int line_width = 0;
1308         int jump_width = 0;
1309         unsigned char *result = NULL;
1310
1311         if (src == NULL || dst == NULL) {
1312                 _mmcam_dbg_err("src[%p] or dst[%p] is NULL", src, dst);
1313                 return FALSE;
1314         }
1315
1316         result = (unsigned char *)malloc((dst_width * dst_height)<<1);
1317         if (!result) {
1318                 _mmcam_dbg_err("failed to alloc dst data");
1319                 return FALSE;
1320         }
1321
1322         ratio_width = src_width / dst_width;
1323         ratio_height = src_height / dst_height;
1324         line_width = src_width << 1;
1325         jump_width = ratio_width << 1;
1326
1327         _mmcam_dbg_warn("[src %dx%d] [dst %dx%d] [line width %d] [ratio width %d, height %d]",
1328                         src_width, src_height, dst_width, dst_height,
1329                         line_width, ratio_width, ratio_height);
1330
1331         for (i = 0 ; i < src_height ; i += ratio_height) {
1332                 line_base = i * line_width;
1333                 for (j = 0 ; j < line_width ; j += jump_width) {
1334                         src_index = line_base + j;
1335                         result[k++] = src[src_index];
1336                         result[k++] = src[src_index+1];
1337
1338                         j += jump_width;
1339                         src_index = line_base + j;
1340                         if (src_index % 4 == 0) {
1341                                 result[k++] = src[src_index+2];
1342                         } else {
1343                                 result[k++] = src[src_index];
1344                         }
1345                         result[k++] = src[src_index+1];
1346                 }
1347         }
1348
1349         *dst = result;
1350
1351         _mmcam_dbg_warn("converting done - result %p", result);
1352
1353         return TRUE;
1354 }
1355
1356 gboolean _mmcamcorder_check_file_path(const gchar *path)
1357 {
1358         if(strstr(path, "/opt/usr") != NULL) {
1359                 return TRUE;
1360         }
1361         return FALSE;
1362 }
1363
1364 static guint16 get_language_code(const char *str)
1365 {
1366     return (guint16) (((str[0]-0x60) & 0x1F) << 10) + (((str[1]-0x60) & 0x1F) << 5) + ((str[2]-0x60) & 0x1F);
1367 }
1368
1369 static gchar * str_to_utf8(const gchar *str)
1370 {
1371         return g_convert (str, -1, "UTF-8", "ASCII", NULL, NULL, NULL);
1372 }
1373
1374 static inline gboolean write_tag(FILE *f, const gchar *tag)
1375 {
1376         while(*tag)
1377                 FPUTC_CHECK(*tag++, f);
1378
1379         return TRUE;
1380 }
1381
1382 static inline gboolean write_to_32(FILE *f, guint val)
1383 {
1384         FPUTC_CHECK(val >> 24, f);
1385         FPUTC_CHECK(val >> 16, f);
1386         FPUTC_CHECK(val >> 8, f);
1387         FPUTC_CHECK(val, f);
1388         return TRUE;
1389 }
1390
1391 static inline gboolean write_to_16(FILE *f, guint val)
1392 {
1393         FPUTC_CHECK(val >> 8, f);
1394         FPUTC_CHECK(val, f);
1395         return TRUE;
1396 }
1397
1398 static inline gboolean write_to_24(FILE *f, guint val)
1399 {
1400         write_to_16(f, val >> 8);
1401         FPUTC_CHECK(val, f);
1402         return TRUE;
1403 }
1404
1405 void *_mmcamcorder_util_task_thread_func(void *data)
1406 {
1407         int ret = MM_ERROR_NONE;
1408         mmf_camcorder_t *hcamcorder = (mmf_camcorder_t *)data;
1409
1410         if (!hcamcorder) {
1411                 _mmcam_dbg_err("handle is NULL");
1412                 return NULL;
1413         }
1414
1415         _mmcam_dbg_warn("start thread");
1416
1417         pthread_mutex_lock(&(hcamcorder->task_thread_lock));
1418
1419         while (hcamcorder->task_thread_state != _MMCAMCORDER_TASK_THREAD_STATE_EXIT) {
1420                 switch (hcamcorder->task_thread_state) {
1421                 case _MMCAMCORDER_TASK_THREAD_STATE_NONE:
1422                         _mmcam_dbg_warn("wait for task signal");
1423                         pthread_cond_wait(&(hcamcorder->task_thread_cond), &(hcamcorder->task_thread_lock));
1424                         _mmcam_dbg_warn("task signal received : state %d", hcamcorder->task_thread_state);
1425                         break;
1426                 case _MMCAMCORDER_TASK_THREAD_STATE_SOUND_PLAY_START:
1427                         _mmcamcorder_sound_play((MMHandleType)hcamcorder, _MMCAMCORDER_SAMPLE_SOUND_NAME_CAPTURE, FALSE);
1428                         hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_NONE;
1429                         break;
1430                 case _MMCAMCORDER_TASK_THREAD_STATE_ENCODE_PIPE_CREATE:
1431                         ret = _mmcamcorder_video_prepare_record((MMHandleType)hcamcorder);
1432
1433                         /* Play record start sound */
1434                         _mmcamcorder_sound_solo_play((MMHandleType)hcamcorder, _MMCAMCORDER_FILEPATH_REC_START_SND, FALSE);
1435
1436                         _mmcam_dbg_log("_mmcamcorder_video_prepare_record return 0x%x", ret);
1437                         hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_NONE;
1438                         break;
1439                 default:
1440                         _mmcam_dbg_warn("invalid task thread state %d", hcamcorder->task_thread_state);
1441                         hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_EXIT;
1442                         break;
1443                 }
1444         }
1445
1446         pthread_mutex_unlock(&(hcamcorder->task_thread_lock));
1447
1448         _mmcam_dbg_warn("exit thread");
1449
1450         return NULL;
1451 }