Update v2.x

This commit is contained in:
bossiel 2011-05-04 20:31:42 +00:00
parent 3d133a782c
commit 7e3970c6ba
11 changed files with 239 additions and 51 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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
}

View File

@ -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));
}

View File

@ -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{

View File

@ -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);

View File

@ -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.

View File

@ -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

View File

@ -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;
}

View File

@ -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.