Flora license update
[apps/core/preloaded/ug-camera-efl.git] / src / cam_ta.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *        http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17
18 #ifndef _CAM_TA_C_
19 #define _CAM_TA_C_
20
21 #include <stdio.h>
22 #include <malloc.h>
23 #include <string.h>
24 #include <assert.h>
25 #include <time.h>               /*  time, ctime */
26 #include <sys/time.h>           /*  gettimeofday */
27 #include <sys/utsname.h>
28 #include <sys/resource.h>
29 #include <unistd.h>
30 #include <stdarg.h>
31
32 #include "cam_ta.h"
33
34 /*  internal func. */
35 static void __free_cps(void);
36 static int __get_cp_index(char *name);
37
38 static void __free_accums(void);
39 static int __get_accum_index(char *name);
40
41 /*  global var. */
42 cam_ta_checkpoint **cam_g_cps = NULL;
43 static int cam_g_cp_index = 0;
44
45 cam_ta_accum_item **cam_g_accums = NULL;
46 static int cam_g_accum_index = 0;
47 static int cam_g_accum_longest_name = 0;
48 static unsigned long cam_g_accum_first_time = 0xFFFFFFFF;       /*  jmlee */
49 static int cam_g_enable = 0;
50
51 int cam_ta_init(void)
52 {
53         if (cam_g_accums)
54                 return 0;
55
56         cam_g_cps =
57             (cam_ta_checkpoint **) malloc(CAM_TA_MAX_CHECKPOINT *
58                                           sizeof(cam_ta_checkpoint *));
59         if (!cam_g_cps)
60                 return -1;
61
62         cam_g_accums =
63             (cam_ta_accum_item **) malloc(CAM_TA_MAX_CHECKPOINT *
64                                           sizeof(cam_ta_accum_item *));
65         if (!cam_g_accums)
66                 return -1;
67
68         cam_g_accum_first_time = 0xFFFFFFFF;
69
70         return 0;
71 }
72
73 int cam_ta_release(void)
74 {
75         if (!cam_g_accums)
76                 return 0;
77
78         __free_cps();
79         __free_accums();
80
81         cam_g_accum_first_time = 0xFFFFFFFF;
82
83         return 0;
84 }
85
86 void cam_ta_set_enable(int enable)
87 {
88         printf("CAM_TA : setting enable to %d\n", enable);
89         cam_g_enable = enable;
90 }
91
92 int cam_ta_get_numof_checkpoints()
93 {
94         return cam_g_cp_index;
95 }
96
97 char *cam_ta_fmt(const char *fmt, ...)
98 {
99         static char ta_buf[512];
100         va_list args;
101
102         memset(ta_buf, '\0', 512);
103
104         va_start(args, fmt);
105         vsnprintf(ta_buf, 512, fmt, args);
106         va_end(args);
107
108         return ta_buf;
109 }
110
111 int cam_ta_add_checkpoint(char *name, int show, char *filename, int line)
112 {
113         cam_ta_checkpoint *cp = NULL;
114         struct timeval t;
115
116         if (!cam_g_enable)
117                 return -1;
118
119         if (!cam_g_accums)
120                 return 0;
121
122         if (cam_g_cp_index == CAM_TA_MAX_CHECKPOINT)
123                 return -1;
124
125         if (!name)
126                 return -1;
127
128         if (strlen(name) == 0)
129                 return -1;
130
131         cp = (cam_ta_checkpoint *) malloc(sizeof(cam_ta_checkpoint));
132         if (!cp)
133                 return -1;
134
135         cp->name = (char *)malloc(strlen(name) + 1);
136         if (!cp->name) {
137                 free(cp);
138                 return -1;
139         }
140         strncpy(cp->name, name, strlen(name));
141
142         if (show)
143                 printf("[CHECK-POINT] %s...(%s:%d)\n", name, filename, line);
144
145         gettimeofday(&t, NULL);
146         cp->timestamp = t.tv_sec * 1000000L + t.tv_usec;
147 #ifdef CAM_TA_UNIT_MSEC
148         cp->timestamp = (cp->timestamp >= 1000) ? cp->timestamp / 1000 : 0;
149 #endif
150
151         cam_g_cps[cam_g_cp_index] = cp;
152
153         cam_g_cp_index++;
154
155         return 0;
156 }
157
158 void cam_ta_show_checkpoints(void)
159 {
160         int i = 0;
161
162         if (!cam_g_accums)
163                 return;
164
165         printf("BEGIN RESULT ============================\n");
166         for (i = 0; i < cam_g_cp_index; i++) {
167                 printf("[%d] %s : %ld us.\n", i, cam_g_cps[i]->name,
168                        cam_g_cps[i]->timestamp);
169         }
170         printf("END RESULT   ============================\n");
171 }
172
173 void cam_ta_show_diff(char *name1, char *name2)
174 {
175         if (!cam_g_accums)
176                 return;
177
178         printf("Time takes from [%s] to [%s] : %ld us.\n", name1, name2,
179                cam_ta_get_diff(name1, name2));
180 }
181
182 unsigned long cam_ta_get_diff(char *name1, char *name2)
183 {
184         int cp1, cp2;
185
186         if (!cam_g_accums)
187                 return 0;
188
189         /*  fail if bad param. */
190         if (!name1 || !name2)
191                 return -1;
192
193         /*  fail if same. */
194         if (strcmp(name1, name2) == 0)
195                 return -1;
196
197         /*  get index */
198         if ((cp1 = __get_cp_index(name1)) == -1)
199                 return -1;
200
201         if ((cp2 = __get_cp_index(name2)) == -1)
202                 return -1;
203
204         /* NOTE :
205            return value must be positive value.
206            bcz the value of higher index of cam_g_cps always higher than lower one.
207          */
208         return cam_g_cps[cp2]->timestamp - cam_g_cps[cp1]->timestamp;
209
210 }
211
212 static int __get_cp_index(char *name)
213 {
214         int i;
215
216         assert(name);
217
218         /*  find index */
219         for (i = 0; i < cam_g_cp_index; i++) {
220                 if (strcmp(name, cam_g_cps[i]->name) == 0)
221                         return i;
222         }
223
224         return -1;
225 }
226
227 static int __get_accum_index(char *name)
228 {
229         int i;
230
231         assert(name);
232
233         /*  find index */
234         for (i = 0; i < cam_g_accum_index; i++) {
235                 if (strcmp(name, cam_g_accums[i]->name) == 0)
236                         return i;
237         }
238
239         return -1;
240 }
241
242 static void __free_cps(void)
243 {
244         int i = 0;
245
246         if (!cam_g_cps)
247                 return;
248
249         for (i = 0; i < cam_g_cp_index; i++) {
250                 if (cam_g_cps[i]) {
251                         if (cam_g_cps[i]->name)
252                                 free(cam_g_cps[i]->name);
253
254                         free(cam_g_cps[i]);
255
256                         cam_g_cps[i] = NULL;
257                 }
258         }
259
260         free(cam_g_cps);
261         cam_g_cps = NULL;
262
263         cam_g_cp_index = 0;
264 }
265
266 static void __free_accums(void)
267 {
268         int i = 0;
269
270         if (!cam_g_accums)
271                 return;
272
273         for (i = 0; i < cam_g_accum_index; i++) {
274                 if (cam_g_accums[i]) {
275                         if (cam_g_accums[i]->name)
276                                 free(cam_g_accums[i]->name);
277
278                         free(cam_g_accums[i]);
279
280                         cam_g_accums[i] = NULL;
281                 }
282         }
283
284         cam_g_accum_index = 0;
285         cam_g_accum_longest_name = 0;
286
287         free(cam_g_accums);
288         cam_g_accums = NULL;
289 }
290
291 int cam_ta_accum_item_begin(char *name, int show, char *filename, int line)
292 {
293         cam_ta_accum_item *accum = NULL;
294         int index = 0;
295         int name_len = 0;
296         struct timeval t;
297
298         if (!cam_g_enable)
299                 return -1;
300
301         if (!cam_g_accums)
302                 return 0;
303
304         if (cam_g_accum_index == CAM_TA_MAX_ACCUM)
305                 return -1;
306
307         if (!name)
308                 return -1;
309
310         name_len = strlen(name);
311         if (name_len == 0)
312                 return -1;
313
314         /*  if 'name' is new one. create new item. */
315         if ((index = __get_accum_index(name)) == -1) {
316                 accum = (cam_ta_accum_item *) malloc(sizeof(cam_ta_accum_item));
317                 if (!accum)
318                         return -1;
319
320                 /*  clear first. */
321                 memset(accum, 0, sizeof(cam_ta_accum_item));
322                 accum->elapsed_min = 0xFFFFFFFF;
323
324                 accum->name = (char *)malloc(name_len + 1);
325                 if (!accum->name) {
326                         free(accum);
327                         accum = NULL;
328                         return -1;
329                 }
330                 memset(accum->name, 0, name_len+1);
331                 strncpy(accum->name, name, name_len);
332
333                 /*  add it to list. */
334                 cam_g_accums[cam_g_accum_index] = accum;
335                 cam_g_accum_index++;
336
337                 if (cam_g_accum_longest_name < name_len)
338                         cam_g_accum_longest_name = name_len;
339
340         } else {
341                 accum = cam_g_accums[index];
342         }
343
344         /*  verify pairs of begin, end. */
345         if (accum->on_estimate) {
346                 printf("[%s] is not 'end'ed!\n", accum->name);
347                 accum->num_unpair++;
348                 return -1;
349         }
350         /*  get timestamp */
351         gettimeofday(&t, NULL);
352         accum->timestamp = t.tv_sec * 1000000L + t.tv_usec;
353 #ifdef CAM_TA_UNIT_MSEC
354         accum->timestamp =
355             (accum->timestamp >= 1000) ? accum->timestamp / 1000 : 0;
356 #endif
357         accum->on_estimate = 1;
358
359         if (accum->first_start == 0) {  /*  assum that timestamp never could be zero. */
360                 accum->first_start = accum->timestamp;
361
362                 if (cam_g_accum_first_time > accum->first_start)
363                         cam_g_accum_first_time = accum->first_start;
364         }
365
366         if (show)
367                 printf("[ACCUM BEGIN] %s : %ld ---(%s:%d)\n", name,
368                        accum->timestamp, filename, line);
369
370         accum->num_calls++;
371
372         return 0;
373 }
374
375 int cam_ta_accum_item_end(char *name, int show, char *filename, int line)
376 {
377         cam_ta_accum_item *accum = NULL;
378         long int tval = 0;
379         int index = 0;
380         struct timeval t;
381
382         if (!cam_g_enable)
383                 return -1;
384
385         if (!cam_g_accums)
386                 return 0;
387
388         /*  get time first for more accuracy. */
389         gettimeofday(&t, NULL);
390
391         if (cam_g_accum_index == CAM_TA_MAX_ACCUM)
392                 return -1;
393
394         if (!name)
395                 return -1;
396
397         if (strlen(name) == 0)
398                 return -1;
399
400         /*  varify the 'name' is already exist. */
401         if ((index = __get_accum_index(name)) == -1) {
402                 /* printf("[%s] is not added before!\n", name); */
403                 return -1;
404         }
405
406         accum = cam_g_accums[index];
407
408         /* verify pairs of begin, end. */
409         if (!accum->on_estimate) {
410                 printf("[%s] is not 'begin' yet!\n", accum->name);
411                 accum->num_unpair++;
412                 return -1;
413         }
414         /*  get current timestamp. */
415         tval = t.tv_sec * 1000000L + t.tv_usec;
416 #ifdef CAM_TA_UNIT_MSEC
417         tval = (tval >= 1000) ? tval / 1000 : 0;
418 #endif
419
420         /*  update last_end */
421         accum->last_end = tval;
422
423         /*  make get elapsed time. */
424         tval = tval - accum->timestamp;
425
426         /*  update min/max */
427         accum->elapsed_max =
428             tval > accum->elapsed_max ? tval : accum->elapsed_max;
429         accum->elapsed_min =
430             tval < accum->elapsed_min ? tval : accum->elapsed_min;
431
432         if (show)
433                 printf("[ACCUM END] %s : %ld + %ld ---(%s:%d)\n", name,
434                        accum->elapsed_accum, tval, filename, line);
435
436         /*  add elapsed time */
437         accum->elapsed_accum += tval;
438         accum->on_estimate = 0;
439
440         return 0;
441 }
442
443 void __print_some_info(FILE *fp)
444 {
445         if (!fp)
446                 return;
447
448         /*  comment */
449         {
450                 fprintf(fp, "\nb~ b~ b~\n\n");
451         }
452
453         /*  General infomation */
454         {
455                 time_t t_val;
456                 char hostname[256] = { '\0', };
457                 struct utsname uts;
458                 struct rusage r_usage;
459
460                 fprintf(fp, "\n[[ General info ]]\n");
461
462                 /*  time and date */
463                 time(&t_val);
464                 fprintf(fp, "Date : %s", ctime(&t_val));
465
466                 /*  system */
467                 if (gethostname(hostname, 255) == 0 && uname(&uts) >= 0) {
468                         fprintf(fp, "Hostname : %s\n", hostname);
469                         fprintf(fp, "System : %s\n", uts.sysname);
470                         fprintf(fp, "Machine : %s\n", uts.machine);
471                         fprintf(fp, "Nodename : %s\n", uts.nodename);
472                         fprintf(fp, "Release : %s \n", uts.release);
473                         fprintf(fp, "Version : %s \n", uts.version);
474                 }
475                 /*  process info. */
476                 fprintf(fp, "Process priority : %d\n",
477                         getpriority(PRIO_PROCESS, getpid()));
478                 getrusage(RUSAGE_SELF, &r_usage);
479                 fprintf(fp,
480                         "CPU usage : User = %ld.%06ld, System = %ld.%06ld\n",
481                         r_usage.ru_utime.tv_sec, r_usage.ru_utime.tv_usec,
482                         r_usage.ru_stime.tv_sec, r_usage.ru_stime.tv_usec);
483
484         }
485
486         /*  host environment variables */
487         {
488                 extern char **environ;
489                 char **env = environ;
490
491                 fprintf(fp, "\n[[ Host environment variables ]]\n");
492                 while (*env) {
493                         fprintf(fp, "%s\n", *env);
494                         env++;
495                 }
496         }
497
498         /*  applied samsung feature */
499         {
500 #if 0
501                 fprintf(fp, "\n[[ Applied samsung feature ]]\n");
502 #ifdef GST_EXT_TIME_ANALYSIS
503                 fprintf(fp, "GST_EXT_TIME_ANALYSIS\n");
504 #endif
505 #ifdef GST_EXT_SKIP_RESCAN_REGISTRY
506                 fprintf(fp, "GST_EXT_SKIP_RESCAN_REGISTRY\n");
507 #endif
508 #ifdef GST_EXT_USE_TINY_REGISTRY
509
510                 fprintf(fp, "GST_EXT_USE_TINY_REGISTRY\n");
511 #endif
512 #ifdef GST_EXT_PAD_LINK_UNCHECKED
513                 fprintf(fp, "GST_EXT_PAD_LINK_UNCHECKED\n");
514 #endif
515 #ifdef GST_EXT_DFBVIDEOSINK_IPP
516                 fprintf(fp, "GST_EXT_DFBVIDEOSINK_IPP\n");
517 #endif
518 #ifdef GST_EXT_REDUCE_PLUGIN_NUM
519                 fprintf(fp, "GST_EXT_REDUCE_PLUGIN_NUM\n");
520 #endif
521 #ifdef GST_EXT_USE_PDP_NETWORK
522                 fprintf(fp, "GST_EXT_USE_PDP_NETWORK\n");
523 #endif
524 #ifdef GST_EXT_VOLUME_WITHOUT_LIBOIL
525                 fprintf(fp, "GST_EXT_VOLUME_WITHOUT_LIBOIL\n");
526 #endif
527 #ifdef GST_EXT_DECODEBIN_QUEUE_ENLARGE
528                 fprintf(fp, "GST_EXT_DECODEBIN_QUEUE_ENLARGE\n");
529 #endif
530
531                 /*  Camcorder releated feature */
532
533 #ifdef GST_EXT_NONBLOCKDQUE
534                 fprintf(fp, "GST_EXT_NONBLOCKDQUE\n");
535 #endif
536 #ifdef GST_EXT_RENEGOTIATION
537                 fprintf(fp, "GST_EXT_RENEGOTIATION\n");
538 #endif
539 #ifdef GST_EXT_MOBILECAMERA
540                 fprintf(fp, "GST_EXT_MOBILECAMERA\n");
541 #endif
542 #ifdef GST_EXT_VIDEOSCALE_IPP
543                 fprintf(fp, "GST_EXT_VIDEOSCALE_IPP\n");
544 #endif
545 #ifdef GST_EXT_ASYNC_DEV
546                 fprintf(fp, "GST_EXT_ASYNC_DEV\n");
547 #endif
548 #ifdef GST_EXT_AV_RECORDING
549                 fprintf(fp, "GST_EXT_AV_RECORDING\n");
550 #endif
551 #ifdef GST_EXT_SWITCH_CAMERA
552                 fprintf(fp, "GST_EXT_SWITCH_CAMERA\n");
553 #endif
554
555                 fprintf(fp, "\n\n");
556 #endif
557         }
558
559 }
560
561 void cam_ta_accum_show_result(int direction)
562 {
563         int i = 0;
564         char format[256];
565         FILE *fp = stderr;
566
567         if (!cam_g_accums)
568                 return;
569
570         switch (direction) {
571         case CAM_TA_SHOW_STDOUT:
572                 fp = stdout;
573                 break;
574         case CAM_TA_SHOW_STDERR:
575                 fp = stderr;
576                 break;
577         case CAM_TA_SHOW_FILE:
578                 {
579                         fp = fopen(CAM_TA_RESULT_FILE, "wt");
580                         if (!fp)
581                                 return;
582                 }
583         }
584         __print_some_info(fp);
585
586 #ifdef CAM_TA_UNIT_MSEC
587         snprintf(format, sizeof(format),
588                  "[%%3d] %%-%ds | \ttotal : %%4ld\tcalls : %%3ld\tavg : %%4ld\tmin : %%4ld\tmax : %%4ld\tstart : %%4lu\tend : %%4lu\tunpair : %%3ld\n",
589                  cam_g_accum_longest_name);
590         fprintf(fp,
591                 "BEGIN RESULT ACCUM============================ : NumOfItems : %d, unit(msec)\n",
592                 cam_g_accum_index);
593 #else
594         snprintf(format, sizeof(format),
595                  "[%%3d] %%-%ds | \ttotal : %%ld\tcalls : %%ld\tavg : %%ld\tmin : %%ld\tmax : %%ld\tstart : %%lu\tend : %%lu\tunpair : %%ld\n",
596                  cam_g_accum_longest_name);
597         fprintf(fp,
598                 "BEGIN RESULT ACCUM============================ : NumOfItems : %d, unit(usec)\n",
599                 cam_g_accum_index);
600 #endif
601
602         for (i = 0; i < cam_g_accum_index; i++) {
603                 /*  prevent 'devide by zero' error */
604                 if (cam_g_accums[i]->num_calls == 0)
605                         cam_g_accums[i]->num_calls = 1;
606
607                 fprintf(fp, format, i, cam_g_accums[i]->name, cam_g_accums[i]->elapsed_accum, cam_g_accums[i]->num_calls, (cam_g_accums[i]->elapsed_accum == 0) ? 0 : (int)(cam_g_accums[i]->elapsed_accum / cam_g_accums[i]->num_calls),       /*  Fix it! : devide by zero. */
608                         cam_g_accums[i]->elapsed_min,
609                         cam_g_accums[i]->elapsed_max,
610                         cam_g_accums[i]->first_start - cam_g_accum_first_time,
611                         cam_g_accums[i]->last_end - cam_g_accum_first_time,
612                         cam_g_accums[i]->num_unpair);
613         }
614         fprintf(fp, "END RESULT ACCUM  ============================\n");
615
616         if (direction == CAM_TA_SHOW_FILE)
617                 fclose(fp);
618 }
619
620 #endif                          /* _CAM_TA_C_ */