Update v2.x
This commit is contained in:
parent
3d133a782c
commit
7e3970c6ba
|
@ -103,7 +103,7 @@ public:
|
|||
|
||||
public: /* Public API functions */
|
||||
tsip_invite_event_type_t getType() const;
|
||||
twrap_media_type_t getMediaType();
|
||||
twrap_media_type_t getMediaType() const;
|
||||
const InviteSession* getSession() const;
|
||||
CallSession* takeCallSessionOwnership() const;
|
||||
MsrpSession* takeMsrpSessionOwnership() const;
|
||||
|
|
|
@ -48,6 +48,7 @@ typedef struct tdav_consumer_audiounit_s
|
|||
void* buffer;
|
||||
tsk_size_t size;
|
||||
} chunck;
|
||||
tsk_ssize_t leftBytes;
|
||||
SpeexBuffer* buffer;
|
||||
tsk_size_t size;
|
||||
tsk_mutex_handle_t* mutex;
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#include <speex/speex_buffer.h>
|
||||
#include "tinydav/audio/coreaudio/tdav_audiounit.h"
|
||||
#include "tinydav/audio/tdav_producer_audio.h"
|
||||
#include "tsk_condwait.h"
|
||||
#include "tsk_mutex.h"
|
||||
|
||||
TDAV_BEGIN_DECLS
|
||||
|
||||
|
@ -40,6 +42,8 @@ typedef struct tdav_producer_audiounit_s
|
|||
tdav_audiounit_handle_t* audioUnitHandle;
|
||||
unsigned started:1;
|
||||
unsigned paused:1;
|
||||
void* senderThreadId[1];
|
||||
tsk_condwait_handle_t* senderCondWait;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
|
@ -48,6 +52,7 @@ typedef struct tdav_producer_audiounit_s
|
|||
} chunck;
|
||||
SpeexBuffer* buffer;
|
||||
tsk_size_t size;
|
||||
tsk_mutex_handle_t* mutex;
|
||||
} ring;
|
||||
}
|
||||
tdav_producer_audiounit_t;
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#if HAVE_SPEEX_DSP && (!defined(HAVE_SPEEX_DENOISE) || HAVE_SPEEX_DENOISE)
|
||||
# error "AudioUnit already contain denoiser => Disable it"
|
||||
#endif
|
||||
// FIXME: ONLY WORKS with SpeexJitterBuffer => add ifdef elif...
|
||||
|
||||
#undef DISABLE_JITTER_BUFFER
|
||||
#define DISABLE_JITTER_BUFFER 0 // FIXME: Find why there is too delay when we use speex jitter buffer
|
||||
|
@ -66,12 +65,7 @@ static OSStatus __handle_output_buffer(void *inRefCon,
|
|||
/* int ret = */ tdav_consumer_audiounit_get(consumer, ioData->mBuffers[i].mData, ioData->mBuffers[i].mDataByteSize);
|
||||
}
|
||||
|
||||
done:
|
||||
#if !DISABLE_JITTER_BUFFER
|
||||
// alert the jitter buffer
|
||||
tdav_consumer_audio_tick(TDAV_CONSUMER_AUDIO(consumer));
|
||||
#endif
|
||||
|
||||
done:
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -84,8 +78,14 @@ static tsk_size_t tdav_consumer_audiounit_get(tdav_consumer_audiounit_t* self, v
|
|||
memset(((uint8_t*)data)+retSize, 0, (size - retSize));
|
||||
}
|
||||
#else
|
||||
retSize = (tsk_ssize_t)tdav_consumer_audio_get(TDAV_CONSUMER_AUDIO(self), data, 370/*TSK_MIN(self->ring.chunck.size, size)*/);
|
||||
printf("size=%d\n", size);
|
||||
self->ring.leftBytes += size;
|
||||
while (self->ring.leftBytes >= self->ring.chunck.size) {
|
||||
self->ring.leftBytes -= self->ring.chunck.size;
|
||||
retSize = (tsk_ssize_t)tdav_consumer_audio_get(TDAV_CONSUMER_AUDIO(self), self->ring.chunck.buffer, self->ring.chunck.size);
|
||||
tdav_consumer_audio_tick(TDAV_CONSUMER_AUDIO(self));
|
||||
speex_buffer_write(self->ring.buffer, self->ring.chunck.buffer, retSize);
|
||||
}
|
||||
retSize = speex_buffer_read(self->ring.buffer, data, size);
|
||||
if(retSize < size){
|
||||
memset(((uint8_t*)data)+retSize, 0, (size - retSize));
|
||||
}
|
||||
|
@ -131,8 +131,7 @@ static int tdav_consumer_audiounit_prepare(tmedia_consumer_t* self, const tmedia
|
|||
return -4;
|
||||
}
|
||||
else {
|
||||
uint32_t frame_duration = tdav_audiounit_handle_get_frame_duration(consumer->audioUnitHandle);
|
||||
TMEDIA_CONSUMER(consumer)->audio.ptime = frame_duration ? frame_duration : codec->plugin->audio.ptime;
|
||||
TMEDIA_CONSUMER(consumer)->audio.ptime = codec->plugin->audio.ptime;
|
||||
TMEDIA_CONSUMER(consumer)->audio.in.channels = codec->plugin->audio.channels;
|
||||
TMEDIA_CONSUMER(consumer)->audio.in.rate = codec->plugin->rate;
|
||||
|
||||
|
@ -266,16 +265,7 @@ static int tdav_consumer_audiounit_consume(tmedia_consumer_t* self, const void*
|
|||
}
|
||||
#else
|
||||
{
|
||||
tsk_mutex_lock(consumer->ring.mutex);
|
||||
speex_buffer_write(consumer->ring.buffer, (void*)buffer, size);
|
||||
int avail = speex_buffer_get_available(consumer->ring.buffer);
|
||||
while (avail >= consumer->ring.chunck.size) {
|
||||
speex_buffer_read(consumer->ring.buffer, consumer->ring.chunck.buffer, consumer->ring.chunck.size);
|
||||
tdav_consumer_audio_put(TDAV_CONSUMER_AUDIO(consumer), consumer->ring.chunck.buffer, consumer->ring.chunck.size, proto_hdr);
|
||||
avail -= consumer->ring.chunck.size;
|
||||
}
|
||||
tsk_mutex_unlock(consumer->ring.mutex);
|
||||
return 0;
|
||||
return tdav_consumer_audio_put(TDAV_CONSUMER_AUDIO(consumer), buffer, size, proto_hdr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -30,10 +30,17 @@
|
|||
# error "AudioUnit already contain denoiser => Disable it"
|
||||
#endif
|
||||
|
||||
#include <mach/mach.h>
|
||||
#import <sys/sysctl.h>
|
||||
|
||||
#include "tsk_memory.h"
|
||||
#include "tsk_thread.h"
|
||||
#include "tsk_debug.h"
|
||||
|
||||
#define kRingPacketCount +3
|
||||
#define kRingPacketCount +10
|
||||
|
||||
static void *__sender_thread(void *param);
|
||||
static int __sender_thread_set_realtime(uint32_t ptime);
|
||||
|
||||
static OSStatus __handle_input_buffer(void *inRefCon,
|
||||
AudioUnitRenderActionFlags *ioActionFlags,
|
||||
|
@ -62,22 +69,103 @@ static OSStatus __handle_input_buffer(void *inRefCon,
|
|||
inNumberFrames,
|
||||
&buffers);
|
||||
if(!status){
|
||||
// Alert the session that there is new data to send
|
||||
if(TMEDIA_PRODUCER(producer)->enc_cb.callback) {
|
||||
speex_buffer_write(producer->ring.buffer, buffers.mBuffers[0].mData, buffers.mBuffers[0].mDataByteSize);
|
||||
tsk_ssize_t avail = speex_buffer_get_available(producer->ring.buffer);
|
||||
while (avail >= producer->ring.chunck.size) {
|
||||
tsk_size_t read = speex_buffer_read(producer->ring.buffer, producer->ring.chunck.buffer, producer->ring.chunck.size);
|
||||
TMEDIA_PRODUCER(producer)->enc_cb.callback(TMEDIA_PRODUCER(producer)->enc_cb.callback_data,
|
||||
producer->ring.chunck.buffer, producer->ring.chunck.size);
|
||||
avail -= read;
|
||||
}
|
||||
}
|
||||
tsk_mutex_lock(producer->ring.mutex);
|
||||
speex_buffer_write(producer->ring.buffer, buffers.mBuffers[0].mData, buffers.mBuffers[0].mDataByteSize);
|
||||
tsk_mutex_unlock(producer->ring.mutex);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int __sender_thread_set_realtime(uint32_t ptime) {
|
||||
struct thread_time_constraint_policy policy;
|
||||
int params [2] = {CTL_HW, HW_BUS_FREQ};
|
||||
int ret;
|
||||
|
||||
// get bus frequence
|
||||
int freq_ns, freq_ms;
|
||||
size_t size = sizeof (freq_ns);
|
||||
if((ret = sysctl (params, 2, &freq_ns, &size, NULL, 0))){
|
||||
// check errno for more information
|
||||
TSK_DEBUG_ERROR("sysctl() failed with error code=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
freq_ms = freq_ns/1000;
|
||||
|
||||
/*
|
||||
* THREAD_TIME_CONSTRAINT_POLICY:
|
||||
*
|
||||
* This scheduling mode is for threads which have real time
|
||||
* constraints on their execution.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* period: This is the nominal amount of time between separate
|
||||
* processing arrivals, specified in absolute time units. A
|
||||
* value of 0 indicates that there is no inherent periodicity in
|
||||
* the computation.
|
||||
*
|
||||
* computation: This is the nominal amount of computation
|
||||
* time needed during a separate processing arrival, specified
|
||||
* in absolute time units.
|
||||
*
|
||||
* constraint: This is the maximum amount of real time that
|
||||
* may elapse from the start of a separate processing arrival
|
||||
* to the end of computation for logically correct functioning,
|
||||
* specified in absolute time units. Must be (>= computation).
|
||||
* Note that latency = (constraint - computation).
|
||||
*
|
||||
* preemptible: This indicates that the computation may be
|
||||
* interrupted, subject to the constraint specified above.
|
||||
*/
|
||||
policy.period = (ptime/2) * freq_ms; // take half of the ptime
|
||||
policy.computation = 2 * freq_ms;
|
||||
policy.constraint = 3 * freq_ms;
|
||||
policy.preemptible = true;
|
||||
|
||||
if ((ret = thread_policy_set(mach_thread_self(),
|
||||
THREAD_TIME_CONSTRAINT_POLICY, (int *)&policy,
|
||||
THREAD_TIME_CONSTRAINT_POLICY_COUNT)) != KERN_SUCCESS) {
|
||||
TSK_DEBUG_ERROR("thread_policy_set failed(period=%u,computation=%u,constraint=%u) failed with error code= %d",
|
||||
policy.period, policy.computation, policy.constraint,
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *__sender_thread(void *param)
|
||||
{
|
||||
tdav_producer_audiounit_t* producer = (tdav_producer_audiounit_t*)param;
|
||||
uint32_t ptime = TMEDIA_PRODUCER(producer)->audio.ptime;
|
||||
tsk_ssize_t avail, read;
|
||||
TSK_DEBUG_INFO("__sender_thread::ENTER");
|
||||
__sender_thread_set_realtime(TMEDIA_PRODUCER(producer)->audio.ptime);
|
||||
for (;;) {
|
||||
tsk_condwait_timedwait(producer->senderCondWait, (uint64_t)ptime);
|
||||
if(!producer->started){
|
||||
break;
|
||||
}
|
||||
if(TMEDIA_PRODUCER(producer)->enc_cb.callback) {
|
||||
tsk_mutex_lock(producer->ring.mutex);
|
||||
avail = speex_buffer_get_available(producer->ring.buffer);
|
||||
if(avail >= producer->ring.chunck.size){
|
||||
read = speex_buffer_read(producer->ring.buffer, producer->ring.chunck.buffer, producer->ring.chunck.size);
|
||||
}
|
||||
else{
|
||||
read = 0;
|
||||
}
|
||||
tsk_mutex_unlock(producer->ring.mutex);
|
||||
if(read > 0){
|
||||
TMEDIA_PRODUCER(producer)->enc_cb.callback(TMEDIA_PRODUCER(producer)->enc_cb.callback_data, producer->ring.chunck.buffer, read);
|
||||
}
|
||||
}
|
||||
else;
|
||||
}
|
||||
TSK_DEBUG_INFO("__sender_thread::EXIT");
|
||||
return tsk_null;
|
||||
}
|
||||
|
||||
/* ============ Media Producer Interface ================= */
|
||||
#define tdav_producer_audiounit_set tsk_null
|
||||
|
||||
|
@ -172,6 +260,11 @@ static int tdav_producer_audiounit_prepare(tmedia_producer_t* self, const tmedia
|
|||
TSK_DEBUG_ERROR("Failed to allocate new buffer");
|
||||
return -7;
|
||||
}
|
||||
// create mutex for ring buffer
|
||||
if(!(producer->ring.mutex = tsk_mutex_create())){
|
||||
TSK_DEBUG_ERROR("Failed to create new mutex");
|
||||
return -8;
|
||||
}
|
||||
// create ringbuffer
|
||||
producer->ring.size = kRingPacketCount * producer->ring.chunck.size;
|
||||
if(!producer->ring.buffer){
|
||||
|
@ -186,7 +279,7 @@ static int tdav_producer_audiounit_prepare(tmedia_producer_t* self, const tmedia
|
|||
}
|
||||
if(!producer->ring.buffer){
|
||||
TSK_DEBUG_ERROR("Failed to create a new ring buffer with size = %d", producer->ring.size);
|
||||
return -8;
|
||||
return -9;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,18 +302,33 @@ static int tdav_producer_audiounit_start(tmedia_producer_t* self)
|
|||
producer->paused = tsk_false;
|
||||
return tsk_false;
|
||||
}
|
||||
|
||||
int ret;
|
||||
if(producer->started){
|
||||
TSK_DEBUG_WARN("Already started");
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
int ret = tdav_audiounit_handle_start(producer->audioUnitHandle);
|
||||
ret = tdav_audiounit_handle_start(producer->audioUnitHandle);
|
||||
if(ret){
|
||||
TSK_DEBUG_ERROR("tdav_audiounit_handle_start failed with error code=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
producer->started = tsk_true;
|
||||
|
||||
// create conditional variable
|
||||
if(!(producer->senderCondWait = tsk_condwait_create())){
|
||||
TSK_DEBUG_ERROR("Failed to create conditional variable");
|
||||
return -2;
|
||||
}
|
||||
// start the reader thread
|
||||
ret = tsk_thread_create(&producer->senderThreadId[0], __sender_thread, producer);
|
||||
if(ret){
|
||||
TSK_DEBUG_ERROR("Failed to start the sender thread. error code=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
TSK_DEBUG_INFO("AudioUnit producer started");
|
||||
return 0;
|
||||
}
|
||||
|
@ -253,10 +361,18 @@ static int tdav_producer_audiounit_stop(tmedia_producer_t* self)
|
|||
int ret = tdav_audiounit_handle_stop(producer->audioUnitHandle);
|
||||
if(ret){
|
||||
TSK_DEBUG_ERROR("tdav_audiounit_handle_stop failed with error code=%d", ret);
|
||||
return ret;
|
||||
// do not return even if failed => we MUST stop the thread!
|
||||
}
|
||||
}
|
||||
producer->started = tsk_false;
|
||||
// signal
|
||||
if(producer->senderCondWait){
|
||||
tsk_condwait_broadcast(producer->senderCondWait);
|
||||
}
|
||||
// stop thread
|
||||
if(producer->senderThreadId[0]){
|
||||
tsk_thread_join(&(producer->senderThreadId[0]));
|
||||
}
|
||||
TSK_DEBUG_INFO("AudioUnit producer stoppped");
|
||||
return 0;
|
||||
}
|
||||
|
@ -290,10 +406,16 @@ static tsk_object_t* tdav_producer_audiounit_dtor(tsk_object_t * self)
|
|||
if (producer->audioUnitHandle) {
|
||||
tdav_audiounit_handle_destroy(&producer->audioUnitHandle);
|
||||
}
|
||||
if(producer->ring.mutex){
|
||||
tsk_mutex_destroy(&producer->ring.mutex);
|
||||
}
|
||||
TSK_FREE(producer->ring.chunck.buffer);
|
||||
if(producer->ring.buffer){
|
||||
speex_buffer_destroy(producer->ring.buffer);
|
||||
}
|
||||
if(producer->senderCondWait){
|
||||
tsk_condwait_destroy(&producer->senderCondWait);
|
||||
}
|
||||
/* deinit base */
|
||||
tdav_producer_audio_deinit(TDAV_PRODUCER_AUDIO(producer));
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ trtp_rtcp_sdes_chunck_t* trtp_rtcp_sdes_chunck_deserialize(const void* data, tsk
|
|||
pdata+=4;
|
||||
while(pdata<pend){
|
||||
if((item = trtp_rtcp_sdes_item_deserialize(pdata, (pend-pdata)))){
|
||||
tsk_list_push_back_data(chunck->items, &item);
|
||||
tsk_list_push_back_data(chunck->items, (void**)&item);
|
||||
pdata+=trtp_rtcp_sdes_item_get_size(item);
|
||||
}
|
||||
else{
|
||||
|
|
|
@ -174,8 +174,7 @@ int tsk_condwait_timedwait(tsk_condwait_handle_t* handle, uint64_t ms)
|
|||
tsk_condwait_t *condwait = (tsk_condwait_t*)handle;
|
||||
|
||||
#if TSK_UNDER_WINDOWS
|
||||
if((ret = WaitForSingleObject(condwait->pcond, (DWORD)ms)) != WAIT_OBJECT_0)
|
||||
{
|
||||
if((ret = WaitForSingleObject(condwait->pcond, (DWORD)ms)) != WAIT_OBJECT_0){
|
||||
if(ret == TIMED_OUT){
|
||||
/* TSK_DEBUG_INFO("WaitForSingleObject function timedout: %d", ret); */
|
||||
}
|
||||
|
@ -185,8 +184,7 @@ int tsk_condwait_timedwait(tsk_condwait_handle_t* handle, uint64_t ms)
|
|||
return ((ret == TIMED_OUT) ? 0 : ret);
|
||||
}
|
||||
#else
|
||||
if(condwait && condwait->mutex)
|
||||
{
|
||||
if(condwait && condwait->mutex){
|
||||
struct timespec ts = {0, 0};
|
||||
struct timeval tv = {0, 0};
|
||||
/*int rc =*/ tsk_gettimeofday(&tv, 0);
|
||||
|
@ -234,8 +232,7 @@ int tsk_condwait_signal(tsk_condwait_handle_t* handle)
|
|||
if(condwait && condwait->mutex){
|
||||
tsk_mutex_lock(condwait->mutex);
|
||||
|
||||
if(ret = pthread_cond_signal(condwait->pcond))
|
||||
{
|
||||
if(ret = pthread_cond_signal(condwait->pcond)){
|
||||
TSK_DEBUG_ERROR("pthread_cond_signal function failed: %d", ret);
|
||||
}
|
||||
tsk_mutex_unlock(condwait->mutex);
|
||||
|
@ -257,17 +254,14 @@ int tsk_condwait_broadcast(tsk_condwait_handle_t* handle)
|
|||
tsk_condwait_t *condwait = (tsk_condwait_t*)handle;
|
||||
|
||||
#if TSK_UNDER_WINDOWS
|
||||
if(ret = ((SetEvent(condwait->pcond) && ResetEvent(condwait->pcond)) ? 0 : -1))
|
||||
{
|
||||
if(ret = ((SetEvent(condwait->pcond) && ResetEvent(condwait->pcond)) ? 0 : -1)){
|
||||
ret = GetLastError();
|
||||
TSK_DEBUG_ERROR("SetEvent function failed: %d", ret);
|
||||
}
|
||||
#else
|
||||
if(condwait && condwait->mutex)
|
||||
{
|
||||
if(condwait && condwait->mutex){
|
||||
tsk_mutex_lock(condwait->mutex);
|
||||
if(ret = pthread_cond_broadcast(condwait->pcond))
|
||||
{
|
||||
if(ret = pthread_cond_broadcast(condwait->pcond)){
|
||||
TSK_DEBUG_ERROR("pthread_cond_broadcast function failed: %d", ret);
|
||||
}
|
||||
tsk_mutex_unlock(condwait->mutex);
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/**@defgroup tsk_thread_group Utility functions for threading.
|
||||
*/
|
||||
|
||||
|
@ -74,6 +76,44 @@ int tsk_thread_create(void** tid, void *(*start) (void *), void *arg)
|
|||
#endif
|
||||
}
|
||||
|
||||
/**@ingroup tsk_thread_group
|
||||
*/
|
||||
int tsk_thread_set_priority(void* tid, int32_t priority)
|
||||
{
|
||||
#if TSK_UNDER_WINDOWS
|
||||
// SetPriorityClass()
|
||||
TSK_DEBUG_ERROR("Not implemented");
|
||||
return -1;
|
||||
#else
|
||||
struct sched_param sp;
|
||||
int ret;
|
||||
if(!tid){
|
||||
TSK_DEBUG_ERROR("Invalid parameter");
|
||||
return -1;
|
||||
}
|
||||
memset(&sp, 0, sizeof(struct sched_param));
|
||||
sp.sched_priority = priority;
|
||||
if ((ret = pthread_setschedparam(*((pthread_t*)tid), SCHED_RR, &sp))) {
|
||||
TSK_DEBUG_ERROR("Failed to change priority to %d with error code=%d", priority, ret);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**@ingroup tsk_thread_group
|
||||
*/
|
||||
int tsk_thread_set_priority_2(int32_t priority)
|
||||
{
|
||||
#if TSK_UNDER_WINDOWS
|
||||
TSK_DEBUG_ERROR("Not implemented");
|
||||
return -1;
|
||||
#else
|
||||
pthread_t thread = pthread_self();
|
||||
return tsk_thread_set_priority(&thread, priority);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**@ingroup tsk_thread_group
|
||||
* Join a thread.
|
||||
* @param tid Pthread handle to the target thread.
|
||||
|
|
|
@ -36,6 +36,8 @@ TSK_BEGIN_DECLS
|
|||
|
||||
TINYSAK_API void tsk_thread_sleep(uint64_t ms);
|
||||
TINYSAK_API int tsk_thread_create(void** tid, void *(*start) (void *), void *arg);
|
||||
TINYSAK_API int tsk_thread_set_priority(void* tid, int32_t priority);
|
||||
TINYSAK_API int tsk_thread_set_priority_2(int32_t priority);
|
||||
TINYSAK_API int tsk_thread_join(void** tid);
|
||||
|
||||
TSK_END_DECLS
|
||||
|
|
|
@ -43,6 +43,12 @@
|
|||
#endif
|
||||
|
||||
#include <time.h>
|
||||
#if defined __APPLE__ && 0
|
||||
# include <mach/mach.h>
|
||||
# include <mach/mach_time.h>
|
||||
|
||||
static mach_timebase_info_data_t __apple_timebase_info = {0, 0};
|
||||
#endif
|
||||
|
||||
/**@defgroup tsk_time_group Datetime functions.
|
||||
*/
|
||||
|
@ -141,10 +147,15 @@ uint64_t tsk_time_epoch()
|
|||
{
|
||||
#if TSK_UNDER_WINDOWS
|
||||
return (uint64_t)timeGetTime();
|
||||
#elif HAVE_CLOCK_GETTIME
|
||||
#elif HAVE_CLOCK_GETTIME || _POSIX_TIMERS > 0
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return (((uint64_t)ts.tv_sec)*(uint64_t)1000) + (((uint64_t)ts.tv_nsec)/(uint64_t)1000000);
|
||||
#elif defined(__APPLE__) && 0
|
||||
if(__apple_timebase_info.denom == 0){
|
||||
(void) mach_timebase_info(&__apple_timebase_info);
|
||||
}
|
||||
return (mach_absolute_time() * __apple_timebase_info.numer / __apple_timebase_info.denom)*1e-6;
|
||||
#else
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
|
@ -152,3 +163,23 @@ uint64_t tsk_time_epoch()
|
|||
#endif
|
||||
}
|
||||
|
||||
int tsk_time_epoch_2(struct timespec *ts)
|
||||
{
|
||||
#if HAVE_CLOCK_GETTIME || _POSIX_TIMERS > 0
|
||||
clock_gettime(CLOCK_MONOTONIC, ts);
|
||||
#elif defined(__APPLE__) && 0
|
||||
if(__apple_timebase_info.denom == 0){
|
||||
(void) mach_timebase_info(&__apple_timebase_info);
|
||||
}
|
||||
uint64_t nano = mach_absolute_time() * __apple_timebase_info.numer / __apple_timebase_info.denom;
|
||||
ts->tv_sec = nano * 1e-9;
|
||||
ts->tv_nsec = nano - (ts->tv_sec * 1e9);
|
||||
#else
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, tsk_null);
|
||||
ts->tv_sec = tv.tv_sec;
|
||||
ts->tv_nsec = tv.tv_usec * 1000;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ TSK_BEGIN_DECLS
|
|||
//#if defined(__SYMBIAN32__) || ANDROID /* Forward declaration */
|
||||
struct timeval;
|
||||
struct timezone;
|
||||
struct timespec;
|
||||
//#endif
|
||||
|
||||
/**@ingroup tsk_time_group
|
||||
|
@ -47,6 +48,8 @@ struct timezone;
|
|||
TINYSAK_API int tsk_gettimeofday(struct timeval *tv, struct timezone *tz);
|
||||
TINYSAK_API uint64_t tsk_time_get_ms(struct timeval *tv);
|
||||
TINYSAK_API uint64_t tsk_time_epoch();
|
||||
TINYSAK_API int tsk_time_epoch_2(struct timespec *ts);
|
||||
|
||||
|
||||
/**@ingroup tsk_time_group
|
||||
* Gets the number of milliseconds since the EPOCH.
|
||||
|
|
Loading…
Reference in New Issue