clock_thread.c
来自「基于sip协议的网络电话源码」· C语言 代码 · 共 266 行
C
266 行
/* $Id: clock_thread.c 974 2007-02-19 01:13:53Z bennylp $ *//* * Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <pjmedia/clock.h>#include <pjmedia/errno.h>#include <pj/assert.h>#include <pj/lock.h>#include <pj/os.h>#include <pj/pool.h>/* * Implementation of media clock with OS thread. */struct pjmedia_clock{ pj_timestamp freq; pj_timestamp interval; pj_timestamp next_tick; pj_timestamp timestamp; unsigned samples_per_frame; unsigned options; pjmedia_clock_callback *cb; void *user_data; pj_thread_t *thread; pj_bool_t running; pj_bool_t quitting; pj_lock_t *lock;};static int clock_thread(void *arg);/* * Create media clock. */PJ_DEF(pj_status_t) pjmedia_clock_create( pj_pool_t *pool, unsigned clock_rate, unsigned samples_per_frame, unsigned options, pjmedia_clock_callback *cb, void *user_data, pjmedia_clock **p_clock){ pjmedia_clock *clock; pj_status_t status; PJ_ASSERT_RETURN(pool && clock_rate && samples_per_frame && p_clock, PJ_EINVAL); clock = pj_pool_alloc(pool, sizeof(pjmedia_clock)); status = pj_get_timestamp_freq(&clock->freq); if (status != PJ_SUCCESS) return status; clock->interval.u64 = samples_per_frame * clock->freq.u64 / clock_rate; clock->next_tick.u64 = 0; clock->timestamp.u64 = 0; clock->samples_per_frame = samples_per_frame; clock->options = options; clock->cb = cb; clock->user_data = user_data; clock->thread = NULL; clock->running = PJ_FALSE; clock->quitting = PJ_FALSE; /* I don't think we need a mutex, so we'll use null. */ status = pj_lock_create_null_mutex(pool, "clock", &clock->lock); if (status != PJ_SUCCESS) return status; status = pj_thread_create(pool, "clock", &clock_thread, clock, 0, 0, &clock->thread); if (status != PJ_SUCCESS) { pj_lock_destroy(clock->lock); return status; } *p_clock = clock; return PJ_SUCCESS;}/* * Start the clock. */PJ_DEF(pj_status_t) pjmedia_clock_start(pjmedia_clock *clock){ pj_timestamp now; pj_status_t status; PJ_ASSERT_RETURN(clock != NULL, PJ_EINVAL); if (clock->running) return PJ_SUCCESS; status = pj_get_timestamp(&now); if (status != PJ_SUCCESS) return status; pj_lock_acquire(clock->lock); clock->next_tick.u64 = now.u64 + clock->interval.u64; clock->running = PJ_TRUE; pj_lock_release(clock->lock); return status;}/* * Stop the clock. */PJ_DEF(pj_status_t) pjmedia_clock_stop(pjmedia_clock *clock){ PJ_ASSERT_RETURN(clock != NULL, PJ_EINVAL); clock->running = PJ_FALSE; return PJ_SUCCESS;}/* * Poll the clock. */PJ_DEF(pj_bool_t) pjmedia_clock_wait( pjmedia_clock *clock, pj_bool_t wait, pj_timestamp *ts){ pj_timestamp now; pj_status_t status; PJ_ASSERT_RETURN(clock != NULL, PJ_FALSE); PJ_ASSERT_RETURN((clock->options & PJMEDIA_CLOCK_NO_ASYNC) != 0, PJ_FALSE); PJ_ASSERT_RETURN(clock->running, PJ_FALSE); status = pj_get_timestamp(&now); if (status != PJ_SUCCESS) return PJ_FALSE; /* Wait for the next tick to happen */ if (now.u64 < clock->next_tick.u64) { unsigned msec; if (!wait) return PJ_FALSE; msec = pj_elapsed_msec(&now, &clock->next_tick); pj_thread_sleep(msec); } /* Call callback, if any */ if (clock->cb) (*clock->cb)(&clock->timestamp, clock->user_data); /* Report timestamp to caller */ if (ts) ts->u64 = clock->timestamp.u64; /* Increment timestamp */ clock->timestamp.u64 += clock->samples_per_frame; /* Calculate next tick */ clock->next_tick.u64 += clock->interval.u64; /* Done */ return PJ_TRUE;}/* * Clock thread */static int clock_thread(void *arg){ pj_timestamp now; pjmedia_clock *clock = arg; /* Get the first tick */ pj_get_timestamp(&clock->next_tick); clock->next_tick.u64 += clock->interval.u64; while (!clock->quitting) { pj_get_timestamp(&now); /* Wait for the next tick to happen */ if (now.u64 < clock->next_tick.u64) { unsigned msec; msec = pj_elapsed_msec(&now, &clock->next_tick); pj_thread_sleep(msec); } /* Skip if not running */ if (!clock->running) continue; pj_lock_acquire(clock->lock); /* Call callback, if any */ if (clock->cb) (*clock->cb)(&clock->timestamp, clock->user_data); /* Increment timestamp */ clock->timestamp.u64 += clock->samples_per_frame; /* Calculate next tick */ clock->next_tick.u64 += clock->interval.u64; pj_lock_release(clock->lock); } return 0;}/* * Destroy the clock. */PJ_DEF(pj_status_t) pjmedia_clock_destroy(pjmedia_clock *clock){ PJ_ASSERT_RETURN(clock != NULL, PJ_EINVAL); clock->running = PJ_FALSE; clock->quitting = PJ_TRUE; if (clock->thread) { pj_thread_join(clock->thread); pj_thread_destroy(clock->thread); clock->thread = NULL; } if (clock->lock) { pj_lock_destroy(clock->lock); clock->lock = NULL; } return PJ_SUCCESS;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?