mux_pids = sep+1;

		if (e) return e;
	}
	return GF_OK;
}

static GF_Err dasher_reload_context(GF_Filter *filter, GF_DasherCtx *ctx)
{
	GF_Err e;
	Bool last_period_active = GF_FALSE;
	u32 i, j, k, nb_p, nb_as, nb_rep, count;
	GF_DOMParser *mpd_parser;

	ctx->first_context_load = GF_FALSE;

	if (!gf_file_exists(ctx->state)) return GF_OK;

	/* parse the MPD */
	mpd_parser = gf_xml_dom_new();
	e = gf_xml_dom_parse(mpd_parser, ctx->state, NULL, NULL);

	if (e != GF_OK) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[Dasher] Cannot parse MPD state %s: %s\n", ctx->state, gf_xml_dom_get_error(mpd_parser) ));
		gf_xml_dom_del(mpd_parser);
		return GF_URL_ERROR;
	}
	if (ctx->mpd) gf_mpd_del(ctx->mpd);
	ctx->mpd = gf_mpd_new();
	e = gf_mpd_init_from_dom(gf_xml_dom_get_root(mpd_parser), ctx->mpd, ctx->state);
	gf_xml_dom_del(mpd_parser);
	//test mode, strip URL path
	if (gf_sys_is_test_mode()) {
		count = gf_list_count(ctx->mpd->program_infos);
		for (i=0; i<count; i++) {
			GF_MPD_ProgramInfo *info = gf_list_get(ctx->mpd->program_infos, i);
			if (info->title && strstr(info->title, "generated by GPAC")) {
				gf_free(info->title);
				char tmp[256];
				char *name = strrchr(ctx->out_path, '/');
				if (!name) name = strrchr(ctx->out_path, '\\');
				if (!name) name = ctx->out_path;
				else name++;
				sprintf(tmp, "%s generated by GPAC", name);
				info->title = gf_strdup(tmp);
			}
		}
	}

	if (!ctx->mpd->xml_namespace)
		ctx->mpd->xml_namespace = "urn:mpeg:dash:schema:mpd:2011";

	if (e != GF_OK) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[Dasher] Cannot reload MPD state %s: %s\n", ctx->state, gf_error_to_string(e) ));
		gf_mpd_del(ctx->mpd);
		ctx->mpd = NULL;
		return GF_URL_ERROR;
	}

	//do a first pass to detect any potential changes in input config, if so consider the period over.
	nb_p = gf_list_count(ctx->mpd->periods);
	for (i=0; i<nb_p; i++) {
		u32 nb_done_in_period = 0;
		u32 nb_remain_in_period = 0;
		GF_MPD_Period *p = gf_list_get(ctx->mpd->periods, i);
		nb_as = gf_list_count(p->adaptation_sets);
		for (j=0; j<nb_as; j++) {
			GF_MPD_AdaptationSet *set = gf_list_get(p->adaptation_sets, j);
			nb_rep = gf_list_count(set->representations);
			for (k=0; k<nb_rep; k++) {
				GF_DashStream *ds;
				char *p_id;
				GF_MPD_Representation *rep = gf_list_get(set->representations, k);
				if (! rep->dasher_ctx) continue;

				//ensure we have the same settings - if not consider the dash stream has been resetup for a new period
				ds = dasher_get_stream(ctx, rep->dasher_ctx->src_url, rep->dasher_ctx->source_pid, 0);
				if (!ds) {
					rep->dasher_ctx->done = 1;
					nb_done_in_period++;
					if (rep->dasher_ctx->last_dyn_period_id >= ctx->last_dyn_period_id)
						ctx->last_dyn_period_id = 1 + rep->dasher_ctx->last_dyn_period_id;
					continue;
				}

				if (rep->dasher_ctx->done) {
					nb_done_in_period++;
					ds->nb_repeat = rep->dasher_ctx->nb_repeat + 1;
					if (rep->dasher_ctx->last_dyn_period_id > ctx->last_dyn_period_id)
						ctx->last_dyn_period_id = rep->dasher_ctx->last_dyn_period_id;
					continue;
				}

				p_id = DEFAULT_PERIOD_ID;
				if (rep->dasher_ctx->period_id) p_id = rep->dasher_ctx->period_id;

				if (ds->period_id && p_id && !strcmp(ds->period_id, p_id)) {
				} else if (!ds->period_id && !rep->dasher_ctx->period_id) {
				} else {
					rep->dasher_ctx->done = 1;
					nb_done_in_period++;
					continue;
				}
				if (ds->period_start.num * rep->dasher_ctx->period_start.den != rep->dasher_ctx->period_start.num * ds->period_start.den) {
					rep->dasher_ctx->done = 1;
					nb_done_in_period++;
					continue;
				}
				if (ds->period_dur.num * rep->dasher_ctx->period_duration.den != rep->dasher_ctx->period_duration.num * ds->period_dur.den) {
					rep->dasher_ctx->done = 1;
					nb_done_in_period++;
					continue;
				}
				//check we can reload muxed components - if not consider this source as removed
				if (rep->dasher_ctx->mux_pids) {
					e = dasher_reload_muxed_comp(ctx, ds, rep->dasher_ctx->mux_pids, GF_TRUE);
					if (e) {
						rep->dasher_ctx->done = 1;
						nb_done_in_period++;
						continue;
					}
				}
				nb_remain_in_period++;
			}
		}
		if (nb_remain_in_period) {
			assert(i+1==nb_p);
			last_period_active = GF_TRUE;
		}
		else if (nb_done_in_period && ctx->subdur  ) {
			//we are done but we loop the entire streams
			for (j=0; j<gf_list_count(ctx->pids); j++) {
				GF_DashStream *ds = gf_list_get(ctx->pids, j);
				ds->done = 0;
				ds->segment_started = GF_FALSE;
				ds->seg_done = GF_FALSE;
				ds->cumulated_dur = 0;
				ds->cumulated_subdur = 0;
			}
		}
	}

	if (!last_period_active) return GF_OK;
	ctx->current_period->period = gf_list_last(ctx->mpd->periods);
	gf_list_reset(ctx->current_period->streams);
	gf_list_del(ctx->next_period->streams);
	ctx->next_period->streams = gf_list_clone(ctx->pids);

	if (ctx->current_period->period->duration) {
		//reset last period duration and cumulated dur of MPD
		if (ctx->mpd->media_presentation_duration>ctx->current_period->period->duration)
			ctx->mpd->media_presentation_duration -= ctx->current_period->period->duration;
		else
			ctx->mpd->media_presentation_duration = 0;
		ctx->current_period->period->duration = 0;
	}

	nb_as = gf_list_count(ctx->current_period->period->adaptation_sets);
	for (j=0; j<nb_as; j++) {
		GF_DashStream *set_ds = NULL;
		GF_List *multi_pids = NULL;
		Bool use_multi_pid_init = GF_FALSE;
		GF_MPD_AdaptationSet *set = gf_list_get(ctx->current_period->period->adaptation_sets, j);
		nb_rep = gf_list_count(set->representations);
		for (k=0; k<nb_rep; k++) {
			GF_DashStream *ds;
			GF_MPD_Representation *rep = gf_list_get(set->representations, k);
			if (! rep->dasher_ctx) continue;

			ds = dasher_get_stream(ctx, rep->dasher_ctx->src_url, rep->dasher_ctx->source_pid, 0);
			if (!ds) continue;

			//restore everything
			ds->done = rep->dasher_ctx->done;
			ds->seg_number = rep->dasher_ctx->seg_number;

			if (ds->init_seg) gf_free(ds->init_seg);
			ds->init_seg = gf_strdup(rep->dasher_ctx->init_seg);

			if (ds->seg_template) gf_free(ds->seg_template);
			ds->seg_template = gf_strdup(rep->dasher_ctx->template_seg);

			if (ds->idx_template) gf_free(ds->idx_template);
			ds->idx_template = rep->dasher_ctx->template_idx ? gf_strdup(rep->dasher_ctx->template_idx) : NULL;

			if (rep->dasher_ctx->period_id) {
				if (ds->period_id) gf_free(ds->period_id);
				ds->period_id = gf_strdup(rep->dasher_ctx->period_id);
			}

			ds->period_start = rep->dasher_ctx->period_start;
			if (!ds->period_start.den) {
				ds->period_start.num = 0;
				ds->period_start.den = 1;
			}
			ds->period_dur = rep->dasher_ctx->period_duration;
			if (!ds->period_dur.den) {
				ds->period_dur.num = 0;
				ds->period_dur.den = 1;
			}
			ds->pid_id = rep->dasher_ctx->pid_id;
			ds->dep_pid_id = rep->dasher_ctx->dep_pid_id;
			ds->seek_to_pck = rep->dasher_ctx->last_pck_idx;
			ds->dash_dur = rep->dasher_ctx->dash_dur;
			if (!ds->dash_dur.den) {
				ds->dash_dur.num = 0;
				ds->dash_dur.den = 1;
			}
			ds->next_seg_start = rep->dasher_ctx->next_seg_start;
			ds->adjusted_next_seg_start = ds->next_seg_start;
			ds->first_cts = rep->dasher_ctx->first_cts;
			ds->first_dts = rep->dasher_ctx->first_dts;
			ds->ts_offset = rep->dasher_ctx->ts_offset;
			ds->est_next_dts = rep->dasher_ctx->est_next_dts;
			ds->mpd_timescale = rep->dasher_ctx->mpd_timescale;
			ds->cumulated_dur = (u64) (rep->dasher_ctx->cumulated_dur * ds->timescale);
			ds->cumulated_subdur = rep->dasher_ctx->cumulated_subdur;
			ds->rep_init = GF_TRUE;
			ds->subdur_done = rep->dasher_ctx->subdur_forced ? GF_TRUE : GF_FALSE;
			ds->subdur_forced_use_period_dur = 0;
			ds->nb_pck = 0;
			if (!ctx->subdur) {
				ds->nb_pck = ds->seek_to_pck;
				ds->seek_to_pck = 0;
			}
			ds->nb_segments_purged = rep->dasher_ctx->segs_purged;
			ds->dur_purged = rep->dasher_ctx->dur_purged;
			ds->moof_sn = rep->dasher_ctx->moof_sn;
			ds->moof_sn_inc = rep->dasher_ctx->moof_sn_inc;
			ctx->last_dyn_period_id = rep->dasher_ctx->last_dyn_period_id;

			if (ctx->store_seg_states && !ds->pending_segment_states)
				ds->pending_segment_states = gf_list_new();

			if (rep->segment_list && !ds->pending_segment_urls)
				ds->pending_segment_urls = gf_list_new();

			ds->owns_set = rep->dasher_ctx->owns_set;
			if (ds->owns_set) set_ds = ds;

			if (rep->dasher_ctx->done) {
				ds->done = 1;
				if (ds->rep) gf_mpd_representation_free(ds->rep);
				ds->rep = NULL;
				continue;
			}

			ds->nb_comp = 1;

			if (ds->rep) gf_mpd_representation_free(ds->rep);
			ds->rep = rep;
			ds->set = set;
			rep->playback.udta = ds;
			if (ds->owns_set)
				set->udta = ds;
			if (rep->dasher_ctx->multi_pids)
				use_multi_pid_init = GF_TRUE;

			ds->period = ctx->current_period;
			if ((ds->codec_id==GF_CODECID_MHAS) || (ds->codec_id==GF_CODECID_MPHA)) {
				const GF_PropertyValue *prop = gf_filter_pid_get_property(ds->ipid, GF_PROP_PID_MHA_COMPATIBLE_PROFILES);
				if (prop) {
					ds->set->nb_alt_mha_profiles = prop->value.uint_list.nb_items;
					ds->set->alt_mha_profiles = prop->value.uint_list.vals;
				}
			}


			gf_list_del_item(ctx->next_period->streams, ds);

			//non-muxed component or main comp of muxed goes first in the list
			if (ds->nb_comp>1) {
				gf_list_insert(ctx->current_period->streams, ds, 0);
			} else {
				gf_list_add(ctx->current_period->streams, ds);
			}

			if (rep->dasher_ctx->mux_pids) {
				e = dasher_reload_muxed_comp(ctx, ds, rep->dasher_ctx->mux_pids, GF_FALSE);
				if (e) return e;
			}
		}
		assert(set_ds);
		set_ds->nb_rep = gf_list_count(set->representations);

		//if multi PID init, gather pids
		if (use_multi_pid_init) {
			multi_pids = gf_list_new();
			for (i=0; i<nb_rep; i++) {
				GF_MPD_Representation *rep = gf_list_get(set->representations, i);
				GF_DashStream *ds = rep->playback.udta;
				if (ds->owns_set) ds->multi_pids = multi_pids;
				gf_list_add(multi_pids, ds->ipid);
			}
		}
		count = gf_list_count(ctx->current_period->streams);
		for (i=0; i<nb_rep; i++) {
			GF_MPD_Representation *rep = gf_list_get(set->representations, i);
			GF_DashStream *ds = rep->playback.udta;
			if (!ds || ds->done) continue;
			//happens when reloading context without closing the filter
			if (ds->dst_filter || ds->opid) continue;

			//open destination, trashing init
			assert(!ds->muxed_base);
			dasher_open_destination(filter, ctx, rep, ds->init_seg, GF_TRUE);

			dasher_open_pid(filter, ctx, ds, multi_pids, GF_TRUE);

			for (j=0; j<count; j++) {
				GF_DashStream *a_ds = gf_list_get(ctx->current_period->streams, j);
				if (a_ds->muxed_base != ds) continue;