void gf_filter_relink_dst(GF_FilterPidInst *from_pidinst)
{
	GF_Filter *filter_dst;
	GF_FilterPid *link_from_pid = NULL;
	u32 min_chain_len = 0;
	Bool needs_flush = GF_FALSE;
	GF_FilterPidInst *src_pidinst = from_pidinst;
	GF_FilterPidInst *dst_pidinst;
	GF_Filter *cur_filter = from_pidinst->filter;

	//locate the true destination
	dst_pidinst = filter_relink_get_upper_pid(src_pidinst, &needs_flush);
	assert(dst_pidinst);

	//make sure we flush the end of the pipeline  !
	if (needs_flush) {
		cur_filter->removed = 2;
		//prevent any fetch from pid
		safe_int_inc(&src_pidinst->detach_pending);
		gf_fs_post_task(cur_filter->session, gf_filter_relink_task, cur_filter, NULL, "relink_dst", src_pidinst);
		return;
	}
	filter_dst = dst_pidinst->filter;

	gf_fs_check_graph_load(cur_filter->session, GF_TRUE);

	//walk down the filter chain and find the shortest path to our destination
	//stop when the current filter is not a one-to-one filter
	while (1) {
		u32 fchain_len;
		GF_FilterPidInst *an_inpid = NULL;
		gf_mx_p(cur_filter->tasks_mx);
		if ((cur_filter->num_input_pids>1) || (cur_filter->num_output_pids>1)) {
			gf_mx_v(cur_filter->tasks_mx);
			break;
		}

		an_inpid = gf_list_get(cur_filter->input_pids, 0);
		if (!an_inpid) {
			gf_mx_v(cur_filter->tasks_mx);
			break;
		}
		if (gf_filter_pid_caps_match((GF_FilterPid *)an_inpid, filter_dst->freg, filter_dst, NULL, NULL, NULL, -1)) {
			link_from_pid = an_inpid->pid;
			gf_mx_v(cur_filter->tasks_mx);
			break;
		}
		fchain_len = gf_filter_pid_resolve_link_length(an_inpid->pid, filter_dst);
		if (fchain_len && (!min_chain_len || (min_chain_len > fchain_len))) {
			min_chain_len = fchain_len;
			link_from_pid = an_inpid->pid;
		}
		gf_mx_v(cur_filter->tasks_mx);
		cur_filter = an_inpid->pid->filter;
	}

	if (!link_from_pid) {
		gf_fs_check_graph_load(cur_filter->session, GF_FALSE);
		return;
	}
	//detach the pidinst, and relink from the new input pid
	gf_filter_renegociate_output_dst(link_from_pid, link_from_pid->filter, filter_dst, dst_pidinst, src_pidinst);
}
void gf_filter_relink_dst(GF_FilterPidInst *from_pidinst)
{
	GF_Filter *filter_dst;
	GF_FilterPid *link_from_pid = NULL;
	u32 min_chain_len = 0;
	Bool needs_flush = GF_FALSE;
	GF_FilterPidInst *src_pidinst = from_pidinst;
	GF_FilterPidInst *dst_pidinst;
	GF_Filter *cur_filter = from_pidinst->filter;

	 
	dst_pidinst = filter_relink_get_upper_pid(src_pidinst, &needs_flush);
	assert(dst_pidinst);

	 
	if (needs_flush) {
		cur_filter->removed = 2;
		 
		safe_int_inc(&src_pidinst->detach_pending);
		gf_fs_post_task(cur_filter->session, gf_filter_relink_task, cur_filter, NULL, "relink_dst", src_pidinst);
		return;
	}
	filter_dst = dst_pidinst->filter;

	gf_fs_check_graph_load(cur_filter->session, GF_TRUE);

	 
	 
	while (1) {
		u32 fchain_len;
		GF_FilterPidInst *an_inpid = NULL;
		gf_mx_p(cur_filter->tasks_mx);
		if ((cur_filter->num_input_pids>1) || (cur_filter->num_output_pids>1)) {
			gf_mx_v(cur_filter->tasks_mx);
			break;
		}

		an_inpid = gf_list_get(cur_filter->input_pids, 0);
		if (!an_inpid) {
			gf_mx_v(cur_filter->tasks_mx);
			break;
		}
		if (gf_filter_pid_caps_match((GF_FilterPid *)an_inpid, filter_dst->freg, filter_dst, NULL, NULL, NULL, -1)) {
			link_from_pid = an_inpid->pid;
			gf_mx_v(cur_filter->tasks_mx);
			break;
		}
		fchain_len = gf_filter_pid_resolve_link_length(an_inpid->pid, filter_dst);
		if (fchain_len && (!min_chain_len || (min_chain_len > fchain_len))) {
			min_chain_len = fchain_len;
			link_from_pid = an_inpid->pid;
		}
		gf_mx_v(cur_filter->tasks_mx);
		cur_filter = an_inpid->pid->filter;
	}

	if (!link_from_pid) {
		gf_fs_check_graph_load(cur_filter->session, GF_FALSE);
		return;
	}
	 
	gf_filter_renegociate_output_dst(link_from_pid, link_from_pid->filter, filter_dst, dst_pidinst, src_pidinst);
}