static tsk_size_t tdav_consumer_audiounit_get(tdav_consumer_audiounit_t* self, void* data, tsk_size_t size)
{
	tsk_ssize_t retSize = 0;
	
#if DISABLE_JITTER_BUFFER
	retSize = speex_buffer_read(self->ring.buffer, data, size);
	if(retSize < size){
		memset(((uint8_t*)data)+retSize, 0, (size - retSize));
	}
#else
	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);
	}
	// IMPORTANT: looks like there is a bug in speex: continously trying to read more than avail
	// many times can corrupt the buffer. At least on OS X 1.5
	if(speex_buffer_get_available(self->ring.buffer) >= size){
		retSize = speex_buffer_read(self->ring.buffer, data, size);
	}
	else{
		memset(data, 0, size);
	}
#endif

	return retSize;
}
Ejemplo n.º 2
0
static OSStatus __handle_input_buffer(void *inRefCon, 
                                  AudioUnitRenderActionFlags *ioActionFlags, 
                                  const AudioTimeStamp *inTimeStamp, 
                                  UInt32 inBusNumber, 
                                  UInt32 inNumberFrames, 
                                  AudioBufferList *ioData) {
	OSStatus status = noErr;
	tdav_producer_audiounit_t* producer = (tdav_producer_audiounit_t*)inRefCon;
	
	// holder
	AudioBuffer buffer;
	buffer.mData =  tsk_null;
	buffer.mDataByteSize = 0;
	buffer.mNumberChannels = TMEDIA_PRODUCER(producer)->audio.channels;
	
	// list of holders
	AudioBufferList buffers;
	buffers.mNumberBuffers = 1;
	buffers.mBuffers[0] = buffer;
	
	// render to get frames from the system
	status = AudioUnitRender(tdav_audiounit_handle_get_instance(producer->audioUnitHandle), 
							 ioActionFlags, 
							 inTimeStamp, 
							 inBusNumber, 
							 inNumberFrames, 
							 &buffers);
	if(status == 0){
		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;
}
Ejemplo n.º 3
0
static OSStatus __handle_input_buffer(void *inRefCon, 
                                  AudioUnitRenderActionFlags *ioActionFlags, 
                                  const AudioTimeStamp *inTimeStamp, 
                                  UInt32 inBusNumber, 
                                  UInt32 inNumberFrames, 
                                  AudioBufferList *ioData) {
	OSStatus status = noErr;
	tdav_producer_audiounit_t* producer = (tdav_producer_audiounit_t*)inRefCon;
	
	// holder
	AudioBuffer buffer;
	buffer.mData =  tsk_null;
	buffer.mDataByteSize = 0;
	buffer.mNumberChannels = TMEDIA_PRODUCER(producer)->audio.channels;
	
	// list of holders
	AudioBufferList buffers;
	buffers.mNumberBuffers = 1;
	buffers.mBuffers[0] = buffer;
	
	// render to get frames from the system
	status = AudioUnitRender(tdav_audiounit_handle_get_instance(producer->audioUnitHandle), 
							 ioActionFlags, 
							 inTimeStamp, 
							 inBusNumber, 
							 inNumberFrames, 
							 &buffers);
	if(status == 0){
        // must not be done on async thread: doing it gives bad audio quality when audio+video call is done with CPU consuming codec (e.g. speex or g729)
		speex_buffer_write(producer->ring.buffer, buffers.mBuffers[0].mData, buffers.mBuffers[0].mDataByteSize);
        int avail = speex_buffer_get_available(producer->ring.buffer);
        while (producer->started && avail >= producer->ring.chunck.size) {
            avail -= speex_buffer_read(producer->ring.buffer, (void*)producer->ring.chunck.buffer, (int)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);
        }
	}
	
    return status;
}
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
}