示例#1
0
/*we have no choice but always browsing the children, since a src can be replaced by a new one
without the parent being modified. We just collect the src and check against the current mixer inputs
to reset the mixer or not - the spec is not clear about that btw, shall rebuffering happen if a source is modified or not ...*/
static void audiobuffer_traverse(GF_Node *node, void *rs, Bool is_destroy)
{
	u32 j;
	Bool update_mixer;
	GF_ChildNodeItem *l;
	GF_AudioGroup *parent;
	AudioBufferStack *st = (AudioBufferStack *)gf_node_get_private(node);
	M_AudioBuffer *ab = (M_AudioBuffer *)node;
	GF_TraverseState*tr_state = (GF_TraverseState*) rs;

	if (is_destroy) {
		gf_sc_audio_unregister(&st->output);
		if (st->time_handle.is_registered) 
			gf_sc_unregister_time_node(st->output.compositor, &st->time_handle);

		gf_mixer_del(st->am);
		if (st->buffer) gf_free(st->buffer);
		gf_list_del(st->new_inputs);
		gf_free(st);
		return;
	}
	parent = tr_state->audio_parent;
	tr_state->audio_parent = (GF_AudioGroup *) st;
	l = ab->children;
	while (l) {
		gf_node_traverse(l->node, tr_state);
		l = l->next;
	}

	gf_mixer_lock(st->am, 1);

	/*if no new inputs don't change mixer config*/
	update_mixer = gf_list_count(st->new_inputs) ? 1 : 0;
	
	if (gf_mixer_get_src_count(st->am) == gf_list_count(st->new_inputs)) {
		u32 count = gf_list_count(st->new_inputs);
		update_mixer = 0;
		for (j=0; j<count; j++) {
			GF_AudioInput *cur = (GF_AudioInput *)gf_list_get(st->new_inputs, j);
			if (!gf_mixer_is_src_present(st->am, &cur->input_ifce)) {
				update_mixer = 1;
				break;
			}
		}
	}

	if (update_mixer) {
		gf_mixer_remove_all(st->am);
		gf_mixer_force_chanel_out(st->am, ab->numChan);
	}

	while (gf_list_count(st->new_inputs)) {
		GF_AudioInput *src = (GF_AudioInput *)gf_list_get(st->new_inputs, 0);
		gf_list_rem(st->new_inputs, 0);
		if (update_mixer) gf_mixer_add_input(st->am, &src->input_ifce);
	}

	gf_mixer_lock(st->am, 0);
	tr_state->audio_parent = parent;

	/*Note the audio buffer is ALWAYS registered untill destroyed since buffer filling shall happen even when inactive*/
	if (!st->output.register_with_parent || !st->output.register_with_renderer) 
		gf_sc_audio_register(&st->output, tr_state);

	/*store mute flag*/
	st->is_muted = tr_state->switched_off;
}
示例#2
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;
}
示例#3
0
GF_EXPORT
Bool gf_mixer_reconfig(GF_AudioMixer *am)
{
	u32 i, count, numInit, max_sample_rate, max_channels, max_bps, cfg_changed, ch_cfg;
	gf_mixer_lock(am, GF_TRUE);
	if (am->isEmpty || !am->must_reconfig) {
		gf_mixer_lock(am, GF_FALSE);
		return GF_FALSE;
	}

	if (am->ar && am->ar->config_forced) {
		am->must_reconfig = GF_FALSE;
		gf_mixer_lock(am, GF_FALSE);
		return GF_FALSE;
	}

	numInit = 0;
	max_sample_rate = am->sample_rate;
	max_channels = am->nb_channels;
	max_bps = am->bits_per_sample;
	cfg_changed = 0;
	ch_cfg = 0;

	max_sample_rate = 0,

	count = gf_list_count(am->sources);
	assert(count);
	for (i=0; i<count; i++) {
		Bool has_cfg;
		MixerInput *in = (MixerInput *) gf_list_get(am->sources, i);
		has_cfg = in->src->GetConfig(in->src, GF_TRUE);
		if (has_cfg) {
			/*check same cfg...*/
			if (in->src->samplerate * in->src->chan * in->src->bps == 8*in->bytes_per_sec) {
				numInit++;
				continue;
			}
		} else continue;
		/*update out cfg*/
		if ((count==1) && (max_sample_rate != in->src->samplerate)) {
//			cfg_changed = 1;
			max_sample_rate = in->src->samplerate;
		} else if (max_sample_rate<in->src->samplerate) {
//			cfg_changed = 1;
			max_sample_rate = in->src->samplerate;
		}
		if ((count==1) && (max_bps!=in->src->bps)) {
			cfg_changed = 1;
			max_bps = in->src->bps;
		} else if (max_bps<in->src->bps) {
			cfg_changed = 1;
			max_bps = in->src->bps;
		}
		if (!am->force_channel_out) {
			if ((count==1) && (max_channels!=in->src->chan)) {
				cfg_changed = 1;
				max_channels = in->src->chan;
				if (in->src->chan>2) ch_cfg |= in->src->ch_cfg;
			} else if (max_channels < in->src->chan) {
				cfg_changed = 1;
				max_channels = in->src->chan;
				if (in->src->chan>2) ch_cfg |= in->src->ch_cfg;
			}
		}

		numInit++;
		in->bytes_per_sec = in->src->samplerate * in->src->chan * in->src->bps / 8;
		/*cfg has changed, we must reconfig everything*/
		if (cfg_changed || (max_sample_rate != am->sample_rate) ) {
			in->has_prev = GF_FALSE;
			memset(&in->last_channels, 0, sizeof(s16)*GF_SR_MAX_CHANNELS);
		}
	}

	if (cfg_changed || (max_sample_rate && (max_sample_rate != am->sample_rate)) ) {
		if (max_channels>2) {
			if (ch_cfg != am->channel_cfg) {
				/*recompute num channel based on all input channels*/
				max_channels = 0;
				if (ch_cfg & GF_AUDIO_CH_FRONT_LEFT) max_channels ++;
				if (ch_cfg & GF_AUDIO_CH_FRONT_RIGHT) max_channels ++;
				if (ch_cfg & GF_AUDIO_CH_FRONT_CENTER) max_channels ++;
				if (ch_cfg & GF_AUDIO_CH_LFE) max_channels ++;
				if (ch_cfg & GF_AUDIO_CH_BACK_LEFT) max_channels ++;
				if (ch_cfg & GF_AUDIO_CH_BACK_RIGHT) max_channels ++;
				if (ch_cfg & GF_AUDIO_CH_BACK_CENTER) max_channels ++;
				if (ch_cfg & GF_AUDIO_CH_SIDE_LEFT) max_channels ++;
				if (ch_cfg & GF_AUDIO_CH_SIDE_RIGHT) max_channels ++;
			}
		} else {
			ch_cfg = GF_AUDIO_CH_FRONT_LEFT;
			if (max_channels==2) ch_cfg |= GF_AUDIO_CH_FRONT_RIGHT;
		}
		gf_mixer_set_config(am, max_sample_rate, max_channels, max_bps, ch_cfg);
	}

	if (numInit == count) am->must_reconfig = GF_FALSE;
	if (am->ar) cfg_changed = 1;

	gf_mixer_lock(am, GF_FALSE);
	return cfg_changed;
}
示例#4
0
void gf_sr_lock_audio(GF_Renderer *sr, Bool doLock)
{
	if (sr->audio_renderer) {
		gf_mixer_lock(sr->audio_renderer->mixer, doLock);
	}
}