diff options
Diffstat (limited to 'src/cam_ta.c')
-rwxr-xr-x | src/cam_ta.c | 620 |
1 files changed, 620 insertions, 0 deletions
diff --git a/src/cam_ta.c b/src/cam_ta.c new file mode 100755 index 0000000..9f89f11 --- /dev/null +++ b/src/cam_ta.c @@ -0,0 +1,620 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef _CAM_TA_C_ +#define _CAM_TA_C_ + +#include <stdio.h> +#include <malloc.h> +#include <string.h> +#include <assert.h> +#include <time.h> /* time, ctime */ +#include <sys/time.h> /* gettimeofday */ +#include <sys/utsname.h> +#include <sys/resource.h> +#include <unistd.h> +#include <stdarg.h> + +#include "cam_ta.h" + +/* internal func. */ +static void __free_cps(void); +static int __get_cp_index(char *name); + +static void __free_accums(void); +static int __get_accum_index(char *name); + +/* global var. */ +cam_ta_checkpoint **cam_g_cps = NULL; +static int cam_g_cp_index = 0; + +cam_ta_accum_item **cam_g_accums = NULL; +static int cam_g_accum_index = 0; +static int cam_g_accum_longest_name = 0; +static unsigned long cam_g_accum_first_time = 0xFFFFFFFF; /* jmlee */ +static int cam_g_enable = 0; + +int cam_ta_init(void) +{ + if (cam_g_accums) + return 0; + + cam_g_cps = + (cam_ta_checkpoint **) malloc(CAM_TA_MAX_CHECKPOINT * + sizeof(cam_ta_checkpoint *)); + if (!cam_g_cps) + return -1; + + cam_g_accums = + (cam_ta_accum_item **) malloc(CAM_TA_MAX_CHECKPOINT * + sizeof(cam_ta_accum_item *)); + if (!cam_g_accums) + return -1; + + cam_g_accum_first_time = 0xFFFFFFFF; + + return 0; +} + +int cam_ta_release(void) +{ + if (!cam_g_accums) + return 0; + + __free_cps(); + __free_accums(); + + cam_g_accum_first_time = 0xFFFFFFFF; + + return 0; +} + +void cam_ta_set_enable(int enable) +{ + printf("CAM_TA : setting enable to %d\n", enable); + cam_g_enable = enable; +} + +int cam_ta_get_numof_checkpoints() +{ + return cam_g_cp_index; +} + +char *cam_ta_fmt(const char *fmt, ...) +{ + static char ta_buf[512]; + va_list args; + + memset(ta_buf, '\0', 512); + + va_start(args, fmt); + vsnprintf(ta_buf, 512, fmt, args); + va_end(args); + + return ta_buf; +} + +int cam_ta_add_checkpoint(char *name, int show, char *filename, int line) +{ + cam_ta_checkpoint *cp = NULL; + struct timeval t; + + if (!cam_g_enable) + return -1; + + if (!cam_g_accums) + return 0; + + if (cam_g_cp_index == CAM_TA_MAX_CHECKPOINT) + return -1; + + if (!name) + return -1; + + if (strlen(name) == 0) + return -1; + + cp = (cam_ta_checkpoint *) malloc(sizeof(cam_ta_checkpoint)); + if (!cp) + return -1; + + cp->name = (char *)malloc(strlen(name) + 1); + if (!cp->name) { + free(cp); + return -1; + } + strncpy(cp->name, name, strlen(name)); + + if (show) + printf("[CHECK-POINT] %s...(%s:%d)\n", name, filename, line); + + gettimeofday(&t, NULL); + cp->timestamp = t.tv_sec * 1000000L + t.tv_usec; +#ifdef CAM_TA_UNIT_MSEC + cp->timestamp = (cp->timestamp >= 1000) ? cp->timestamp / 1000 : 0; +#endif + + cam_g_cps[cam_g_cp_index] = cp; + + cam_g_cp_index++; + + return 0; +} + +void cam_ta_show_checkpoints(void) +{ + int i = 0; + + if (!cam_g_accums) + return; + + printf("BEGIN RESULT ============================\n"); + for (i = 0; i < cam_g_cp_index; i++) { + printf("[%d] %s : %ld us.\n", i, cam_g_cps[i]->name, + cam_g_cps[i]->timestamp); + } + printf("END RESULT ============================\n"); +} + +void cam_ta_show_diff(char *name1, char *name2) +{ + if (!cam_g_accums) + return; + + printf("Time takes from [%s] to [%s] : %ld us.\n", name1, name2, + cam_ta_get_diff(name1, name2)); +} + +unsigned long cam_ta_get_diff(char *name1, char *name2) +{ + int cp1, cp2; + + if (!cam_g_accums) + return 0; + + /* fail if bad param. */ + if (!name1 || !name2) + return -1; + + /* fail if same. */ + if (strcmp(name1, name2) == 0) + return -1; + + /* get index */ + if ((cp1 = __get_cp_index(name1)) == -1) + return -1; + + if ((cp2 = __get_cp_index(name2)) == -1) + return -1; + + /* NOTE : + return value must be positive value. + bcz the value of higher index of cam_g_cps always higher than lower one. + */ + return cam_g_cps[cp2]->timestamp - cam_g_cps[cp1]->timestamp; + +} + +static int __get_cp_index(char *name) +{ + int i; + + assert(name); + + /* find index */ + for (i = 0; i < cam_g_cp_index; i++) { + if (strcmp(name, cam_g_cps[i]->name) == 0) + return i; + } + + return -1; +} + +static int __get_accum_index(char *name) +{ + int i; + + assert(name); + + /* find index */ + for (i = 0; i < cam_g_accum_index; i++) { + if (strcmp(name, cam_g_accums[i]->name) == 0) + return i; + } + + return -1; +} + +static void __free_cps(void) +{ + int i = 0; + + if (!cam_g_cps) + return; + + for (i = 0; i < cam_g_cp_index; i++) { + if (cam_g_cps[i]) { + if (cam_g_cps[i]->name) + free(cam_g_cps[i]->name); + + free(cam_g_cps[i]); + + cam_g_cps[i] = NULL; + } + } + + free(cam_g_cps); + cam_g_cps = NULL; + + cam_g_cp_index = 0; +} + +static void __free_accums(void) +{ + int i = 0; + + if (!cam_g_accums) + return; + + for (i = 0; i < cam_g_accum_index; i++) { + if (cam_g_accums[i]) { + if (cam_g_accums[i]->name) + free(cam_g_accums[i]->name); + + free(cam_g_accums[i]); + + cam_g_accums[i] = NULL; + } + } + + cam_g_accum_index = 0; + cam_g_accum_longest_name = 0; + + free(cam_g_accums); + cam_g_accums = NULL; +} + +int cam_ta_accum_item_begin(char *name, int show, char *filename, int line) +{ + cam_ta_accum_item *accum = NULL; + int index = 0; + int name_len = 0; + struct timeval t; + + if (!cam_g_enable) + return -1; + + if (!cam_g_accums) + return 0; + + if (cam_g_accum_index == CAM_TA_MAX_ACCUM) + return -1; + + if (!name) + return -1; + + name_len = strlen(name); + if (name_len == 0) + return -1; + + /* if 'name' is new one. create new item. */ + if ((index = __get_accum_index(name)) == -1) { + accum = (cam_ta_accum_item *) malloc(sizeof(cam_ta_accum_item)); + if (!accum) + return -1; + + /* clear first. */ + memset(accum, 0, sizeof(cam_ta_accum_item)); + accum->elapsed_min = 0xFFFFFFFF; + + accum->name = (char *)malloc(name_len + 1); + if (!accum->name) { + free(accum); + accum = NULL; + return -1; + } + memset(accum->name, 0, name_len+1); + strncpy(accum->name, name, name_len); + + /* add it to list. */ + cam_g_accums[cam_g_accum_index] = accum; + cam_g_accum_index++; + + if (cam_g_accum_longest_name < name_len) + cam_g_accum_longest_name = name_len; + + } else { + accum = cam_g_accums[index]; + } + + /* verify pairs of begin, end. */ + if (accum->on_estimate) { + printf("[%s] is not 'end'ed!\n", accum->name); + accum->num_unpair++; + return -1; + } + /* get timestamp */ + gettimeofday(&t, NULL); + accum->timestamp = t.tv_sec * 1000000L + t.tv_usec; +#ifdef CAM_TA_UNIT_MSEC + accum->timestamp = + (accum->timestamp >= 1000) ? accum->timestamp / 1000 : 0; +#endif + accum->on_estimate = 1; + + if (accum->first_start == 0) { /* assum that timestamp never could be zero. */ + accum->first_start = accum->timestamp; + + if (cam_g_accum_first_time > accum->first_start) + cam_g_accum_first_time = accum->first_start; + } + + if (show) + printf("[ACCUM BEGIN] %s : %ld ---(%s:%d)\n", name, + accum->timestamp, filename, line); + + accum->num_calls++; + + return 0; +} + +int cam_ta_accum_item_end(char *name, int show, char *filename, int line) +{ + cam_ta_accum_item *accum = NULL; + long int tval = 0; + int index = 0; + struct timeval t; + + if (!cam_g_enable) + return -1; + + if (!cam_g_accums) + return 0; + + /* get time first for more accuracy. */ + gettimeofday(&t, NULL); + + if (cam_g_accum_index == CAM_TA_MAX_ACCUM) + return -1; + + if (!name) + return -1; + + if (strlen(name) == 0) + return -1; + + /* varify the 'name' is already exist. */ + if ((index = __get_accum_index(name)) == -1) { + /* printf("[%s] is not added before!\n", name); */ + return -1; + } + + accum = cam_g_accums[index]; + + /* verify pairs of begin, end. */ + if (!accum->on_estimate) { + printf("[%s] is not 'begin' yet!\n", accum->name); + accum->num_unpair++; + return -1; + } + /* get current timestamp. */ + tval = t.tv_sec * 1000000L + t.tv_usec; +#ifdef CAM_TA_UNIT_MSEC + tval = (tval >= 1000) ? tval / 1000 : 0; +#endif + + /* update last_end */ + accum->last_end = tval; + + /* make get elapsed time. */ + tval = tval - accum->timestamp; + + /* update min/max */ + accum->elapsed_max = + tval > accum->elapsed_max ? tval : accum->elapsed_max; + accum->elapsed_min = + tval < accum->elapsed_min ? tval : accum->elapsed_min; + + if (show) + printf("[ACCUM END] %s : %ld + %ld ---(%s:%d)\n", name, + accum->elapsed_accum, tval, filename, line); + + /* add elapsed time */ + accum->elapsed_accum += tval; + accum->on_estimate = 0; + + return 0; +} + +void __print_some_info(FILE *fp) +{ + if (!fp) + return; + + /* comment */ + { + fprintf(fp, "\nb~ b~ b~\n\n"); + } + + /* General infomation */ + { + time_t t_val; + char hostname[256] = { '\0', }; + struct utsname uts; + struct rusage r_usage; + + fprintf(fp, "\n[[ General info ]]\n"); + + /* time and date */ + time(&t_val); + fprintf(fp, "Date : %s", ctime(&t_val)); + + /* system */ + if (gethostname(hostname, 255) == 0 && uname(&uts) >= 0) { + fprintf(fp, "Hostname : %s\n", hostname); + fprintf(fp, "System : %s\n", uts.sysname); + fprintf(fp, "Machine : %s\n", uts.machine); + fprintf(fp, "Nodename : %s\n", uts.nodename); + fprintf(fp, "Release : %s \n", uts.release); + fprintf(fp, "Version : %s \n", uts.version); + } + /* process info. */ + fprintf(fp, "Process priority : %d\n", + getpriority(PRIO_PROCESS, getpid())); + getrusage(RUSAGE_SELF, &r_usage); + fprintf(fp, + "CPU usage : User = %ld.%06ld, System = %ld.%06ld\n", + r_usage.ru_utime.tv_sec, r_usage.ru_utime.tv_usec, + r_usage.ru_stime.tv_sec, r_usage.ru_stime.tv_usec); + + } + + /* host environment variables */ + { + extern char **environ; + char **env = environ; + + fprintf(fp, "\n[[ Host environment variables ]]\n"); + while (*env) { + fprintf(fp, "%s\n", *env); + env++; + } + } + + /* applied samsung feature */ + { +#if 0 + fprintf(fp, "\n[[ Applied samsung feature ]]\n"); +#ifdef GST_EXT_TIME_ANALYSIS + fprintf(fp, "GST_EXT_TIME_ANALYSIS\n"); +#endif +#ifdef GST_EXT_SKIP_RESCAN_REGISTRY + fprintf(fp, "GST_EXT_SKIP_RESCAN_REGISTRY\n"); +#endif +#ifdef GST_EXT_USE_TINY_REGISTRY + + fprintf(fp, "GST_EXT_USE_TINY_REGISTRY\n"); +#endif +#ifdef GST_EXT_PAD_LINK_UNCHECKED + fprintf(fp, "GST_EXT_PAD_LINK_UNCHECKED\n"); +#endif +#ifdef GST_EXT_DFBVIDEOSINK_IPP + fprintf(fp, "GST_EXT_DFBVIDEOSINK_IPP\n"); +#endif +#ifdef GST_EXT_REDUCE_PLUGIN_NUM + fprintf(fp, "GST_EXT_REDUCE_PLUGIN_NUM\n"); +#endif +#ifdef GST_EXT_USE_PDP_NETWORK + fprintf(fp, "GST_EXT_USE_PDP_NETWORK\n"); +#endif +#ifdef GST_EXT_VOLUME_WITHOUT_LIBOIL + fprintf(fp, "GST_EXT_VOLUME_WITHOUT_LIBOIL\n"); +#endif +#ifdef GST_EXT_DECODEBIN_QUEUE_ENLARGE + fprintf(fp, "GST_EXT_DECODEBIN_QUEUE_ENLARGE\n"); +#endif + + /* Camcorder releated feature */ + +#ifdef GST_EXT_NONBLOCKDQUE + fprintf(fp, "GST_EXT_NONBLOCKDQUE\n"); +#endif +#ifdef GST_EXT_RENEGOTIATION + fprintf(fp, "GST_EXT_RENEGOTIATION\n"); +#endif +#ifdef GST_EXT_MOBILECAMERA + fprintf(fp, "GST_EXT_MOBILECAMERA\n"); +#endif +#ifdef GST_EXT_VIDEOSCALE_IPP + fprintf(fp, "GST_EXT_VIDEOSCALE_IPP\n"); +#endif +#ifdef GST_EXT_ASYNC_DEV + fprintf(fp, "GST_EXT_ASYNC_DEV\n"); +#endif +#ifdef GST_EXT_AV_RECORDING + fprintf(fp, "GST_EXT_AV_RECORDING\n"); +#endif +#ifdef GST_EXT_SWITCH_CAMERA + fprintf(fp, "GST_EXT_SWITCH_CAMERA\n"); +#endif + + fprintf(fp, "\n\n"); +#endif + } + +} + +void cam_ta_accum_show_result(int direction) +{ + int i = 0; + char format[256]; + FILE *fp = stderr; + + if (!cam_g_accums) + return; + + switch (direction) { + case CAM_TA_SHOW_STDOUT: + fp = stdout; + break; + case CAM_TA_SHOW_STDERR: + fp = stderr; + break; + case CAM_TA_SHOW_FILE: + { + fp = fopen(CAM_TA_RESULT_FILE, "wt"); + if (!fp) + return; + } + } + __print_some_info(fp); + +#ifdef CAM_TA_UNIT_MSEC + snprintf(format, sizeof(format), + "[%%3d] %%-%ds | \ttotal : %%4ld\tcalls : %%3ld\tavg : %%4ld\tmin : %%4ld\tmax : %%4ld\tstart : %%4lu\tend : %%4lu\tunpair : %%3ld\n", + cam_g_accum_longest_name); + fprintf(fp, + "BEGIN RESULT ACCUM============================ : NumOfItems : %d, unit(msec)\n", + cam_g_accum_index); +#else + snprintf(format, sizeof(format), + "[%%3d] %%-%ds | \ttotal : %%ld\tcalls : %%ld\tavg : %%ld\tmin : %%ld\tmax : %%ld\tstart : %%lu\tend : %%lu\tunpair : %%ld\n", + cam_g_accum_longest_name); + fprintf(fp, + "BEGIN RESULT ACCUM============================ : NumOfItems : %d, unit(usec)\n", + cam_g_accum_index); +#endif + + for (i = 0; i < cam_g_accum_index; i++) { + /* prevent 'devide by zero' error */ + if (cam_g_accums[i]->num_calls == 0) + cam_g_accums[i]->num_calls = 1; + + 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. */ + cam_g_accums[i]->elapsed_min, + cam_g_accums[i]->elapsed_max, + cam_g_accums[i]->first_start - cam_g_accum_first_time, + cam_g_accums[i]->last_end - cam_g_accum_first_time, + cam_g_accums[i]->num_unpair); + } + fprintf(fp, "END RESULT ACCUM ============================\n"); + + if (direction == CAM_TA_SHOW_FILE) + fclose(fp); +} + +#endif /* _CAM_TA_C_ */ |