GF_Err gf_filter_set_source(GF_Filter *filter, GF_Filter *link_from, const char *link_ext)
{
	if (!filter || !link_from) return GF_BAD_PARAM;
	if (filter == link_from) return GF_OK;
	//don't allow loops
	if (gf_filter_in_parent_chain(filter, link_from)) return GF_BAD_PARAM;

	if (!link_from->id) {
		gf_filter_assign_id(link_from, NULL);
	}
	if (link_ext) {
		char szSep[2];
		char *id = NULL;
		gf_dynstrcat(&id, link_from->id, NULL);
		szSep[0] = link_from->session->sep_frag;
		szSep[1] = 0;
		gf_dynstrcat(&id, link_ext, szSep);
		gf_filter_set_sources(filter, id);
		gf_free(id);
	} else {
		gf_filter_set_sources(filter, link_from->id);
	}
	if (link_from->target_filter != filter) {
		filter->target_filter = link_from->target_filter;
		link_from->target_filter = NULL;
	}
	return GF_OK;
}
GF_Err gf_filter_set_source(GF_Filter *filter, GF_Filter *link_from, const char *link_ext)
{
	if (!filter || !link_from) return GF_BAD_PARAM;
	if (filter == link_from) return GF_OK;
	 
	if (gf_filter_in_parent_chain(filter, link_from)) return GF_BAD_PARAM;

	if (!link_from->id) {
		gf_filter_assign_id(link_from, NULL);
	}
	if (link_ext) {
		char szSep[2];
		char *id = NULL;
		gf_dynstrcat(&id, link_from->id, NULL);
		szSep[0] = link_from->session->sep_frag;
		szSep[1] = 0;
		gf_dynstrcat(&id, link_ext, szSep);
		gf_filter_set_sources(filter, id);
		gf_free(id);
	} else {
		gf_filter_set_sources(filter, link_from->id);
	}
	if (link_from->target_filter != filter) {
		filter->target_filter = link_from->target_filter;
		link_from->target_filter = NULL;
	}
	return GF_OK;
}