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