예제 #1
0
static u32 gf_ar_fill_output(void *ptr, char *buffer, u32 buffer_size)
{
	u32 written;
	GF_AudioRenderer *ar = (GF_AudioRenderer *) ptr;
	if (!ar->need_reconfig) {
		u32 delay_ms = ar->disable_resync ?	0 : ar->audio_delay;

		if (ar->filter_chain.enable_filters) {
			char *ptr = buffer;
			u32 res = buffer_size;
			written = 0;
			delay_ms += ar->filter_chain.delay_ms;

			while (buffer_size) {
				u32 to_copy;
				if (!ar->nb_used) {
					u32 nb_bytes;

					/*fill input block*/
					nb_bytes = gf_mixer_get_output(ar->mixer, ar->filter_chain.tmp_block1, ar->filter_chain.min_block_size, delay_ms);
					if (!nb_bytes) 
						return written;

					/*delay used to check for late frames - we only use it on the first call to gf_mixer_get_output()*/
					delay_ms = 0;

					ar->nb_filled = gf_afc_process(&ar->filter_chain, nb_bytes);
					if (!ar->nb_filled) continue;
				}
				to_copy = ar->nb_filled - ar->nb_used;
				if (to_copy>buffer_size) to_copy = buffer_size;
				memcpy(ptr, ar->filter_chain.tmp_block1 + ar->nb_used, to_copy);
				ptr += to_copy;
				buffer_size -= to_copy;
				written += to_copy;
				ar->nb_used += to_copy;
				if (ar->nb_used==ar->nb_filled) ar->nb_used = 0;
			}
			assert(res==written);
		} else {
			written = gf_mixer_get_output(ar->mixer, buffer, buffer_size, delay_ms);
		}
		if (ar->audio_listeners) {
			u32 k=0;
			GF_AudioListener *l;
			while ((l = gf_list_enum(ar->audio_listeners, &k))) {
				l->on_audio_frame(l->udta, buffer, written, gf_sc_ar_get_clock(ar), delay_ms);
			}
		}
		return written;
	}
	return 0;
}
예제 #2
0
static char *audiobuffer_fetch_frame(void *callback, u32 *size, u32 audio_delay_ms)
{
	u32 blockAlign;
	AudioBufferStack *st = (AudioBufferStack *) gf_node_get_private( ((GF_AudioInput *) callback)->owner);
	M_AudioBuffer *ab = (M_AudioBuffer*)st->output.owner;

	if (!st->is_init) return NULL;
	if (!st->buffer) {
		st->done = 0;
		st->buffer_size = (u32) ceil(FIX2FLT(ab->length) * st->output.input_ifce.bps*st->output.input_ifce.samplerate*st->output.input_ifce.chan/8);
		blockAlign = gf_mixer_get_block_align(st->am);
		/*BLOCK ALIGN*/
		while (st->buffer_size%blockAlign) st->buffer_size++;
		st->buffer = (char*)gf_malloc(sizeof(char) * st->buffer_size);
		memset(st->buffer, 0, sizeof(char) * st->buffer_size);
		st->read_pos = st->write_pos = 0;
	}
	if (st->done) return NULL;

	/*even if not active, fill the buffer*/
	if (st->write_pos < st->buffer_size) {
		u32 written;
		while (1) {
			/*just try to completely fill it*/
			written = gf_mixer_get_output(st->am, st->buffer + st->write_pos, st->buffer_size - st->write_pos, 0);
			if (!written) break;
			st->write_pos += written;
			assert(st->write_pos<=st->buffer_size);
		}
	}
	/*not playing*/
	if (! ab->isActive) return NULL;
	*size = st->write_pos - st->read_pos;
	return st->buffer + st->read_pos;
}
예제 #3
0
static u32 gf_ar_fill_output(void *ptr, char *buffer, u32 buffer_size)
{
	u32 written;
	GF_AudioRenderer *ar = (GF_AudioRenderer *) ptr;
	if (!ar->need_reconfig) {
		u32 delay_ms = ar->disable_resync ?	0 : ar->audio_delay;

		if (ar->Frozen) {
			memset(buffer, 0, buffer_size);
			return buffer_size;
		}

		gf_mixer_lock(ar->mixer, GF_TRUE);

		if (ar->filter_chain.enable_filters) {
			char *ptr = buffer;
			written = 0;
			delay_ms += ar->filter_chain.delay_ms;

			while (buffer_size) {
				u32 to_copy;
				if (!ar->nb_used) {
					u32 nb_bytes;

					/*fill input block*/
					nb_bytes = gf_mixer_get_output(ar->mixer, ar->filter_chain.tmp_block1, ar->filter_chain.min_block_size, delay_ms);
					if (!nb_bytes)
						return written;

					/*delay used to check for late frames - we only use it on the first call to gf_mixer_get_output()*/
					delay_ms = 0;

					ar->nb_filled = gf_afc_process(&ar->filter_chain, nb_bytes);
					if (!ar->nb_filled) continue;
				}
				to_copy = ar->nb_filled - ar->nb_used;
				if (to_copy>buffer_size) to_copy = buffer_size;
				memcpy(ptr, ar->filter_chain.tmp_block1 + ar->nb_used, to_copy);
				ptr += to_copy;
				buffer_size -= to_copy;
				written += to_copy;
				ar->nb_used += to_copy;
				if (ar->nb_used==ar->nb_filled) ar->nb_used = 0;
			}
		} else {
			written = gf_mixer_get_output(ar->mixer, buffer, buffer_size, delay_ms);
		}
		gf_mixer_lock(ar->mixer, GF_FALSE);

		//done with one sim step, go back in pause
		if (ar->step_mode) {
			ar->step_mode = GF_FALSE;
			gf_ar_pause(ar, GF_TRUE, GF_FALSE, GF_FALSE);
		}

		if (!ar->need_reconfig) {
			if (ar->audio_listeners) {
				u32 k=0;
				GF_AudioListener *l;
				while ((l = (GF_AudioListener*)gf_list_enum(ar->audio_listeners, &k))) {
					l->on_audio_frame(l->udta, buffer, buffer_size, gf_sc_ar_get_clock(ar), delay_ms);
				}
			}

			ar->bytes_requested += buffer_size;
			ar->current_time = ar->time_at_last_config + (u32) (ar->bytes_requested * 1000 / ar->bytes_per_second);
		}
		//always return buffer size (eg requested input size to be filled), since the clock is always increased by buffer_size (cf above line)
		return buffer_size;
	}
	return 0;
}