void gf_filter_renegociate_output_dst(GF_FilterPid *pid, GF_Filter *filter, GF_Filter *filter_dst, GF_FilterPidInst *dst_pidi, GF_FilterPidInst *src_pidi)
{
	Bool is_new_chain = GF_TRUE;
	GF_Filter *new_f;
	Bool reconfig_only = src_pidi ? GF_FALSE: GF_TRUE;

	assert(filter);

	if (!filter_dst) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_FILTER, ("Internal error, lost destination for pid %s in filter %s while negotiating caps !!\n", pid->name, filter->name));
		return;
	}

	//try to load filters to reconnect output pid
	//we pass the source pid if given, so that we are sure the active property set is used to match the caps
	if (!reconfig_only && gf_filter_pid_caps_match(src_pidi ? (GF_FilterPid *)src_pidi : pid, filter_dst->freg, filter_dst, NULL, NULL, NULL, -1)) {
		GF_FilterPidInst *a_dst_pidi;
		new_f = pid->filter;
		assert(pid->num_destinations==1);
		a_dst_pidi = gf_list_get(pid->destinations, 0);
		//we are replacing the chain, remove filters until dest, keeping the final PID connected since we will detach
		// and reattach it
		if (!filter_dst->sticky) filter_dst->sticky = 2;
		gf_filter_remove_internal(a_dst_pidi->filter, filter_dst, GF_TRUE);
		is_new_chain = GF_FALSE;

		//we will reassign packets from that pid instance to the new connection
		filter_dst->swap_pidinst_dst = a_dst_pidi;

		src_pidi->filter->removed = 2;

	}
	//we are inserting a new chain for reconfiguration only
	else if (reconfig_only) {
		gf_fs_check_graph_load(filter_dst->session, GF_TRUE);
		//make sure we don't try the PID parent filter since we just failed reconfiguring it
		gf_list_add(pid->filter->blacklisted, (void *) pid->filter->freg);
		new_f = gf_filter_pid_resolve_link_for_caps(pid, filter_dst, GF_TRUE);

		gf_list_del_item(pid->filter->blacklisted, (void *)pid->filter->freg);

		//special case: no adaptation filter found but destination filter has forced caps set, try to load a filter chain allowing for new caps
		if (!new_f && filter_dst->forced_caps) {
			new_f = gf_filter_pid_resolve_link_for_caps(pid, filter_dst, GF_FALSE);
			if (new_f) {
				//drop caps negociate
				reconfig_only = GF_FALSE;
			}
		}
	}
	//we are inserting a new chain
	else {
		Bool reassigned;
		gf_fs_check_graph_load(filter_dst->session, GF_TRUE);
		new_f = gf_filter_pid_resolve_link(pid, filter_dst, &reassigned);
	}

	gf_fs_check_graph_load(filter_dst->session, GF_FALSE);

	if (! new_f) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_FILTER, ("No suitable filter to adapt caps between pid %s in filter %s to filter %s, disconnecting pid!\n", pid->name, filter->name, filter_dst->name));
		filter->session->last_connect_error = GF_FILTER_NOT_FOUND;

		if (pid->adapters_blacklist) {
			gf_list_del(pid->adapters_blacklist);
			pid->adapters_blacklist = NULL;
		}
		if (pid->num_destinations==1) {
			GF_FilterEvent evt;
			GF_FEVT_INIT(evt, GF_FEVT_PLAY, pid);
			gf_filter_pid_send_event_internal(pid, &evt, GF_TRUE);
			GF_FEVT_INIT(evt, GF_FEVT_STOP, pid);
			gf_filter_pid_send_event_internal(pid, &evt, GF_TRUE);
		}
		if (dst_pidi) {
			gf_fs_post_task(filter->session, gf_filter_pid_disconnect_task, dst_pidi->filter, dst_pidi->pid, "pidinst_disconnect", NULL);
		}
		return;
	}
	//detach pid instance from its source pid
	if (dst_pidi) {
		//signal as detached, this will prevent any further packet access
		safe_int_inc(&dst_pidi->detach_pending);

		//we need to first reconnect the pid and then detach the output
		if (is_new_chain) {
			//signal a stream reset is pending to prevent filter entering endless loop
			safe_int_inc(&dst_pidi->filter->stream_reset_pending);
			//keep track of the pidinst being detached in the target filter
			new_f->swap_pidinst_dst = dst_pidi;
			//keep track of the pidinst being detached from the source filter
			new_f->swap_pidinst_src = src_pidi;
			new_f->swap_needs_init = GF_TRUE;
		}
		//we directly detach the pid
		else {
			safe_int_inc(&dst_pidi->pid->filter->detach_pid_tasks_pending);
			safe_int_inc(&filter_dst->detach_pid_tasks_pending);
			gf_fs_post_task(filter->session, gf_filter_pid_detach_task, filter_dst, dst_pidi->pid, "pidinst_detach", filter_dst);
		}
	}

	if (reconfig_only) {
		assert(pid->caps_negociate);
		new_f->caps_negociate = pid->caps_negociate;
		safe_int_inc(&new_f->caps_negociate->reference_count);
	}

	if (is_new_chain) {
		//mark this filter has having pid connection pending to prevent packet dispatch until the connection is done
		safe_int_inc(&pid->filter->out_pid_connection_pending);
		gf_filter_pid_post_connect_task(new_f, pid);
	} else {
		gf_fs_post_task(filter->session, gf_filter_pid_reconfigure_task, filter_dst, pid, "pidinst_reconfigure", NULL);
	}
}
void gf_filter_renegociate_output_dst(GF_FilterPid *pid, GF_Filter *filter, GF_Filter *filter_dst, GF_FilterPidInst *dst_pidi, GF_FilterPidInst *src_pidi)
{
	Bool is_new_chain = GF_TRUE;
	GF_Filter *new_f;
	Bool reconfig_only = src_pidi ? GF_FALSE: GF_TRUE;

	assert(filter);

	if (!filter_dst) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_FILTER, ("Internal error, lost destination for pid %s in filter %s while negotiating caps !!\n", pid->name, filter->name));
		return;
	}

	 
	 
	if (!reconfig_only && gf_filter_pid_caps_match(src_pidi ? (GF_FilterPid *)src_pidi : pid, filter_dst->freg, filter_dst, NULL, NULL, NULL, -1)) {
		GF_FilterPidInst *a_dst_pidi;
		new_f = pid->filter;
		assert(pid->num_destinations==1);
		a_dst_pidi = gf_list_get(pid->destinations, 0);
		 
		 
		if (!filter_dst->sticky) filter_dst->sticky = 2;
		gf_filter_remove_internal(a_dst_pidi->filter, filter_dst, GF_TRUE);
		is_new_chain = GF_FALSE;

		 
		filter_dst->swap_pidinst_dst = a_dst_pidi;

		src_pidi->filter->removed = 2;

	}
	 
	else if (reconfig_only) {
		gf_fs_check_graph_load(filter_dst->session, GF_TRUE);
		 
		gf_list_add(pid->filter->blacklisted, (void *) pid->filter->freg);
		new_f = gf_filter_pid_resolve_link_for_caps(pid, filter_dst, GF_TRUE);

		gf_list_del_item(pid->filter->blacklisted, (void *)pid->filter->freg);

		 
		if (!new_f && filter_dst->forced_caps) {
			new_f = gf_filter_pid_resolve_link_for_caps(pid, filter_dst, GF_FALSE);
			if (new_f) {
				 
				reconfig_only = GF_FALSE;
			}
		}
	}
	 
	else {
		Bool reassigned;
		gf_fs_check_graph_load(filter_dst->session, GF_TRUE);
		new_f = gf_filter_pid_resolve_link(pid, filter_dst, &reassigned);
	}

	gf_fs_check_graph_load(filter_dst->session, GF_FALSE);

	if (! new_f) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_FILTER, ("No suitable filter to adapt caps between pid %s in filter %s to filter %s, disconnecting pid!\n", pid->name, filter->name, filter_dst->name));
		filter->session->last_connect_error = GF_FILTER_NOT_FOUND;

		if (pid->adapters_blacklist) {
			gf_list_del(pid->adapters_blacklist);
			pid->adapters_blacklist = NULL;
		}
		if (pid->num_destinations==1) {
			GF_FilterEvent evt;
			GF_FEVT_INIT(evt, GF_FEVT_PLAY, pid);
			gf_filter_pid_send_event_internal(pid, &evt, GF_TRUE);
			GF_FEVT_INIT(evt, GF_FEVT_STOP, pid);
			gf_filter_pid_send_event_internal(pid, &evt, GF_TRUE);
		}
		if (dst_pidi) {
			gf_fs_post_task(filter->session, gf_filter_pid_disconnect_task, dst_pidi->filter, dst_pidi->pid, "pidinst_disconnect", NULL);
		}
		return;
	}
	 
	if (dst_pidi) {
		 
		safe_int_inc(&dst_pidi->detach_pending);

		 
		if (is_new_chain) {
			 
			safe_int_inc(&dst_pidi->filter->stream_reset_pending);
			 
			new_f->swap_pidinst_dst = dst_pidi;
			 
			new_f->swap_pidinst_src = src_pidi;
			new_f->swap_needs_init = GF_TRUE;
		}
		 
		else {
			safe_int_inc(&dst_pidi->pid->filter->detach_pid_tasks_pending);
			safe_int_inc(&filter_dst->detach_pid_tasks_pending);
			gf_fs_post_task(filter->session, gf_filter_pid_detach_task, filter_dst, dst_pidi->pid, "pidinst_detach", filter_dst);
		}
	}

	if (reconfig_only) {
		assert(pid->caps_negociate);
		new_f->caps_negociate = pid->caps_negociate;
		safe_int_inc(&new_f->caps_negociate->reference_count);
	}

	if (is_new_chain) {
		 
		safe_int_inc(&pid->filter->out_pid_connection_pending);
		gf_filter_pid_post_connect_task(new_f, pid);
	} else {
		gf_fs_post_task(filter->session, gf_filter_pid_reconfigure_task, filter_dst, pid, "pidinst_reconfigure", NULL);
	}
}