tizen beta release
[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 |                                                                                                                                                                                       |
24 |  INCLUDE FILES                                                                                                                                                        |
25 |                                                                                                                                                                                       |
26 ========================================================================================== */
27 #include <stdio.h>
28 #include <stdarg.h>
29 #include <camsrcjpegenc.h>
30 #include <sys/vfs.h> /* struct statfs */
31
32 #include "mm_camcorder_internal.h"
33 #include "mm_camcorder_util.h"
34
35 /*---------------------------------------------------------------------------
36 |    GLOBAL VARIABLE DEFINITIONS for internal                                                           |
37 ---------------------------------------------------------------------------*/
38
39 /*---------------------------------------------------------------------------
40 |    LOCAL VARIABLE DEFINITIONS for internal                                                            |
41 ---------------------------------------------------------------------------*/
42 #define TIME_STRING_MAX_LEN   64
43 #define FPUTC_CHECK(x_char, x_file)\
44 {\
45         if (fputc(x_char, x_file) == EOF) \
46         {\
47                 _mmcam_dbg_err("[Critical] fputc() returns fail.\n");   \
48                 return FALSE;\
49         }\
50 }
51 #define FPUTS_CHECK(x_str, x_file)\
52 {\
53         if (fputs(x_str, x_file) == EOF) \
54         {\
55                 _mmcam_dbg_err("[Critical] fputs() returns fail.\n");\
56                 SAFE_FREE(str); \
57                 return FALSE;\
58         }\
59 }
60
61 /*---------------------------------------------------------------------------
62 |    LOCAL FUNCTION PROTOTYPES:                                                                                         |
63 ---------------------------------------------------------------------------*/
64 /* STATIC INTERNAL FUNCTION */
65         
66 //static gint           skip_mdat(FILE *f);
67 static guint16           get_language_code(const char *str);
68 static gchar*            str_to_utf8(const gchar *str);
69 static inline gboolean   write_tag(FILE *f, const gchar *tag);
70 static inline gboolean   write_to_32(FILE *f, guint val);
71 static inline gboolean   write_to_16(FILE *f, guint val);
72 static inline gboolean   write_to_24(FILE *f, guint val);
73
74 /*===========================================================================================
75 |                                                                                                                                                                                       |
76 |  FUNCTION DEFINITIONS                                                                                                                                         |
77 |                                                                                                                                                                                       |
78 ========================================================================================== */
79 /*---------------------------------------------------------------------------
80 |    GLOBAL FUNCTION DEFINITIONS:                                                                                       |
81 ---------------------------------------------------------------------------*/
82
83 gint32 _mmcamcorder_double_to_fix(gdouble d_number)
84 {
85         return (gint32) (d_number * 65536.0);
86 }
87
88 // find top level tag only, do not use this function for finding sub level tags
89 gint _mmcamcorder_find_tag(FILE *f, guint32 tag_fourcc)
90 {
91         guchar buf[8];
92
93         rewind(f);
94
95         while(fread(&buf, sizeof(guchar), 8, f)>0)
96         {
97                 gulong buf_size = 0;
98                 guint32 buf_fourcc = MMCAM_FOURCC(buf[4], buf[5],buf[6],buf[7]);
99
100                 if(tag_fourcc == buf_fourcc)
101                 {
102                         _mmcam_dbg_log("find tag : %c%c%c%c", MMCAM_FOURCC_ARGS(tag_fourcc));
103                         return 1;
104                 }
105                 else
106                 {
107                         _mmcam_dbg_log("skip [%c%c%c%c]  tag", MMCAM_FOURCC_ARGS(buf_fourcc));          
108                         buf_size = _mmcamcorder_get_container_size(buf);
109                         if(fseek(f, buf_size-8, SEEK_CUR) != 0)
110                         {
111                                 _mmcam_dbg_err("fseek() fail");
112                                 return 0;
113                         }               
114                 }
115         }
116         _mmcam_dbg_log("cannot find tag : %c%c%c%c", MMCAM_FOURCC_ARGS(tag_fourcc));
117         return 0;
118 }
119
120 gboolean _mmcamcorder_update_size(FILE *f, gint64 prev_pos, gint64 curr_pos)
121 {
122         _mmcam_dbg_log("size : %"G_GINT64_FORMAT"", curr_pos-prev_pos);
123         if(fseek(f, prev_pos, SEEK_SET) != 0)
124         {
125                 _mmcam_dbg_err("fseek() fail");
126                 return FALSE;
127         }
128
129         if (!write_to_32(f, curr_pos -prev_pos))
130                 return FALSE;
131         
132         if(fseek(f, curr_pos, SEEK_SET) != 0)
133         {
134                 _mmcam_dbg_err("fseek() fail");
135                 return FALSE;
136         }
137         
138         return TRUE;
139 }
140
141 gboolean _mmcamcorder_write_loci(FILE *f, _MMCamcorderLocationInfo info)
142 {
143         gint64 current_pos, pos;
144         gchar *str = NULL;
145
146         _mmcam_dbg_log("");
147
148         if((pos = ftell(f))<0)
149         {
150                 _mmcam_dbg_err("ftell() returns negative value");       
151                 return FALSE;
152         }
153         
154         if(!write_to_32(f, 0)) //size
155                 return FALSE;
156         
157         if(!write_tag(f, "loci"))       // type
158                 return FALSE;
159         
160         FPUTC_CHECK(0, f);              // version
161
162         if(!write_to_24(f, 0))  // flags
163                 return FALSE;
164         
165         if(!write_to_16(f, get_language_code("eng"))) // language
166                 return FALSE;
167         
168         str = str_to_utf8("location_name");
169         
170         FPUTS_CHECK(str, f); // name
171         SAFE_FREE(str);
172         
173         FPUTC_CHECK('\0', f);
174         FPUTC_CHECK(0, f);              //role
175         
176         if(!write_to_32(f, info.longitude))     // Longitude
177                 return FALSE;
178         
179         if(!write_to_32(f, info.latitude)) // Latitude
180                 return FALSE;
181         
182         if(! write_to_32(f, info.altitude))     // Altitude
183                 return FALSE;
184         
185         str = str_to_utf8("Astronomical_body");
186         FPUTS_CHECK(str, f);//Astronomical_body
187         SAFE_FREE(str);
188         
189         FPUTC_CHECK('\0', f);
190         
191         str = str_to_utf8("Additional_notes");
192         FPUTS_CHECK(str, f); // Additional_notes
193         SAFE_FREE(str);
194         
195         FPUTC_CHECK('\0', f);
196         
197         if((current_pos = ftell(f))<0)
198         {
199                 _mmcam_dbg_err("ftell() returns negative value");       
200                 return FALSE;
201         }
202         
203         if(! _mmcamcorder_update_size(f, pos, current_pos))
204                 return FALSE;
205
206         return TRUE;
207 }
208
209 gboolean _mmcamcorder_write_udta(FILE *f, _MMCamcorderLocationInfo info)
210 {
211         gint64 current_pos, pos;
212
213         _mmcam_dbg_log("");
214  
215         if((pos = ftell(f))<0)
216         {
217                 _mmcam_dbg_err("ftell() returns negative value");       
218                 return FALSE;
219         }
220         
221         if(!write_to_32(f, 0))  //size 
222                 return FALSE;
223         
224         if(!write_tag(f, "udta"))       // type 
225                 return FALSE;
226         
227         if(! _mmcamcorder_write_loci(f, info))
228                 return FALSE;
229         
230         if((current_pos = ftell(f))<0)
231         {
232                 _mmcam_dbg_err("ftell() returns negative value");
233                 return FALSE;
234         }
235  
236         if(! _mmcamcorder_update_size(f, pos, current_pos))
237                 return FALSE;
238  
239
240         return TRUE;
241 }
242
243
244 gulong _mmcamcorder_get_container_size(const guchar *size)
245 {
246         gulong result = 0;
247         gulong temp = 0;
248         temp = size[0];
249         result = temp << 24;
250         temp = size[1];
251         result = result | (temp << 16);
252         temp = size[2];
253         result = result | (temp << 8);
254         result = result | size[3];      
255         return result;
256 }
257
258
259 int _mmcamcorder_get_freespace(const gchar *path, guint64 *free_space)
260 {
261         struct statfs fs;
262
263         g_assert(path);
264
265         if (!g_file_test(path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
266                 _mmcam_dbg_log("File(%s) doesn't exist.", path);
267                 return -2;
268         }
269
270         if (-1 == statfs(path, &fs)) {
271                 _mmcam_dbg_log("Getting free space is failed.(%s)", path);
272                 return -1;
273         }
274
275         *free_space = (guint64)fs.f_bsize * fs.f_bavail;
276         return 1;
277 }
278
279
280 int _mmcamcorder_get_file_size(const char *filename, guint64 *size)
281 {
282         struct stat buf;
283
284         if (stat(filename, &buf) != 0)
285                 return -1;
286         *size = (guint64)buf.st_size;
287         return 1;
288 }
289
290
291 void _mmcamcorder_remove_buffer_probe(MMHandleType handle, _MMCamcorderHandlerCategory category)
292 {
293         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
294         GList *list = NULL;
295         MMCamcorderHandlerItem *item = NULL;
296
297         mmf_return_if_fail(hcamcorder);
298
299         if(!hcamcorder->buffer_probes)
300         {
301                 _mmcam_dbg_err("Fail to remove buffer probe, list for buffer probe is NULL");
302         }
303
304         list = hcamcorder->buffer_probes;
305
306         while(list)
307         {       
308                 item = list->data;
309
310                 if(!item)
311                 {
312                         _mmcam_dbg_err("Remove buffer probe faild, the item is NULL");
313                         list =  g_list_next(list);
314                         continue;                       
315                 }
316
317                 if(item->category & category)
318                 {
319                 
320                         if(item->object && GST_IS_PAD(item->object))
321                         {
322                                 _mmcam_dbg_log("Remove buffer probe on [%s:%s] - [ID : %lu], [Category : %x]", 
323                                                 GST_DEBUG_PAD_NAME(item->object), item->handler_id,  item->category);
324                                 gst_pad_remove_buffer_probe(GST_PAD(item->object), item->handler_id);
325                         }
326                         else
327                         {
328                                 _mmcam_dbg_warn("Remove buffer probe faild, the pad is null or not pad, just remove item from list and free it");
329                         }                       
330                         
331                         list =  g_list_next(list);
332                         hcamcorder->buffer_probes = g_list_remove(hcamcorder->buffer_probes, item);
333                         SAFE_FREE(item);
334                 }
335                 else
336                 {
337                         _mmcam_dbg_log("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
338                         list =  g_list_next(list);
339                 }
340         }
341
342         if( category == _MMCAMCORDER_HANDLER_CATEGORY_ALL)
343         {
344                 g_list_free(hcamcorder->buffer_probes);
345                 hcamcorder->buffer_probes = NULL;
346         }
347 }
348
349 void _mmcamcorder_remove_event_probe(MMHandleType handle, _MMCamcorderHandlerCategory category)
350 {
351         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
352         GList *list = NULL;
353         MMCamcorderHandlerItem *item = NULL;
354
355         mmf_return_if_fail(hcamcorder);
356
357         if(!hcamcorder->event_probes)
358         {
359                 _mmcam_dbg_err("Fail to remove event probe, list for event probe is NULL");
360         }
361
362         list = hcamcorder->event_probes;
363
364         while(list)
365         {       
366                 item = list->data;
367
368                 if(!item)
369                 {
370                         _mmcam_dbg_err("Remove event probe faild, the item is NULL");
371                         list =  g_list_next(list);
372                         continue;                       
373                 }
374
375                 if(item->category & category)
376                 {
377                 
378                         if(item->object && GST_IS_PAD(item->object))
379                         {
380                                 _mmcam_dbg_log("Remove event probe on [%s:%s] - [ID : %lu], [Category : %x]", 
381                                                 GST_DEBUG_PAD_NAME(item->object), item->handler_id,  item->category);
382                                 gst_pad_remove_event_probe(GST_PAD(item->object), item->handler_id);
383                         }
384                         else
385                         {
386                                 _mmcam_dbg_warn("Remove event probe faild, the pad is null or not pad, just remove item from list and free it");
387                         }                       
388                         
389                         list =  g_list_next(list);
390                         hcamcorder->event_probes = g_list_remove(hcamcorder->event_probes, item);
391                         SAFE_FREE(item);
392                 }
393                 else
394                 {
395                         _mmcam_dbg_log("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
396                         list =  g_list_next(list);
397                 }
398         }
399
400         if( category == _MMCAMCORDER_HANDLER_CATEGORY_ALL)
401         {
402                 g_list_free(hcamcorder->event_probes);
403                 hcamcorder->event_probes = NULL;
404         }       
405 }
406
407 void _mmcamcorder_remove_data_probe(MMHandleType handle, _MMCamcorderHandlerCategory category)
408 {
409         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
410         GList *list = NULL;
411         MMCamcorderHandlerItem *item = NULL;
412
413         mmf_return_if_fail(hcamcorder);
414
415         if(!hcamcorder->data_probes)
416         {
417                 _mmcam_dbg_err("Fail to remove data probe, list for data probe is NULL");
418         }
419
420         list = hcamcorder->data_probes;
421
422         while(list)
423         {       
424                 item = list->data;
425
426                 if(!item)
427                 {
428                         _mmcam_dbg_err("Remove data probe faild, the item is NULL");
429                         list =  g_list_next(list);
430                         continue;                       
431                 }
432
433                 if(item->category & category)
434                 {
435                 
436                         if(item->object && GST_IS_PAD(item->object))
437                         {
438                                 _mmcam_dbg_log("Remove data probe on [%s:%s] - [ID : %lu], [Category : %x]", 
439                                                 GST_DEBUG_PAD_NAME(item->object), item->handler_id,  item->category);
440                                 gst_pad_remove_data_probe(GST_PAD(item->object), item->handler_id);
441                         }
442                         else
443                         {
444                                 _mmcam_dbg_warn("Remove data probe faild, the pad is null or not pad, just remove item from list and free it");
445                         }                       
446                         
447                         list =  g_list_next(list);
448                         hcamcorder->data_probes = g_list_remove(hcamcorder->data_probes, item);
449                         SAFE_FREE(item);
450                 }
451                 else
452                 {
453                         _mmcam_dbg_log("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
454                         list =  g_list_next(list);
455                 }
456         }
457
458         if( category == _MMCAMCORDER_HANDLER_CATEGORY_ALL)
459         {
460                 g_list_free(hcamcorder->data_probes);
461                 hcamcorder->data_probes = NULL;
462         }               
463 }
464
465 void _mmcamcorder_disconnect_signal(MMHandleType handle, _MMCamcorderHandlerCategory category)
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->signals)
474         {
475                 _mmcam_dbg_err("Fail to disconnect signals, list for signal is NULL");
476         }
477
478         list = hcamcorder->signals;
479
480         while(list)
481         {       
482                 item = list->data;
483
484                 if(!item)
485                 {
486                         _mmcam_dbg_err("Fail to Disconnecting signal, the item is NULL");
487                         list =  g_list_next(list);
488                         continue;                       
489                 }
490
491                 if(item->category & category)
492                 {
493                 
494                         if(item->object && GST_IS_ELEMENT(item->object))
495                         {
496                                 if ( g_signal_handler_is_connected ( item->object, item->handler_id ) )
497                                 {
498                                         _mmcam_dbg_log("Disconnect signal from [%s] : [ID : %lu], [Category : %x]", 
499                                                                         GST_OBJECT_NAME(item->object), item->handler_id,  item->category);                      
500                                         g_signal_handler_disconnect ( item->object, item->handler_id );
501                                 }
502                                 else
503                                 {
504                                         _mmcam_dbg_warn("Signal was not connected, cannot disconnect it :  [%s]  [ID : %lu], [Category : %x]", 
505                                                                                 GST_OBJECT_NAME(item->object), item->handler_id,  item->category);
506                                 }
507
508                         }
509                         else
510                         {
511                                 _mmcam_dbg_err("Fail to Disconnecting signal, the element is null or not element, just remove item from list and free it");
512                         }                       
513                         
514                         list =  g_list_next(list);
515                         hcamcorder->signals = g_list_remove(hcamcorder->signals, item);
516                         SAFE_FREE(item);
517                 }
518                 else
519                 {
520                         _mmcam_dbg_log("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
521                         list =  g_list_next(list);
522                 }
523         }
524
525         if( category == _MMCAMCORDER_HANDLER_CATEGORY_ALL)
526         {
527                 g_list_free(hcamcorder->signals);
528                 hcamcorder->signals = NULL;
529         }               
530 }
531
532 void _mmcamcorder_remove_all_handlers(MMHandleType handle,  _MMCamcorderHandlerCategory category)
533 {
534         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
535
536         _mmcam_dbg_log("ENTER");        
537
538         if(hcamcorder->signals)
539                 _mmcamcorder_disconnect_signal((MMHandleType)hcamcorder, category);
540         if(hcamcorder->data_probes)
541                 _mmcamcorder_remove_data_probe((MMHandleType)hcamcorder, category);
542         if(hcamcorder->event_probes)
543                 _mmcamcorder_remove_event_probe((MMHandleType)hcamcorder, category);    
544         if(hcamcorder->buffer_probes)
545                 _mmcamcorder_remove_buffer_probe((MMHandleType)hcamcorder, category);
546
547         _mmcam_dbg_log("LEAVE");
548 }
549
550 void _mmcamcorder_element_release_noti(gpointer data, GObject *where_the_object_was)
551 {
552         int i=0;
553         _MMCamcorderSubContext *sc = (_MMCamcorderSubContext *)data;    
554         mmf_return_if_fail(sc);
555         mmf_return_if_fail(sc->element);
556
557         for(i=0;i< _MMCamcorder_PIPELINE_ELEMENT_NUM; i++)
558         {
559                 if(sc->element[i].gst && (G_OBJECT(sc->element[i].gst) == where_the_object_was))
560                 {
561                         _mmcam_dbg_log("The element[%d][%p] is finalized", sc->element[i].id, sc->element[i].gst);
562                         sc->element[i].gst = NULL;
563                         sc->element[i].id = _MMCAMCORDER_NONE;
564                         break;
565                 }
566         }
567 }
568
569
570 gboolean
571 _mmcamcroder_msg_callback(void *data)
572 {
573         _MMCamcorderMsgItem * item = (_MMCamcorderMsgItem*)data;
574         mmf_camcorder_t *hcamcorder= NULL;
575         mmf_return_val_if_fail( item, FALSE );
576         
577         hcamcorder = MMF_CAMCORDER(item->handle);
578         mmf_return_val_if_fail( hcamcorder, FALSE );
579
580 //      _mmcam_dbg_log("msg id:%x, msg_cb:%p, msg_data:%p, item:%p", item->id, hcamcorder->msg_cb, hcamcorder->msg_data, item);
581
582         _MMCAMCORDER_LOCK_MESSAGE_CALLBACK( hcamcorder );
583
584         if ((hcamcorder) && (hcamcorder->msg_cb)) {
585                 hcamcorder->msg_cb(item->id, (MMMessageParamType*)(&(item->param)), hcamcorder->msg_cb_param);
586         }
587
588         _MMCAMCORDER_UNLOCK_MESSAGE_CALLBACK( hcamcorder );
589
590         _MMCAMCORDER_LOCK((MMHandleType)hcamcorder);
591         
592         if (hcamcorder->msg_data)
593                 hcamcorder->msg_data = g_list_remove(hcamcorder->msg_data, item);
594
595         SAFE_FREE(item);
596
597         _MMCAMCORDER_UNLOCK((MMHandleType)hcamcorder);
598
599         return FALSE;           //For not being called again
600 }
601
602
603 gboolean
604 _mmcamcroder_send_message(MMHandleType handle, _MMCamcorderMsgItem *data)
605 {
606         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
607         _MMCamcorderMsgItem *item = NULL;
608
609         mmf_return_val_if_fail(hcamcorder, FALSE);
610         mmf_return_val_if_fail(data, FALSE);
611
612         switch (data->id)
613         {
614                 case MM_MESSAGE_CAMCORDER_STATE_CHANGED:
615                 case MM_MESSAGE_CAMCORDER_STATE_CHANGED_BY_ASM:
616                         data->param.union_type = MM_MSG_UNION_STATE;
617                         break;
618                 case MM_MESSAGE_CAMCORDER_RECORDING_STATUS:
619                         data->param.union_type = MM_MSG_UNION_RECORDING_STATUS;
620                         break;
621                 case MM_MESSAGE_CAMCORDER_FIRMWARE_UPDATE:
622                         data->param.union_type = MM_MSG_UNION_FIRMWARE;
623                         break;
624                 case MM_MESSAGE_CAMCORDER_CURRENT_VOLUME:
625                         data->param.union_type = MM_MSG_UNION_REC_VOLUME_DB;
626                         break;
627                 case MM_MESSAGE_CAMCORDER_TIME_LIMIT:
628                 case MM_MESSAGE_CAMCORDER_MAX_SIZE:
629                 case MM_MESSAGE_CAMCORDER_NO_FREE_SPACE:
630                 case MM_MESSAGE_CAMCORDER_ERROR:
631                 case MM_MESSAGE_CAMCORDER_FOCUS_CHANGED:
632                 case MM_MESSAGE_CAMCORDER_CAPTURED:
633                 case MM_MESSAGE_READY_TO_RESUME:
634                 default:
635                         data->param.union_type = MM_MSG_UNION_CODE;
636                         break;
637         }
638
639         item = g_malloc(sizeof(_MMCamcorderMsgItem));
640         memcpy(item, data, sizeof(_MMCamcorderMsgItem));
641         item->handle = handle;
642
643         _MMCAMCORDER_LOCK(handle);
644         hcamcorder->msg_data = g_list_append(hcamcorder->msg_data, item);
645 //      _mmcam_dbg_log("item[%p]", item);
646
647         g_idle_add(_mmcamcroder_msg_callback, item);
648
649         _MMCAMCORDER_UNLOCK(handle);
650
651         return TRUE;
652 }
653
654
655 void
656 _mmcamcroder_remove_message_all(MMHandleType handle)
657 {
658         mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
659         _MMCamcorderMsgItem *item = NULL;
660         gboolean ret = TRUE;
661         GList *list = NULL;
662
663         mmf_return_if_fail(hcamcorder);
664
665         _MMCAMCORDER_LOCK(handle);
666
667         if(!hcamcorder->msg_data)
668         {
669                 _mmcam_dbg_log("No message data is remained.");
670         }
671         else
672         {
673                 list = hcamcorder->msg_data;
674
675                 while(list)
676                 {
677                         item = list->data;
678                         list =  g_list_next(list);
679
680                         if(!item)
681                         {
682                                 _mmcam_dbg_err("Fail to remove message. The item is NULL");
683                         }
684                         else
685                         {
686                                 ret = g_idle_remove_by_data (item);
687                                 _mmcam_dbg_log("Remove item[%p]. ret[%d]", item, ret);
688
689                                 hcamcorder->msg_data = g_list_remove(hcamcorder->msg_data, item);
690
691                                 SAFE_FREE(item);
692                         }
693                 }
694
695                 g_list_free(hcamcorder->msg_data);
696                 hcamcorder->msg_data = NULL;
697         }
698
699         _MMCAMCORDER_UNLOCK(handle);
700
701         return;
702 }
703
704
705 void
706 _mmcamcorder_err_trace_write( char *str_filename, char *func_name, int line_num, char *fmt, ... )
707 {
708         FILE *f    = NULL;
709         va_list ap = {0};
710         char time_string[TIME_STRING_MAX_LEN] = {'\0',};
711
712         time_t current_time;
713         struct tm new_time;
714
715         mmf_return_if_fail( str_filename );
716
717         current_time = time( NULL );
718         localtime_r( &current_time, &new_time );
719
720         f = fopen( str_filename, "a" );
721         if( f == NULL )
722         {
723                 _mmcam_dbg_warn( "Failed to open file.[%s]", str_filename );
724                 return;
725         }
726
727         asctime_r(&new_time, time_string);
728         fprintf( f, "[%.19s][%05d][%s]", time_string, line_num, func_name );
729
730         va_start( ap, fmt );
731         vfprintf( f, fmt, ap );
732         va_end( ap );
733
734         fprintf( f, "\n" );
735
736         fclose( f );
737 }
738
739 int
740 _mmcamcorder_get_pixel_format(GstBuffer *buffer)
741 {
742         GstCaps *caps = NULL;
743         const GstStructure *structure;
744         const char *media_type;
745         MMPixelFormatType type = 0;
746         unsigned int fourcc = 0;
747         
748         mmf_return_val_if_fail( buffer != NULL, MM_PIXEL_FORMAT_INVALID );
749
750         caps = gst_buffer_get_caps (buffer);
751         structure = gst_caps_get_structure (caps, 0);
752         media_type = gst_structure_get_name (structure);
753
754         if (!strcmp (media_type, "image/jpeg") )
755         {
756                 _mmcam_dbg_log("It is jpeg.");
757                 type = MM_PIXEL_FORMAT_ENCODED;
758         }
759         else if (!strcmp (media_type, "video/x-raw-yuv"))
760         {
761                 _mmcam_dbg_log("It is yuv.");
762                 gst_structure_get_fourcc (structure, "format", &fourcc);
763                 type = _mmcamcorder_get_pixtype(fourcc);
764         }
765         else
766         {
767                 _mmcam_dbg_err("Not supported format");
768                 type = MM_PIXEL_FORMAT_INVALID;
769         }
770         
771         _mmcam_dbg_log( "Type [%d]", type );
772
773         gst_caps_unref( caps );
774         caps = NULL;
775
776         return type;
777 }
778
779 unsigned int _mmcamcorder_get_fourcc(int pixtype, int codectype, int use_zero_copy_format)
780 {
781         unsigned int fourcc = 0;
782
783         _mmcam_dbg_log("pixtype(%d)", pixtype);
784
785         switch (pixtype) {
786         case MM_PIXEL_FORMAT_NV12:
787                 if (use_zero_copy_format) {
788                         fourcc = GST_MAKE_FOURCC ('S', 'N', '1', '2');
789                 } else {
790                         fourcc = GST_MAKE_FOURCC ('N', 'V', '1', '2');
791                 }
792                 break;
793         case MM_PIXEL_FORMAT_YUYV:
794                 if (use_zero_copy_format) {
795                         fourcc = GST_MAKE_FOURCC ('S', 'U', 'Y', 'V');
796                 } else {
797                         fourcc = GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
798                 }
799                 break;
800         case MM_PIXEL_FORMAT_UYVY:
801                 if (use_zero_copy_format) {
802                         fourcc = GST_MAKE_FOURCC ('S', 'Y', 'V', 'Y');
803                 } else {
804                         fourcc = GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
805                 }
806                 break;
807         case MM_PIXEL_FORMAT_I420:
808                 if (use_zero_copy_format) {
809                         fourcc = GST_MAKE_FOURCC ('S', '4', '2', '0');
810                 } else {
811                         fourcc = GST_MAKE_FOURCC ('I', '4', '2', '0');
812                 }
813                 break;
814         case MM_PIXEL_FORMAT_YV12:
815                 fourcc = GST_MAKE_FOURCC ('Y', 'V', '1', '2');
816                 break;
817         case MM_PIXEL_FORMAT_422P:
818                 fourcc = GST_MAKE_FOURCC ('4', '2', '2', 'P');
819                 break;
820         case MM_PIXEL_FORMAT_RGB565:
821                 fourcc = GST_MAKE_FOURCC ('R', 'G', 'B', 'P');
822                 break;
823         case MM_PIXEL_FORMAT_RGB888:
824                 fourcc = GST_MAKE_FOURCC ('R', 'G', 'B', '3');
825                 break;
826         case MM_PIXEL_FORMAT_ENCODED:
827                 if (codectype == MM_IMAGE_CODEC_JPEG) {
828                         fourcc = GST_MAKE_FOURCC ('J', 'P', 'E', 'G');
829                 } else if (codectype == MM_IMAGE_CODEC_JPEG_SRW) {
830                         fourcc = GST_MAKE_FOURCC ('J', 'P', 'E', 'G'); /*TODO: JPEG+SamsungRAW format */
831                 } else if (codectype == MM_IMAGE_CODEC_SRW) {
832                         fourcc = GST_MAKE_FOURCC ('J', 'P', 'E', 'G'); /*TODO: SamsungRAW format */
833                 } else if (codectype == MM_IMAGE_CODEC_PNG) {
834                         fourcc = GST_MAKE_FOURCC ('P', 'N', 'G', ' ');
835                 } else {
836                         /* Please let us know what other fourcces are. ex) BMP, GIF?*/
837                         fourcc = GST_MAKE_FOURCC ('J', 'P', 'E', 'G');
838                 }
839                 break;
840         default:
841                 _mmcam_dbg_log("Not proper pixel type. Set default.");
842                 fourcc = GST_MAKE_FOURCC ('S', '4', '2', '0');
843                 break;
844         }
845
846         return fourcc;
847 }
848
849
850 int _mmcamcorder_get_pixtype(unsigned int fourcc)
851 {
852         int pixtype = MM_PIXEL_FORMAT_INVALID;
853         char *pfourcc = (char*)&fourcc;
854         _mmcam_dbg_log("fourcc(%c%c%c%c)", pfourcc[0], pfourcc[1], pfourcc[2], pfourcc[3]);
855
856         switch (fourcc) {
857         case GST_MAKE_FOURCC ('S', 'N', '1', '2'):
858         case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
859                 pixtype = MM_PIXEL_FORMAT_NV12;
860                 break;
861         case GST_MAKE_FOURCC ('S', 'U', 'Y', 'V'):
862         case GST_MAKE_FOURCC ('Y', 'U', 'Y', 'V'):
863         case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
864                 pixtype = MM_PIXEL_FORMAT_YUYV;
865                 break;
866         case GST_MAKE_FOURCC ('S', 'Y', 'V', 'Y'):
867         case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
868                 pixtype = MM_PIXEL_FORMAT_UYVY;
869                 break;
870         case GST_MAKE_FOURCC ('S', '4', '2', '0'):
871         case GST_MAKE_FOURCC ('I', '4', '2', '0'):
872                 pixtype = MM_PIXEL_FORMAT_I420;
873                 break;
874         case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
875                 pixtype = MM_PIXEL_FORMAT_YV12;
876                 break;
877         case GST_MAKE_FOURCC ('4', '2', '2', 'P'):
878                 pixtype = MM_PIXEL_FORMAT_422P;
879                 break;
880         case GST_MAKE_FOURCC ('R', 'G', 'B', 'P'):
881                 pixtype = MM_PIXEL_FORMAT_RGB565;
882                 break;
883         case GST_MAKE_FOURCC ('R', 'G', 'B', '3'):
884                 pixtype = MM_PIXEL_FORMAT_RGB888;
885                 break;
886         case GST_MAKE_FOURCC ('A', 'R', 'G', 'B'):
887         case GST_MAKE_FOURCC ('x', 'R', 'G', 'B'):
888                 pixtype = MM_PIXEL_FORMAT_ARGB;
889                 break;
890         case GST_MAKE_FOURCC ('B', 'G', 'R', 'A'):
891         case GST_MAKE_FOURCC ('B', 'G', 'R', 'x'):
892                 pixtype = MM_PIXEL_FORMAT_RGBA;
893                 break;
894         case GST_MAKE_FOURCC ('J', 'P', 'E', 'G'):
895         case GST_MAKE_FOURCC ('P', 'N', 'G', ' '):
896                 pixtype = MM_PIXEL_FORMAT_ENCODED;
897                 break;
898         default:
899                 _mmcam_dbg_log("Not supported fourcc type(%x)", fourcc);
900                 pixtype = MM_PIXEL_FORMAT_INVALID;
901                 break;
902         }
903
904         return pixtype;
905 }
906
907
908 gboolean
909 _mmcamcorder_add_elements_to_bin( GstBin *bin, GList *element_list )
910 {
911         GList *local_list = element_list;
912         _MMCamcorderGstElement *element = NULL;
913
914         mmf_return_val_if_fail( bin && local_list, FALSE );
915
916         while( local_list )
917         {
918                 element = (_MMCamcorderGstElement*)local_list->data;
919                 if( element && element->gst )
920                 {
921                         if( !gst_bin_add( bin, GST_ELEMENT(element->gst) ) )
922                         {
923                                 _mmcam_dbg_err( "Add element [%s] to bin [%s] FAILED",
924                                                 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
925                                                 GST_ELEMENT_NAME(GST_ELEMENT(bin)) );
926                                 return FALSE;
927                         }
928                         else
929                         {
930                                 _mmcam_dbg_log( "Add element [%s] to bin [%s] OK",
931                                                 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
932                                                 GST_ELEMENT_NAME(GST_ELEMENT(bin)) );
933                         }
934                 }
935
936                 local_list = local_list->next;
937         }
938
939         return TRUE;
940 }
941
942 gboolean
943 _mmcamcorder_link_elements( GList *element_list )
944 {
945         GList                  *local_list  = element_list;
946         _MMCamcorderGstElement *element     = NULL;
947         _MMCamcorderGstElement *pre_element = NULL;
948
949         mmf_return_val_if_fail( local_list, FALSE );
950
951         pre_element = (_MMCamcorderGstElement*)local_list->data;
952         local_list = local_list->next;
953
954         while( local_list )
955         {
956                 element = (_MMCamcorderGstElement*)local_list->data;
957                 if( element && element->gst )
958                 {
959                         if( _MM_GST_ELEMENT_LINK( GST_ELEMENT(pre_element->gst), GST_ELEMENT(element->gst) ) )
960                         {
961                                 _mmcam_dbg_log( "Link [%s] to [%s] OK",
962                                                 GST_ELEMENT_NAME(GST_ELEMENT(pre_element->gst)),
963                                                 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
964                         }
965                         else
966                         {
967                                 _mmcam_dbg_err( "Link [%s] to [%s] FAILED",
968                                                 GST_ELEMENT_NAME(GST_ELEMENT(pre_element->gst)),
969                                                 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
970                                 return FALSE;
971                         }
972                 }
973
974                 pre_element = element;
975                 local_list = local_list->next;
976         }
977
978         return TRUE;
979 }
980
981
982 gboolean _mmcamcorder_encode_jpeg(void *src_data, unsigned int src_width, unsigned int src_height,
983                                   int src_format, unsigned int src_length, unsigned int jpeg_quality,
984                                   void **result_data, unsigned int *result_length)
985 {
986         int ret = 0;
987         int i = 0;
988         guint32 src_fourcc = 0;
989         gboolean do_encode = FALSE;
990         jpegenc_parameter enc_param;
991         static jpegenc_info enc_info = {-1,};
992
993         _mmcam_dbg_log("START");
994
995         mmf_return_val_if_fail(src_data && result_data && result_length, FALSE);
996
997         CLEAR(enc_param);
998
999         if (enc_info.sw_support == -1) {
1000                 CLEAR(enc_info);
1001                 __ta__("camsrcjpegenc_get_info",
1002                 camsrcjpegenc_get_info(&enc_info);
1003                 );
1004         }
1005
1006         src_fourcc = _mmcamcorder_get_fourcc(src_format, 0, FALSE);
1007         camsrcjpegenc_get_src_fmt(src_fourcc, &(enc_param.src_fmt));
1008
1009         if (enc_param.src_fmt != COLOR_FORMAT_NOT_SUPPORT &&
1010             enc_info.sw_support == TRUE) {
1011                 /* Check supported format */
1012                 for (i = 0 ; i < enc_info.sw_enc.input_fmt_num ; i++) {
1013                         if (enc_param.src_fmt == enc_info.sw_enc.input_fmt_list[i]) {
1014                                 do_encode = TRUE;
1015                                 break;
1016                         }
1017                 }
1018
1019                 if (do_encode) {
1020                         enc_param.src_data = src_data;
1021                         enc_param.width = src_width;
1022                         enc_param.height = src_height;
1023                         enc_param.src_len = src_length;
1024                         enc_param.jpeg_mode = JPEG_MODE_BASELINE;
1025                         enc_param.jpeg_quality = jpeg_quality;
1026
1027                         __ta__("                    camsrcjpegenc_encode",
1028                         ret = camsrcjpegenc_encode(&enc_info, JPEG_ENCODER_SOFTWARE, &enc_param );
1029                         );
1030                         if (ret == CAMSRC_JPEGENC_ERROR_NONE) {
1031                                 *result_data = enc_param.result_data;
1032                                 *result_length = enc_param.result_len;
1033
1034                                 _mmcam_dbg_log("JPEG encode length(%d)", *result_length);
1035
1036                                 return TRUE;
1037                         } else {
1038                                 _mmcam_dbg_err("camsrcjpegenc_encode failed(%x)", ret);
1039                                 return FALSE;
1040                         }
1041                 } else {
1042                         _mmcam_dbg_err("S/W JPEG codec does NOT support format [%d]", src_format);
1043                         return FALSE;
1044                 }
1045         } else {
1046                 _mmcam_dbg_err("Not Supported FOURCC(format:%d) or There is NO S/W encoder(%d)",
1047                                 src_format, enc_info.sw_support);
1048                 return FALSE;
1049         }
1050 }
1051
1052
1053 static guint16 get_language_code(const char *str)
1054 {
1055     return (guint16) (((str[0]-0x60) & 0x1F) << 10) + (((str[1]-0x60) & 0x1F) << 5) + ((str[2]-0x60) & 0x1F);
1056 }
1057
1058 static gchar * str_to_utf8(const gchar *str)
1059 {
1060         return g_convert (str, -1, "UTF-8", "ASCII", NULL, NULL, NULL);
1061 }
1062
1063 static inline gboolean write_tag(FILE *f, const gchar *tag)
1064 {
1065         while(*tag)
1066                 FPUTC_CHECK(*tag++, f);
1067
1068         return TRUE;    
1069 }
1070
1071 static inline gboolean write_to_32(FILE *f, guint val)
1072 {
1073         FPUTC_CHECK(val >> 24, f);
1074         FPUTC_CHECK(val >> 16, f);
1075         FPUTC_CHECK(val >> 8, f);
1076         FPUTC_CHECK(val, f);
1077         return TRUE;
1078 }
1079
1080 static inline gboolean write_to_16(FILE *f, guint val)
1081 {
1082         FPUTC_CHECK(val >> 8, f);
1083         FPUTC_CHECK(val, f);
1084         return TRUE;    
1085 }
1086
1087 static inline gboolean write_to_24(FILE *f, guint val)
1088 {
1089         write_to_16(f, val >> 8);
1090         FPUTC_CHECK(val, f);
1091         return TRUE;    
1092 }