/** Copyright 2015 Rockchip Electronics Co. LTD** Licensed under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0** 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.*/#define MODULE_TAG "mpp_time"#include <errno.h>#include <string.h>#include <sys/timerfd.h>#include <sys/epoll.h>#include "mpp_mem.h"#include "mpp_time.h"#include "mpp_debug.h"#include "mpp_common.h"#include "mpp_thread.h"#if _WIN32#include <sys/types.h>#include <sys/timeb.h>RK_S64 mpp_time(){struct timeb tb;ftime(&tb);return ((RK_S64)tb.time * 1000 + (RK_S64)tb.millitm) * 1000;}#else#include <time.h>RK_S64 mpp_time(){struct timespec time = {0, 0};clock_gettime(CLOCK_MONOTONIC, &time);return (RK_S64)time.tv_sec * 1000000 + (RK_S64)time.tv_nsec / 1000;}#endifvoid mpp_time_diff(RK_S64 start, RK_S64 end, RK_S64 limit, const char *fmt){RK_S64 diff = end - start;if (diff >= limit)mpp_dbg(MPP_DBG_TIMING, "%s timing %lld us\n", fmt, diff);}typedef struct MppClockImpl_t {const char *check;char name[16];RK_U32 enable;RK_S64 base;RK_S64 time;RK_S64 sum;RK_S64 count;} MppClockImpl;static const char *clock_name = "mpp_clock";MPP_RET check_is_mpp_clock(void *clock){if (clock && ((MppClockImpl*)clock)->check == clock_name)return MPP_OK;mpp_err_f("pointer %p failed on check\n", clock);mpp_abort();return MPP_NOK;}MppClock mpp_clock_get(const char *name){MppClockImpl *impl = mpp_calloc(MppClockImpl, 1);if (impl) {impl->check = clock_name;snprintf(impl->name, sizeof(impl->name) - 1, name, NULL);} elsempp_err_f("malloc failed\n");return impl;}void mpp_clock_put(MppClock clock){if (NULL == clock || check_is_mpp_clock(clock)) {mpp_err_f("invalid clock %p\n", clock);return ;}mpp_free(clock);}void mpp_clock_enable(MppClock clock, RK_U32 enable){if (NULL == clock || check_is_mpp_clock(clock)) {mpp_err_f("invalid clock %p\n", clock);} else {MppClockImpl *p = (MppClockImpl *)clock;p->enable = (enable) ? (1) : (0);}}RK_S64 mpp_clock_start(MppClock clock){if (NULL == clock || check_is_mpp_clock(clock)) {mpp_err_f("invalid clock %p\n", clock);return 0;}MppClockImpl *p = (MppClockImpl *)clock;if (!p->enable)return 0;p->base = mpp_time();p->time = 0;return p->base;}RK_S64 mpp_clock_pause(MppClock clock){if (NULL == clock || check_is_mpp_clock(clock)) {mpp_err_f("invalid clock %p\n", clock);return 0;}MppClockImpl *p = (MppClockImpl *)clock;if (!p->enable)return 0;RK_S64 time = mpp_time();if (!p->time) {// first pause after startp->sum += time - p->base;p->count++;}p->time = time;return p->time - p->base;}RK_S64 mpp_clock_reset(MppClock clock){if (NULL == clock || check_is_mpp_clock(clock)) {mpp_err_f("invalid clock %p\n", clock);} else {MppClockImpl *p = (MppClockImpl *)clock;p->base = 0;p->time = 0;p->sum = 0;p->count = 0;}return 0;}RK_S64 mpp_clock_get_sum(MppClock clock){if (NULL == clock || check_is_mpp_clock(clock)) {mpp_err_f("invalid clock %p\n", clock);return 0;}MppClockImpl *p = (MppClockImpl *)clock;return (p->enable) ? (p->sum) : (0);}RK_S64 mpp_clock_get_count(MppClock clock){if (NULL == clock || check_is_mpp_clock(clock)) {mpp_err_f("invalid clock %p\n", clock);return 0;}MppClockImpl *p = (MppClockImpl *)clock;return (p->enable) ? (p->count) : (0);}const char *mpp_clock_get_name(MppClock clock){if (NULL == clock || check_is_mpp_clock(clock)) {mpp_err_f("invalid clock %p\n", clock);return NULL;}MppClockImpl *p = (MppClockImpl *)clock;return p->name;}typedef struct MppTimerImpl_t {const char *check;char name[16];RK_S32 enabled;RK_S32 initial;RK_S32 interval;RK_S32 timer_fd;RK_S32 epoll_fd;MppThread *thd;MppThreadFunc func;void *ctx;} MppTimerImpl;static const char *timer_name = "mpp_timer";MPP_RET check_is_mpp_timer(void *timer){if (timer && ((MppTimerImpl*)timer)->check == timer_name)return MPP_OK;mpp_err_f("pointer %p failed on check\n", timer);mpp_abort();return MPP_NOK;}static void *mpp_timer_thread(void *ctx){struct itimerspec ts;RK_S32 ret = 0;MppTimerImpl *impl = (MppTimerImpl *)ctx;MppThread *thd = impl->thd;RK_S32 timer_fd = impl->timer_fd;// first expire timets.it_value.tv_sec = impl->initial / 1000;ts.it_value.tv_nsec = (impl->initial % 1000) * 1000;// last expire timets.it_interval.tv_sec = impl->interval / 1000;ts.it_interval.tv_nsec = (impl->interval % 1000) * 1000 * 1000;ret = timerfd_settime(timer_fd, 0, &ts, NULL);if (ret < 0) {mpp_err("timerfd_settime error, Error:[%d:%s]", errno, strerror(errno));return NULL;}while (1) {if (MPP_THREAD_RUNNING != thd->get_status())break;struct epoll_event events;memset(&events, 0, sizeof(events));/* wait epoll event */RK_S32 fd_cnt = epoll_wait(impl->epoll_fd, &events, 1, 500);if (fd_cnt && (events.events & EPOLLIN) && (events.data.fd == timer_fd)) {RK_U64 exp = 0;ssize_t cnt = read(timer_fd, &exp, sizeof(exp));mpp_assert(cnt == sizeof(exp));impl->func(impl->ctx);}}return NULL;}MppTimer mpp_timer_get(const char *name){RK_S32 timer_fd = -1;RK_S32 epoll_fd = -1;MppTimerImpl *impl = NULL;do {struct epoll_event event;impl = mpp_calloc(MppTimerImpl, 1);if (NULL == impl) {mpp_err_f("malloc failed\n");break;}timer_fd = timerfd_create(CLOCK_REALTIME, 0);if (timer_fd < 0)break;epoll_fd = epoll_create(1);if (epoll_fd < 0)break;memset(&event, 0, sizeof(event));event.data.fd = timer_fd;event.events = EPOLLIN | EPOLLET;if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, timer_fd, &event) < 0)break;impl->timer_fd = timer_fd;impl->epoll_fd = epoll_fd;/* default 1 second (1000ms) looper */impl->initial = 1000;impl->interval = 1000;impl->check = timer_name;snprintf(impl->name, sizeof(impl->name) - 1, name, NULL);return impl;} while (0);mpp_err_f("failed to create timer\n");if (impl) {mpp_free(impl);impl = NULL;}if (timer_fd >= 0) {close(timer_fd);timer_fd = -1;}if (epoll_fd >= 0) {close(epoll_fd);epoll_fd = -1;}return NULL;}void mpp_timer_set_callback(MppTimer timer, MppThreadFunc func, void *ctx){if (NULL == timer || check_is_mpp_timer(timer)) {mpp_err_f("invalid timer %p\n", timer);return ;}if (NULL == func) {mpp_err_f("invalid NULL callback\n");return ;}MppTimerImpl *impl = (MppTimerImpl *)timer;impl->func = func;impl->ctx = ctx;}void mpp_timer_set_timing(MppTimer timer, RK_S32 initial, RK_S32 interval){if (NULL == timer || check_is_mpp_timer(timer)) {mpp_err_f("invalid timer %p\n", timer);return ;}MppTimerImpl *impl = (MppTimerImpl *)timer;impl->initial = initial;impl->interval = interval;}void mpp_timer_set_enable(MppTimer timer, RK_S32 enable){if (NULL == timer || check_is_mpp_timer(timer)) {mpp_err_f("invalid timer %p\n", timer);return ;}MppTimerImpl *impl = (MppTimerImpl *)timer;if (NULL == impl->func || impl->initial < 0 || impl->interval < 0) {mpp_err_f("invalid func %p initial %d interval %d\n",impl->func, impl->initial, impl->interval);return ;}if (enable) {if (!impl->enabled && NULL == impl->thd) {MppThread *thd = new MppThread(mpp_timer_thread, impl, impl->name);if (thd) {impl->thd = thd;impl->enabled = 1;thd->start();}}} else {if (impl->enabled && impl->thd) {impl->thd->stop();impl->enabled = 0;}}}void mpp_timer_put(MppTimer timer){if (NULL == timer || check_is_mpp_timer(timer)) {mpp_err_f("invalid timer %p\n", timer);return ;}MppTimerImpl *impl = (MppTimerImpl *)timer;if (impl->enabled)mpp_timer_set_enable(timer, 0);if (impl->timer_fd >= 0) {close(impl->timer_fd);impl->timer_fd = -1;}if (impl->epoll_fd >= 0) {close(impl->epoll_fd);impl->epoll_fd = -1;}if (impl->thd) {delete impl->thd;impl->thd = NULL;}if (impl) {mpp_free(impl);impl = NULL;}}AutoTiming::AutoTiming(const char *name){mStart = mpp_time();mName = name;}AutoTiming::~AutoTiming(){mEnd = mpp_time();mpp_log("%s timing %lld us\n", mName, mEnd - mStart);}#define STOPWATCH_TRACE_STR_LEN 64typedef struct MppStopwatchNode_t {char event[STOPWATCH_TRACE_STR_LEN];RK_S64 time;} MppStopwatchNode;typedef struct MppStopwatchImpl_t {const char *check;char name[STOPWATCH_TRACE_STR_LEN];RK_S32 max_count;RK_S32 filled_count;RK_S32 show_on_exit;RK_S32 log_len;RK_S64 time_elipsed;MppStopwatchNode *nodes;} MppStopwatchImpl;static const char *stopwatch_name = "mpp_stopwatch";MPP_RET check_is_mpp_stopwatch(void *stopwatch){if (stopwatch && ((MppStopwatchImpl*)stopwatch)->check == stopwatch_name)return MPP_OK;mpp_err_f("pointer %p failed on check\n", stopwatch);mpp_abort();return MPP_NOK;}MppStopwatch mpp_stopwatch_get(const char *name){MppStopwatchImpl *impl = mpp_calloc(MppStopwatchImpl, 1);MppStopwatchNode *nodes = mpp_calloc(MppStopwatchNode, 8);if (impl && nodes) {impl->check = stopwatch_name;snprintf(impl->name, sizeof(impl->name) - 1, name, NULL);impl->nodes = nodes;impl->max_count = 8;} else {mpp_err_f("malloc failed\n");MPP_FREE(impl);MPP_FREE(nodes);}return impl;}void mpp_stopwatch_set_show_on_exit(MppStopwatch stopwatch, RK_S32 show_on_exit){if (NULL == stopwatch || check_is_mpp_stopwatch(stopwatch)) {mpp_err_f("invalid stopwatch %p\n", stopwatch);return ;}MppStopwatchImpl *impl = (MppStopwatchImpl *)stopwatch;impl->show_on_exit = show_on_exit;}void mpp_stopwatch_record(MppStopwatch stopwatch, const char *event){/* do not print noisy log */if (NULL == stopwatch)return ;if (check_is_mpp_stopwatch(stopwatch)) {mpp_err_f("invalid stopwatch %p on %s\n", stopwatch, event);return ;}MppStopwatchImpl *impl = (MppStopwatchImpl *)stopwatch;if (impl->filled_count >= impl->max_count) {RK_S32 max_count = impl->max_count * 2;MppStopwatchNode *nodes = mpp_realloc(impl->nodes, MppStopwatchNode,max_count);if (nodes) {impl->nodes = nodes;impl->max_count = max_count;}}if (impl->filled_count < impl->max_count) {MppStopwatchNode *node = impl->nodes + impl->filled_count;node->time = mpp_time();if (event) {RK_S32 len = snprintf(node->event, sizeof(node->event) - 1,"%s", event);if (len > impl->log_len)impl->log_len = len;}impl->filled_count++;}}void mpp_stopwatch_put(MppStopwatch stopwatch){if (NULL == stopwatch || check_is_mpp_stopwatch(stopwatch)) {mpp_err_f("invalid stopwatch %p\n", stopwatch);return ;}MppStopwatchImpl *impl = (MppStopwatchImpl *)stopwatch;if (impl->show_on_exit && impl->nodes && impl->filled_count) {MppStopwatchNode *node = impl->nodes;RK_S64 last_time = node->time;RK_S32 i;char fmt[32];snprintf(fmt, sizeof(fmt) - 1, "%%s %%-%ds: %%6.2f\n", impl->log_len);node++;for (i = 1; i < impl->filled_count; i++) {mpp_log(fmt, impl->name, node->event,(float)(node->time - last_time) / 1000);last_time = node->time;node++;}}MPP_FREE(impl->nodes);MPP_FREE(impl);}RK_S64 mpp_stopwatch_elapsed_time(MppStopwatch stopwatch){if (NULL == stopwatch || check_is_mpp_stopwatch(stopwatch)) {mpp_err_f("invalid stopwatch %p\n", stopwatch);return 0;}MppStopwatchImpl *impl = (MppStopwatchImpl *)stopwatch;if (impl->filled_count < 2)return 0;RK_S64 base_time = impl->nodes[0].time;RK_S64 curr_time = impl->nodes[impl->filled_count - 1].time;RK_S64 elapsed_time = curr_time - base_time;return elapsed_time;}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。