Destroy audioUnit instance when call is put on hold to allow multiple audio sessions

This commit is contained in:
System Administrator 2016-10-21 04:05:06 +02:00
parent a4973c7fe3
commit 6b9f5f831a
85 changed files with 435 additions and 349 deletions

0
thirdparties/common/include/openssl/aes.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/asn1.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/asn1_mac.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/asn1t.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/bio.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/blowfish.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/bn.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/buffer.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/camellia.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/cast.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/cmac.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/cms.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/comp.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/conf.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/conf_api.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/crypto.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/des.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/des_old.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/dh.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/dsa.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/dso.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/dtls1.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/e_os2.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/ebcdic.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/ec.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/ecdh.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/ecdsa.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/engine.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/err.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/evp.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/hmac.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/idea.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/krb5_asn.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/kssl.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/lhash.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/md4.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/md5.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/mdc2.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/modes.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/obj_mac.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/objects.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/ocsp.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/opensslconf.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/opensslv.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/ossl_typ.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/pem.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/pem2.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/pkcs12.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/pkcs7.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/pqueue.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/rand.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/rc2.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/rc4.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/ripemd.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/rsa.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/safestack.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/seed.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/sha.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/srp.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/srtp.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/ssl.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/ssl2.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/ssl23.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/ssl3.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/stack.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/symhacks.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/tls1.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/ts.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/txt_db.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/ui.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/ui_compat.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/whrlpool.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/x509.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/x509_vfy.h Normal file → Executable file
View File

0
thirdparties/common/include/openssl/x509v3.h Normal file → Executable file
View File

0
thirdparties/iphone/lib/universal/libcrypto.a Normal file → Executable file
View File

0
thirdparties/iphone/lib/universal/libssl.a Normal file → Executable file
View File

0
thirdparties/mac/lib/universal/libcrypto.a Normal file → Executable file
View File

0
thirdparties/mac/lib/universal/libssl.a Normal file → Executable file
View File

View File

@ -48,8 +48,8 @@ typedef void* tdav_audiounit_handle_t;
tdav_audiounit_handle_t* tdav_audiounit_handle_create(uint64_t session_id);
AudioComponentInstance tdav_audiounit_handle_get_instance(tdav_audiounit_handle_t* self);
int tdav_audiounit_handle_signal_consumer_prepared(tdav_audiounit_handle_t* self);
int tdav_audiounit_handle_signal_producer_prepared(tdav_audiounit_handle_t* self);
int tdav_audiounit_handle_signal_consumer_ready(tdav_audiounit_handle_t* self);
int tdav_audiounit_handle_signal_producer_ready(tdav_audiounit_handle_t* self);
int tdav_audiounit_handle_start(tdav_audiounit_handle_t* self);
uint32_t tdav_audiounit_handle_get_frame_duration(tdav_audiounit_handle_t* self);
int tdav_audiounit_handle_configure(tdav_audiounit_handle_t* self, tsk_bool_t consumer, uint32_t ptime, AudioStreamBasicDescription* audioFormat);

View File

