summaryrefslogtreecommitdiff
path: root/pjmedia/src/pjmedia/clock_thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'pjmedia/src/pjmedia/clock_thread.c')
-rw-r--r--pjmedia/src/pjmedia/clock_thread.c124
1 files changed, 118 insertions, 6 deletions
diff --git a/pjmedia/src/pjmedia/clock_thread.c b/pjmedia/src/pjmedia/clock_thread.c
index 245db00c..5875450f 100644
--- a/pjmedia/src/pjmedia/clock_thread.c
+++ b/pjmedia/src/pjmedia/clock_thread.c
@@ -23,6 +23,84 @@
#include <pj/lock.h>
#include <pj/os.h>
#include <pj/pool.h>
+#include <pj/string.h>
+#include <pj/compat/high_precision.h>
+
+/* API: Init clock source */
+PJ_DEF(pj_status_t) pjmedia_clock_src_init( pjmedia_clock_src *clocksrc,
+ pjmedia_type media_type,
+ unsigned clock_rate,
+ unsigned ptime_usec )
+{
+ PJ_ASSERT_RETURN(clocksrc, PJ_EINVAL);
+
+ clocksrc->media_type = media_type;
+ clocksrc->clock_rate = clock_rate;
+ clocksrc->ptime_usec = ptime_usec;
+ pj_set_timestamp32(&clocksrc->timestamp, 0, 0);
+ pj_get_timestamp(&clocksrc->last_update);
+
+ return PJ_SUCCESS;
+}
+
+/* API: Update clock source */
+PJ_DECL(pj_status_t) pjmedia_clock_src_update( pjmedia_clock_src *clocksrc,
+ const pj_timestamp *timestamp )
+{
+ PJ_ASSERT_RETURN(clocksrc, PJ_EINVAL);
+
+ if (timestamp)
+ pj_memcpy(&clocksrc->timestamp, timestamp, sizeof(pj_timestamp));
+ pj_get_timestamp(&clocksrc->last_update);
+
+ return PJ_SUCCESS;
+}
+
+/* API: Get clock source's current timestamp */
+PJ_DEF(pj_status_t)
+pjmedia_clock_src_get_current_timestamp( const pjmedia_clock_src *clocksrc,
+ pj_timestamp *timestamp)
+{
+ pj_timestamp now;
+ unsigned elapsed_ms;
+
+ PJ_ASSERT_RETURN(clocksrc && timestamp, PJ_EINVAL);
+
+ pj_get_timestamp(&now);
+ elapsed_ms = pj_elapsed_msec(&clocksrc->last_update, &now);
+ pj_memcpy(timestamp, &clocksrc->timestamp, sizeof(pj_timestamp));
+ pj_add_timestamp32(timestamp, elapsed_ms * clocksrc->clock_rate / 1000);
+
+ return PJ_SUCCESS;
+}
+
+/* API: Get clock source's time (in ms) */
+PJ_DEF(pj_uint32_t)
+pjmedia_clock_src_get_time_msec( const pjmedia_clock_src *clocksrc )
+{
+ pj_timestamp ts;
+
+ pjmedia_clock_src_get_current_timestamp(clocksrc, &ts);
+
+#if PJ_HAS_INT64
+ if (ts.u64 > 0x3FFFFFFFFFFFFFUL)
+ return (pj_uint32_t)(ts.u64 / clocksrc->clock_rate * 1000);
+ else
+ return (pj_uint32_t)(ts.u64 * 1000 / clocksrc->clock_rate);
+#elif PJ_HAS_FLOATING_POINT
+ return (pj_uint32_t)((1.0 * ts.u32.hi * 0xFFFFFFFFUL + ts.u32.lo)
+ * 1000.0 / clocksrc->clock_rate);
+#else
+ if (ts.u32.lo > 0x3FFFFFUL)
+ return (pj_uint32_t)(0xFFFFFFFFUL / clocksrc->clock_rate * ts.u32.hi
+ * 1000UL + ts.u32.lo / clocksrc->clock_rate *
+ 1000UL);
+ else
+ return (pj_uint32_t)(0xFFFFFFFFUL / clocksrc->clock_rate * ts.u32.hi
+ * 1000UL + ts.u32.lo * 1000UL /
+ clocksrc->clock_rate);
+#endif
+}
/*
@@ -50,6 +128,7 @@ struct pjmedia_clock
static int clock_thread(void *arg);
#define MAX_JUMP_MSEC 500
+#define USEC_IN_SEC (pj_uint64_t)1000000
/*
* Create media clock.
@@ -63,25 +142,42 @@ PJ_DEF(pj_status_t) pjmedia_clock_create( pj_pool_t *pool,
void *user_data,
pjmedia_clock **p_clock)
{
+ pjmedia_clock_param param;
+
+ param.usec_interval = (unsigned)(samples_per_frame * USEC_IN_SEC /
+ channel_count / clock_rate);
+ param.clock_rate = clock_rate;
+ return pjmedia_clock_create2(pool, &param, options, cb,
+ user_data, p_clock);
+}
+
+PJ_DEF(pj_status_t) pjmedia_clock_create2(pj_pool_t *pool,
+ const pjmedia_clock_param *param,
+ 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);
+ PJ_ASSERT_RETURN(pool && param->usec_interval && param->clock_rate &&
+ p_clock, PJ_EINVAL);
clock = PJ_POOL_ALLOC_T(pool, pjmedia_clock);
-
status = pj_get_timestamp_freq(&clock->freq);
if (status != PJ_SUCCESS)
return status;
- clock->interval.u64 = samples_per_frame * clock->freq.u64 /
- channel_count / clock_rate;
+ clock->interval.u64 = param->usec_interval * clock->freq.u64 /
+ USEC_IN_SEC;
clock->next_tick.u64 = 0;
clock->timestamp.u64 = 0;
clock->max_jump = MAX_JUMP_MSEC * clock->freq.u64 / 1000;
- clock->timestamp_inc = samples_per_frame / channel_count;
+ clock->timestamp_inc = (unsigned)(param->usec_interval *
+ param->clock_rate /
+ USEC_IN_SEC);
clock->options = options;
clock->cb = cb;
clock->user_data = user_data;
@@ -149,6 +245,22 @@ PJ_DEF(pj_status_t) pjmedia_clock_stop(pjmedia_clock *clock)
}
+/*
+ * Update the clock.
+ */
+PJ_DEF(pj_status_t) pjmedia_clock_modify(pjmedia_clock *clock,
+ const pjmedia_clock_param *param)
+{
+ clock->interval.u64 = param->usec_interval * clock->freq.u64 /
+ USEC_IN_SEC;
+ clock->timestamp_inc = (unsigned)(param->usec_interval *
+ param->clock_rate /
+ USEC_IN_SEC);
+
+ return PJ_SUCCESS;
+}
+
+
/* Calculate next tick */
PJ_INLINE(void) clock_calc_next_tick(pjmedia_clock *clock,
pj_timestamp *now)