static void gf_filter_renegociate_output(GF_Filter *filter, Bool force_afchain_insert)
{
	u32 i, j;
	assert(filter->nb_caps_renegociate );
	safe_int_dec(& filter->nb_caps_renegociate );

	gf_mx_p(filter->tasks_mx);

	for (i=0; i<filter->num_output_pids; i++) {
		GF_FilterPid *pid = gf_list_get(filter->output_pids, i);
		if (pid->caps_negociate) {
			Bool is_ok = GF_FALSE;
			Bool reconfig_direct = GF_FALSE;

			//the caps_negociate property map is create with ref count 1

			//no fanout, we can try direct reconfigure of the filter
			if (pid->num_destinations<=1)
				reconfig_direct = GF_TRUE;
			//fanout but we have as many pid instances being negociated as there are destinations, we can try direct reconfigure
			else if (pid->num_destinations==gf_list_count(pid->caps_negociate_pidi_list) && pid->caps_negociate_direct)
				reconfig_direct = GF_TRUE;

			//we cannot reconfigure output if more than one destination
			if (reconfig_direct && filter->freg->reconfigure_output && !force_afchain_insert) {
				GF_Err e = filter->freg->reconfigure_output(filter, pid);
				if (e) {
					if (filter->is_pid_adaptation_filter) {
						GF_FilterPidInst *src_pidi = gf_list_get(filter->input_pids, 0);
						GF_FilterPidInst *pidi = gf_list_get(pid->destinations, 0);

						GF_LOG(GF_LOG_WARNING, GF_LOG_FILTER, ("PID Adaptation Filter %s output reconfiguration error %s, discarding filter and reloading new adaptation chain\n", filter->name, gf_error_to_string(e)));

						assert(filter->num_input_pids==1);

						gf_filter_pid_retry_caps_negotiate(src_pidi->pid, pid, pidi->filter);

						continue;
					}
					GF_LOG(GF_LOG_WARNING, GF_LOG_FILTER, ("Filter %s output reconfiguration error %s, loading filter chain for renegociation\n", filter->name, gf_error_to_string(e)));
				} else {
					is_ok = GF_TRUE;
					gf_filter_check_output_reconfig(filter);
				}
			} else {
				GF_LOG(GF_LOG_INFO, GF_LOG_FILTER, ("Filter %s cannot reconfigure output pids, loading filter chain for renegociation\n", filter->name));
			}

			if (!is_ok) {
				GF_Filter *filter_dst;
				//we are currently connected to output
				if (pid->num_destinations) {
					for (j=0; j<pid->num_destinations; j++) {
						GF_FilterPidInst *pidi = gf_list_get(pid->destinations, j);
						if (gf_list_find(pid->caps_negociate_pidi_list, pidi)<0)
							continue;
						filter_dst = pidi->filter;

						if (filter_dst->freg->reconfigure_output) {
							assert(!filter_dst->caps_negociate);
							filter_dst->caps_negociate = pid->caps_negociate;
							safe_int_inc(&filter_dst->caps_negociate->reference_count);

							gf_fs_post_task(filter->session, gf_filter_reconfigure_output_task, filter_dst, NULL, "filter reconfigure output", NULL);
						} else {
							//disconnect pid, but prevent filter from unloading
							if (!filter_dst->sticky) filter_dst->sticky = 2;
							gf_filter_renegociate_output_dst(pid, filter, filter_dst, pidi, NULL);
						}
					}
				}
				//we are disconnected (unload of a previous adaptation filter)
				else {
					filter_dst = pid->caps_dst_filter;
					assert(pid->num_destinations==0);
					pid->caps_dst_filter = NULL;
					gf_filter_renegociate_output_dst(pid, filter, filter_dst, NULL, NULL);
				}
			}
			assert(pid->caps_negociate->reference_count);
			if (safe_int_dec(&pid->caps_negociate->reference_count) == 0) {
				gf_props_del(pid->caps_negociate);
			}
			pid->caps_negociate = NULL;
			if (pid->caps_negociate_pidi_list) {
				gf_list_del(pid->caps_negociate_pidi_list);
				pid->caps_negociate_pidi_list = NULL;
			}
		}
	}
	gf_mx_v(filter->tasks_mx);
}