@ -42,6 +42,7 @@ typedef struct tdav_consumer_audiounit_s {
tdav_audiounit_handle_t* audioUnitHandle;
unsigned started:1;
unsigned paused:1;
unsigned ready:1;
struct {
struct {

View File

@ -41,7 +41,8 @@ typedef struct tdav_producer_audiounit_s {
tdav_audiounit_handle_t* audioUnitHandle;
unsigned started:1;
unsigned paused:1;
unsigned muted;
unsigned ready:1;
unsigned muted:1;
struct {
struct {

View File

@ -60,7 +60,7 @@ typedef struct tdav_audiounit_instance_s {
struct {
unsigned consumer:1;
unsigned producer:1;
} prepared;
} ready;
unsigned started:1;
unsigned interrupted:1;
@ -75,7 +75,7 @@ typedef tsk_list_t tdav_audiounit_instances_L_t;
static AudioComponent __audioSystem = tsk_null;
static tdav_audiounit_instances_L_t* __audioUnitInstances = tsk_null;
static int _tdav_audiounit_handle_signal_xxx_prepared(tdav_audiounit_handle_t* self, tsk_bool_t consumer)
static int _tdav_audiounit_handle_signal_xxx_ready(tdav_audiounit_handle_t* self, tsk_bool_t consumer)
{
tdav_audiounit_instance_t* inst = (tdav_audiounit_instance_t*)self;
if(!inst || !inst->audioUnit) {
@ -86,17 +86,17 @@ static int _tdav_audiounit_handle_signal_xxx_prepared(tdav_audiounit_handle_t* s
tsk_safeobj_lock(inst);
if (consumer) {
inst->prepared.consumer = tsk_true;
inst->ready.consumer = tsk_true;
}
else {
inst->prepared.producer = tsk_true;
inst->ready.producer = tsk_true;
}
OSStatus status;
// For iOS we are using full-duplex AudioUnit and we wait for both consumer and producer to be prepared
#if TARGET_OS_IPHONE
if(inst->prepared.consumer && inst->prepared.producer)
if(inst->ready.consumer && inst->ready.producer)
#endif
{
status = AudioUnitInitialize(inst->audioUnit);
@ -184,14 +184,14 @@ AudioComponentInstance tdav_audiounit_handle_get_instance(tdav_audiounit_handle_
return ((tdav_audiounit_instance_t*)self)->audioUnit;
}
int tdav_audiounit_handle_signal_consumer_prepared(tdav_audiounit_handle_t* self)
int tdav_audiounit_handle_signal_consumer_ready(tdav_audiounit_handle_t* self)
{
return _tdav_audiounit_handle_signal_xxx_prepared(self, tsk_true);
return _tdav_audiounit_handle_signal_xxx_ready(self, tsk_true);
}
int tdav_audiounit_handle_signal_producer_prepared(tdav_audiounit_handle_t* self)
int tdav_audiounit_handle_signal_producer_ready(tdav_audiounit_handle_t* self)
{
return _tdav_audiounit_handle_signal_xxx_prepared(self, tsk_false);
return _tdav_audiounit_handle_signal_xxx_ready(self, tsk_false);
}
int tdav_audiounit_handle_start(tdav_audiounit_handle_t* self)
@ -204,6 +204,7 @@ int tdav_audiounit_handle_start(tdav_audiounit_handle_t* self)
}
tsk_safeobj_lock(inst);
if (inst->ready.consumer && inst->ready.producer) {
status = (OSStatus)tdav_apple_enable_audio();
if (status == noErr) {
if ((!inst->started || inst->interrupted) && (status = AudioOutputUnitStart(inst->audioUnit))) {
@ -217,6 +218,10 @@ int tdav_audiounit_handle_start(tdav_audiounit_handle_t* self)
if (inst->started) {
inst->interrupted = 0;
}
}
else {
TSK_DEBUG_INFO("AudioUnit producer(%d) or consumer(%d) not ready yet ...delaying start", (int)inst->ready.producer, (int)inst->ready.consumer);
}
tsk_safeobj_unlock(inst);
return status ? -2 : 0;
}
@ -359,6 +364,8 @@ int tdav_audiounit_handle_stop(tdav_audiounit_handle_t* self)
TSK_DEBUG_ERROR("AudioOutputUnitStop failed with status=%ld", (signed long)status);
}
inst->started = (status == noErr ? tsk_false : tsk_true);
inst->ready.consumer = tsk_false;
inst->ready.producer = tsk_false;
tsk_safeobj_unlock(inst);
return (status != noErr) ? -2 : 0;
}

View File

@ -39,6 +39,8 @@
static tsk_size_t tdav_consumer_audiounit_get(tdav_consumer_audiounit_t* self, void* data, tsk_size_t size);
static int tdav_consumer_audiounit_pause(tmedia_consumer_t* self);
static int tdav_consumer_audiounit_resume(tmedia_consumer_t* self);
static int tdav_consumer_audiounit_init(tmedia_consumer_t* self);
static int tdav_consumer_audiounit_deinit(tmedia_consumer_t* self);
static OSStatus __handle_output_buffer(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
@ -121,6 +123,139 @@ int tdav_consumer_audiounit_set(tmedia_consumer_t* self, const tmedia_param_t* p
}
static int tdav_consumer_audiounit_prepare(tmedia_consumer_t* self, const tmedia_codec_t* codec)
{
tdav_consumer_audiounit_t* consumer = (tdav_consumer_audiounit_t*)self;
if (!consumer || !codec || !codec->plugin) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
// Initialize the decoder parameters without allocating AudioUnit resourses
TMEDIA_CONSUMER(consumer)->audio.ptime = TMEDIA_CODEC_PTIME_AUDIO_DECODING(codec);
TMEDIA_CONSUMER(consumer)->audio.in.channels = TMEDIA_CODEC_CHANNELS_AUDIO_DECODING(codec);
TMEDIA_CONSUMER(consumer)->audio.in.rate = TMEDIA_CODEC_RATE_DECODING(codec);
TSK_DEBUG_INFO("AudioUnit consumer prepared (ptime=%d, channels=%d, rate=%d)",
(int)TMEDIA_CONSUMER(consumer)->audio.ptime,
(int)TMEDIA_CONSUMER(consumer)->audio.in.channels,
(int)TMEDIA_CONSUMER(consumer)->audio.in.rate);
return 0;
}
static int tdav_consumer_audiounit_start(tmedia_consumer_t* self)
{
tdav_consumer_audiounit_t* consumer = (tdav_consumer_audiounit_t*)self;
if(!consumer) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (consumer->paused) {
consumer->paused = tsk_false;
}
if (consumer->started) {
TSK_DEBUG_WARN("Already started");
return 0;
}
else {
int ret;
// Initialize the consumer if not already done
if (!consumer->ready) {
ret = tdav_consumer_audiounit_init(self);
if (ret) {
tdav_consumer_audiounit_deinit(self);
TSK_DEBUG_ERROR("tdav_consumer_audiounit_init failed with error code=%d", ret);
return ret;
}
}
// Start the handle (will wait until producer is ready)
ret = tdav_audiounit_handle_start(consumer->audioUnitHandle);
if (ret) {
tdav_consumer_audiounit_deinit(self);
TSK_DEBUG_ERROR("tdav_audiounit_handle_start failed with error code=%d", ret);
return ret;
}
}
consumer->started = tsk_true;
TSK_DEBUG_INFO("AudioUnit consumer started");
return 0;
}
static int tdav_consumer_audiounit_consume(tmedia_consumer_t* self, const void* buffer, tsk_size_t size, const tsk_object_t* proto_hdr)
{
tdav_consumer_audiounit_t* consumer = (tdav_consumer_audiounit_t*)self;
if(!consumer || !buffer || !size) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
#if DISABLE_JITTER_BUFFER
{
if(consumer->ring.buffer) {
tsk_mutex_lock(consumer->ring.mutex);
speex_buffer_write(consumer->ring.buffer, (void*)buffer, size);
tsk_mutex_unlock(consumer->ring.mutex);
return 0;
}
return -2;
}
#else
{
return tdav_consumer_audio_put(TDAV_CONSUMER_AUDIO(consumer), buffer, size, proto_hdr);
}
#endif
}
static int tdav_consumer_audiounit_pause(tmedia_consumer_t* self)
{
tdav_consumer_audiounit_t* consumer = (tdav_consumer_audiounit_t*)self;
if(!consumer) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (!consumer->paused) {
tdav_consumer_audiounit_deinit(self);
consumer->paused = tsk_true;
}
TSK_DEBUG_INFO("AudioUnit consumer paused");
return 0;
}
static int tdav_consumer_audiounit_resume(tmedia_consumer_t* self)
{
tdav_consumer_audiounit_t* consumer = (tdav_consumer_audiounit_t*)self;
if(!consumer) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (consumer->paused) {
consumer->paused = tsk_false; // *must* be before start()
if (!consumer->started) {
int ret = tdav_consumer_audiounit_start(self);
if (ret) {
TSK_DEBUG_ERROR("Failed to stop the consumer");
return ret;
}
}
}
TSK_DEBUG_INFO("AudioUnit consumer resumed");
return 0;
}
static int tdav_consumer_audiounit_stop(tmedia_consumer_t* self)
{
int ret = tdav_consumer_audiounit_deinit(self);
if (ret) {
TSK_DEBUG_ERROR("Failed to stop the consumer");
return ret;
}
TSK_DEBUG_INFO("AudioUnit consumer stoppped");
return 0;
}
static int tdav_consumer_audiounit_init(tmedia_consumer_t* self)
{
static UInt32 flagOne = 1;
AudioStreamBasicDescription audioFormat;
@ -129,14 +264,21 @@ static int tdav_consumer_audiounit_prepare(tmedia_consumer_t* self, const tmedia
tdav_consumer_audiounit_t* consumer = (tdav_consumer_audiounit_t*)self;
OSStatus status = noErr;
if(!consumer || !codec || !codec->plugin) {
if (!consumer) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (consumer->ready) {
TSK_DEBUG_INFO("AudioUnit consumer already initialized");
return 0;
}
// create handle if not already done
if (!consumer->audioUnitHandle) {
if(!(consumer->audioUnitHandle = tdav_audiounit_handle_create(TMEDIA_CONSUMER(consumer)->session_id))) {
TSK_DEBUG_ERROR("Failed to get audio unit instance for session with id=%lld", TMEDIA_CONSUMER(consumer)->session_id);
return -3;
return -2;
}
}
@ -187,10 +329,6 @@ static int tdav_consumer_audiounit_prepare(tmedia_consumer_t* self, const tmedia
#endif
TMEDIA_CONSUMER(consumer)->audio.ptime = TMEDIA_CODEC_PTIME_AUDIO_DECODING(codec);
TMEDIA_CONSUMER(consumer)->audio.in.channels = TMEDIA_CODEC_CHANNELS_AUDIO_DECODING(codec);
TMEDIA_CONSUMER(consumer)->audio.in.rate = TMEDIA_CODEC_RATE_DECODING(codec);
TSK_DEBUG_INFO("AudioUnit consumer: in.channels=%d, out.channles=%d, in.rate=%d, out.rate=%d, ptime=%d",
TMEDIA_CONSUMER(consumer)->audio.in.channels,
TMEDIA_CONSUMER(consumer)->audio.out.channels,
@ -281,135 +419,45 @@ static int tdav_consumer_audiounit_prepare(tmedia_consumer_t* self, const tmedia
// return -6;
//}
TSK_DEBUG_INFO("AudioUnit consumer prepared");
return tdav_audiounit_handle_signal_consumer_prepared(consumer->audioUnitHandle);
if (tdav_audiounit_handle_signal_consumer_ready(consumer->audioUnitHandle)) {
TSK_DEBUG_ERROR("tdav_audiounit_handle_signal_consumer_ready failed");
return -10;
}
static int tdav_consumer_audiounit_start(tmedia_consumer_t* self)
{
tdav_consumer_audiounit_t* consumer = (tdav_consumer_audiounit_t*)self;
consumer->ready = tsk_true;
if(!consumer) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if(consumer->paused) {
consumer->paused = tsk_false;
}
if(consumer->started) {
TSK_DEBUG_WARN("Already started");
return 0;
}
else {
int ret = tdav_audiounit_handle_start(consumer->audioUnitHandle);
if(ret) {
TSK_DEBUG_ERROR("tdav_audiounit_handle_start failed with error code=%d", ret);
return ret;
}
}
consumer->started = tsk_true;
TSK_DEBUG_INFO("AudioUnit consumer started");
TSK_DEBUG_INFO("AudioUnit consumer initialized and ready");
return 0;
}
static int tdav_consumer_audiounit_consume(tmedia_consumer_t* self, const void* buffer, tsk_size_t size, const tsk_object_t* proto_hdr)
{
tdav_consumer_audiounit_t* consumer = (tdav_consumer_audiounit_t*)self;
if(!consumer || !buffer || !size) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
#if DISABLE_JITTER_BUFFER
{
if(consumer->ring.buffer) {
tsk_mutex_lock(consumer->ring.mutex);
speex_buffer_write(consumer->ring.buffer, (void*)buffer, size);
tsk_mutex_unlock(consumer->ring.mutex);
return 0;
}
return -2;
}
#else
{
return tdav_consumer_audio_put(TDAV_CONSUMER_AUDIO(consumer), buffer, size, proto_hdr);
}
#endif
}
static int tdav_consumer_audiounit_pause(tmedia_consumer_t* self)
int tdav_consumer_audiounit_deinit(tmedia_consumer_t* self)
{
tdav_consumer_audiounit_t* consumer = (tdav_consumer_audiounit_t*)self;
if(!consumer) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (!consumer->paused) {
consumer->paused = tsk_true;
// Stop
if (consumer->started) {
int ret = tdav_audiounit_handle_stop(consumer->audioUnitHandle);
if (ret) {
TSK_DEBUG_ERROR("tdav_audiounit_handle_stop failed with error code=%d", ret);
}
consumer->started = false;
}
}
TSK_DEBUG_INFO("AudioUnit consumer paused");
return 0;
}
static int tdav_consumer_audiounit_resume(tmedia_consumer_t* self)
{
tdav_consumer_audiounit_t* consumer = (tdav_consumer_audiounit_t*)self;
if(!consumer) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (consumer->paused) {
consumer->paused = tsk_false;
if (!consumer->started) {
int ret = tdav_audiounit_handle_start(consumer->audioUnitHandle);
if(ret) {
TSK_DEBUG_ERROR("tdav_audiounit_handle_start failed with error code=%d", ret);
}
consumer->started = true;
}
}
TSK_DEBUG_INFO("AudioUnit consumer resumed");
return 0;
}
static int tdav_consumer_audiounit_stop(tmedia_consumer_t* self)
{
tdav_consumer_audiounit_t* consumer = (tdav_consumer_audiounit_t*)self;
if(!consumer) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if(!consumer->started) {
TSK_DEBUG_INFO("Not started");
return 0;
}
else {
int ret = tdav_audiounit_handle_stop(consumer->audioUnitHandle);
if(ret) {
TSK_DEBUG_ERROR("tdav_audiounit_handle_stop failed with error code=%d", ret);
return ret;
}
consumer->started = tsk_false;
}
// Destroy handle (will be re-created by the next start)
#if TARGET_OS_IPHONE
//https://devforums.apple.com/thread/118595
if (consumer->audioUnitHandle) {
tdav_audiounit_handle_destroy(&consumer->audioUnitHandle);
}
#endif
consumer->ready = tsk_false;
consumer->paused = tsk_false;
TSK_DEBUG_INFO("AudioUnit consumer deinitialized");
consumer->started = tsk_false;
TSK_DEBUG_INFO("AudioUnit consumer stoppped");
return 0;
}
//
@ -432,14 +480,7 @@ static tsk_object_t* tdav_consumer_audiounit_dtor(tsk_object_t * self)
tdav_consumer_audiounit_t *consumer = self;
if(consumer) {
/* deinit self */
// Stop the consumer if not done
if(consumer->started) {
tdav_consumer_audiounit_stop(self);
}
// destroy handle
if(consumer->audioUnitHandle) {
tdav_audiounit_handle_destroy(&consumer->audioUnitHandle);
}
tdav_consumer_audiounit_deinit(TMEDIA_CONSUMER(self));
TSK_FREE(consumer->ring.chunck.buffer);
if(consumer->ring.buffer) {
speex_buffer_destroy(consumer->ring.buffer);

View File

@ -37,6 +37,8 @@
static int tdav_producer_audiounit_pause(tmedia_producer_t* self);
static int tdav_producer_audiounit_resume(tmedia_producer_t* self);
static int tdav_producer_audiounit_init(tmedia_producer_t* self);
static int tdav_producer_audiounit_deinit(tmedia_producer_t* self);
static OSStatus __handle_input_buffer(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
@ -104,6 +106,118 @@ int tdav_producer_audiounit_set(tmedia_producer_t* self, const tmedia_param_t* p
}
static int tdav_producer_audiounit_prepare(tmedia_producer_t* self, const tmedia_codec_t* codec)
{
tdav_producer_audiounit_t* producer = (tdav_producer_audiounit_t*)self;
if (!producer || !codec || !codec->plugin) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
TMEDIA_PRODUCER(producer)->audio.channels = TMEDIA_CODEC_CHANNELS_AUDIO_ENCODING(codec);
TMEDIA_PRODUCER(producer)->audio.rate = TMEDIA_CODEC_RATE_ENCODING(codec);
TMEDIA_PRODUCER(producer)->audio.ptime = TMEDIA_CODEC_PTIME_AUDIO_ENCODING(codec);
TSK_DEBUG_INFO("AudioUnit producer prepared(channels=%d, rate=%d, ptime=%d)",
(int)TMEDIA_PRODUCER(producer)->audio.channels,
(int)TMEDIA_PRODUCER(producer)->audio.rate,
(int)TMEDIA_PRODUCER(producer)->audio.ptime);
return 0;
}
static int tdav_producer_audiounit_start(tmedia_producer_t* self)
{
tdav_producer_audiounit_t* producer = (tdav_producer_audiounit_t*)self;
if (!producer) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (producer->paused) {
producer->paused = tsk_false;
return tsk_false;
}
int ret;
if (producer->started) {
TSK_DEBUG_WARN("Already started");
return 0;
}
else {
// Initialize the consumer if not already done
if (!producer->ready) {
ret = tdav_producer_audiounit_init(self);
if (ret) {
tdav_producer_audiounit_deinit(self);
TSK_DEBUG_ERROR("tdav_producer_audiounit_init failed with error code=%d", ret);
return ret;
}
}
// Start handle
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;
// apply parameters (because could be lost when the producer is restarted -handle recreated-)
ret = tdav_audiounit_handle_mute(producer->audioUnitHandle, producer->muted);
TSK_DEBUG_INFO("AudioUnit producer started");
return 0;
}
static int tdav_producer_audiounit_pause(tmedia_producer_t* self)
{
tdav_producer_audiounit_t* producer = (tdav_producer_audiounit_t*)self;
if (!producer) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (!producer->paused) {
tdav_producer_audiounit_deinit(self);
producer->paused = tsk_true;
}
TSK_DEBUG_INFO("AudioUnit producer paused");
return 0;
}
static int tdav_producer_audiounit_resume(tmedia_producer_t* self)
{
tdav_producer_audiounit_t* producer = (tdav_producer_audiounit_t*)self;
if (!producer) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (producer->paused) {
producer->paused = tsk_false; // *must* be before start()
if (!producer->started) {
int ret = tdav_producer_audiounit_start(self);
if (ret) {
TSK_DEBUG_ERROR("Failed to stop the consumer");
return ret;
}
}
}
TSK_DEBUG_INFO("AudioUnit producer resumed");
return 0;
}
static int tdav_producer_audiounit_stop(tmedia_producer_t* self)
{
int ret = tdav_producer_audiounit_deinit(self);
if (ret) {
TSK_DEBUG_ERROR("Failed to stop the consumer");
return ret;
}
TSK_DEBUG_INFO("AudioUnit producer stoppped");
return 0;
}
static int tdav_producer_audiounit_init(tmedia_producer_t* self)
{
static UInt32 flagOne = 1;
UInt32 param;
@ -115,10 +229,16 @@ static int tdav_producer_audiounit_prepare(tmedia_producer_t* self, const tmedia
AudioStreamBasicDescription audioFormat;
AudioStreamBasicDescription deviceFormat;
if(!producer || !codec || !codec->plugin) {
if (!producer) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (producer->ready) {
TSK_DEBUG_INFO("AudioUnit consumer already initialized");
return 0;
}
if (!producer->audioUnitHandle) {
if(!(producer->audioUnitHandle = tdav_audiounit_handle_create(TMEDIA_PRODUCER(producer)->session_id))) {
TSK_DEBUG_ERROR("Failed to get audio unit instance for session with id=%lld", TMEDIA_PRODUCER(producer)->session_id);
@ -174,11 +294,6 @@ static int tdav_producer_audiounit_prepare(tmedia_producer_t* self, const tmedia
}
#endif /* TARGET_OS_MAC */
/* codec should have ptime */
TMEDIA_PRODUCER(producer)->audio.channels = TMEDIA_CODEC_CHANNELS_AUDIO_ENCODING(codec);
TMEDIA_PRODUCER(producer)->audio.rate = TMEDIA_CODEC_RATE_ENCODING(codec);
TMEDIA_PRODUCER(producer)->audio.ptime = TMEDIA_CODEC_PTIME_AUDIO_ENCODING(codec);
TSK_DEBUG_INFO("AudioUnit producer: channels=%d, rate=%d, ptime=%d",
TMEDIA_PRODUCER(producer)->audio.channels,
TMEDIA_PRODUCER(producer)->audio.rate,
@ -267,7 +382,7 @@ static int tdav_producer_audiounit_prepare(tmedia_producer_t* self, const tmedia
}
else {
int ret;
if((ret = speex_buffer_resize(producer->ring.buffer, producer->ring.size)) < 0) {
if((ret = speex_buffer_resize(producer->ring.buffer, (int)producer->ring.size)) < 0) {
TSK_DEBUG_ERROR("speex_buffer_resize(%d) failed with error code=%d", (int)producer->ring.size, ret);
return ret;
}
@ -281,115 +396,44 @@ static int tdav_producer_audiounit_prepare(tmedia_producer_t* self, const tmedia
}
}
TSK_DEBUG_INFO("AudioUnit producer prepared");
return tdav_audiounit_handle_signal_producer_prepared(producer->audioUnitHandle);;
if (tdav_audiounit_handle_signal_producer_ready(producer->audioUnitHandle)) {
TSK_DEBUG_ERROR("tdav_audiounit_handle_signal_producer_ready failed");
return -10;
}
static int tdav_producer_audiounit_start(tmedia_producer_t* self)
{
tdav_producer_audiounit_t* producer = (tdav_producer_audiounit_t*)self;
producer->ready = tsk_true;
if(!producer) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if(producer->paused) {
producer->paused = tsk_false;
return tsk_false;
}
int ret;
if(producer->started) {
TSK_DEBUG_WARN("Already started");
return 0;
}
else {
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;
// apply parameters (because could be lost when the producer is restarted -handle recreated-)
ret = tdav_audiounit_handle_mute(producer->audioUnitHandle, producer->muted);
TSK_DEBUG_INFO("AudioUnit producer started");
TSK_DEBUG_INFO("AudioUnit producer initialized");
return 0;
}
static int tdav_producer_audiounit_pause(tmedia_producer_t* self)
static int tdav_producer_audiounit_deinit(tmedia_producer_t* self)
{
tdav_producer_audiounit_t* producer = (tdav_producer_audiounit_t*)self;
if (!producer) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (!producer->paused) {
producer->paused = tsk_true;
// Stop
if (producer->started) {
int ret = tdav_audiounit_handle_stop(producer->audioUnitHandle);
if (ret) {
TSK_DEBUG_ERROR("tdav_audiounit_handle_stop failed with error code=%d", ret);
// do not return even if failed => we MUST stop the thread!
}
producer->started = false;
}
}
TSK_DEBUG_INFO("AudioUnit producer paused");
return 0;
}
static int tdav_producer_audiounit_resume(tmedia_producer_t* self)
{
tdav_producer_audiounit_t* producer = (tdav_producer_audiounit_t*)self;
if(!producer) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (producer->paused) {
if (!producer->started) {
int ret = tdav_audiounit_handle_start(producer->audioUnitHandle);
if(ret) {
TSK_DEBUG_ERROR("tdav_audiounit_handle_start failed with error code=%d", ret);
// do not return even if failed => we MUST stop the thread!
}
}
producer->paused = false;
producer->started = true;
}
TSK_DEBUG_INFO("AudioUnit producer resumed");
return 0;
}
static int tdav_producer_audiounit_stop(tmedia_producer_t* self)
{
tdav_producer_audiounit_t* producer = (tdav_producer_audiounit_t*)self;
if(!producer) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if(!producer->started) {
TSK_DEBUG_INFO("Not started");
return 0;
}
else {
int ret = tdav_audiounit_handle_stop(producer->audioUnitHandle);
if(ret) {
TSK_DEBUG_ERROR("tdav_audiounit_handle_stop failed with error code=%d", ret);
// do not return even if failed => we MUST stop the thread!
producer->started = tsk_false;
}
// Destroy handle (will be re-created by the next start)
#if TARGET_OS_IPHONE
//https://devforums.apple.com/thread/118595
if (producer->audioUnitHandle) {
tdav_audiounit_handle_destroy(&producer->audioUnitHandle);
}
#endif
}
producer->started = tsk_false;
TSK_DEBUG_INFO("AudioUnit producer stoppped");
producer->ready = tsk_false;
producer->paused = tsk_false;
TSK_DEBUG_INFO("AudioUnit producer deinitialized");
return 0;
}
@ -413,15 +457,7 @@ static tsk_object_t* tdav_producer_audiounit_dtor(tsk_object_t * self)
{
tdav_producer_audiounit_t *producer = self;
if(producer) {
// Stop the producer if not done
if(producer->started) {
tdav_producer_audiounit_stop(self);
}
// Free all buffers and dispose the queue
if (producer->audioUnitHandle) {
tdav_audiounit_handle_destroy(&producer->audioUnitHandle);
}
tdav_producer_audiounit_deinit(TMEDIA_PRODUCER(self));
TSK_FREE(producer->ring.chunck.buffer);
if(producer->ring.buffer) {
speex_buffer_destroy(producer->ring.buffer);