	//final flush to static of live session: update period duration
	if (ctx->dmode!=GF_MPD_TYPE_DYNAMIC) {
		if (max_rem_dur > *period_dur) *period_dur = 0;
		else *period_dur = *period_dur - max_rem_dur;
	}
}

static void dasher_update_period_duration(GF_DasherCtx *ctx, Bool is_period_switch)
{
	u32 i, count;
	u64 pdur = 0;
	u64 min_dur = 0;
	u64 p_start=0;
	GF_MPD_Period *prev_p = NULL;
	count = gf_list_count(ctx->current_period->streams);
	for (i=0; i<count; i++) {
		GF_DashStream *ds = gf_list_get(ctx->current_period->streams, i);
		if (ds->muxed_base) continue;

		if (ds->xlink && (ds->stream_type==GF_STREAM_FILE) ) {
			pdur = (u32) (1000*(s64)ds->period_dur.num / ds->period_dur.den);
		} else {
			u64 ds_dur = ds->max_period_dur;

			//we had to generate one extra segment to unlock looping, but we don't want to advertise it in the manifest duration
			//because other sets may not be ready for this time interval
			if (ds->subdur_forced_use_period_dur)
				ds_dur = ds->subdur_forced_use_period_dur;

			if (ds->clamped_dur.num && !ctx->loop) {
				u64 clamp_dur = (u64) (ds->clamped_dur.num * 1000);
				if (clamp_dur < ds->clamped_dur.den * ds_dur) ds_dur = clamp_dur / ds->clamped_dur.den;
			}

			if (ds->dur_purged && (ctx->mpd->type != GF_MPD_TYPE_DYNAMIC)) {
				u64 rem_dur = (u64) (ds->dur_purged * 1000);
				if (ds_dur>rem_dur) ds_dur -= rem_dur;
				else ds_dur = 0;
			}

			if (!min_dur || (min_dur > ds_dur)) min_dur = ds->max_period_dur;
			if (pdur < ds_dur) pdur = ds_dur;
		}
	}

	if (!count) {
		if (ctx->current_period->period && ctx->current_period->period->duration)
			pdur = ctx->current_period->period->duration;
	}

	if (!ctx->check_dur) {
		s32 diff = (s32) ((s64) pdur - (s64) min_dur);
		if (ABS(diff)>2000) {
			GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[Dasher] Adaptation sets in period are of unequal duration min %g max %g seconds\n", ((Double)min_dur)/1000, ((Double)pdur)/1000));
		}
	}

	dasher_purge_segments(ctx, &pdur);

	if (ctx->current_period->period) {
		ctx->current_period->period->duration = pdur;

		//update MPD duration in any case
		if (ctx->current_period->period->start) {
			ctx->mpd->media_presentation_duration = ctx->current_period->period->start + pdur;
		} else {
			u32 k, pcount = gf_list_count(ctx->mpd->periods);
			ctx->mpd->media_presentation_duration = 0;
			for (k=0; k<pcount; k++) {
				GF_MPD_Period *p = gf_list_get(ctx->mpd->periods, k);
				if (p->start)
					ctx->mpd->media_presentation_duration = p->start + p->duration;
				else
					ctx->mpd->media_presentation_duration += p->duration;
				if (p==ctx->current_period->period)
					break;
			}
		}
	}

	if (ctx->refresh<0)
		ctx->mpd->media_presentation_duration = (u32) ( (-ctx->refresh) * 1000 );

	//static mode, done
	if (ctx->dmode != GF_MPD_TYPE_DYNAMIC) {
		return;
	}
	assert(ctx->current_period->period);
	//dynamic mode only, reset durations

	ctx->mpd->gpac_mpd_time = ctx->mpd->media_presentation_duration;

	//not done yet for this period, keep duration to 0
	if (ctx->subdur_done) {
		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;
	}

	ctx->mpd->gpac_next_ntp_ms = ctx->mpd->gpac_init_ntp_ms + ctx->mpd->gpac_mpd_time;
	if (ctx->asto<0)
		ctx->mpd->gpac_next_ntp_ms -= (u64) (-ctx->asto * 1000);
	if (ctx->_p_gentime) (*ctx->_p_gentime) = ctx->mpd->gpac_next_ntp_ms;
	if (ctx->_p_mpdtime) (*ctx->_p_mpdtime) = ctx->mpd->gpac_mpd_time;

	GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[Dasher] updated period %s duration "LLU" MPD time "LLU"\n", ctx->current_period->period->ID, pdur, ctx->mpd->gpac_mpd_time ));

	count = gf_list_count(ctx->mpd->periods);
	for (i=0; i<count; i++) {
		GF_MPD_Period *p = gf_list_get(ctx->mpd->periods, i);
		if (p->start) {
			p_start = p->start;
		} else {
			p->start = p_start;
		}
	 
	if (ctx->dmode!=GF_MPD_TYPE_DYNAMIC) {
		if (max_rem_dur > *period_dur) *period_dur = 0;
		else *period_dur = *period_dur - max_rem_dur;
	}
}

static void dasher_update_period_duration(GF_DasherCtx *ctx, Bool is_period_switch)
{
	u32 i, count;
	u64 pdur = 0;
	u64 min_dur = 0;
	u64 p_start=0;
	GF_MPD_Period *prev_p = NULL;
	count = gf_list_count(ctx->current_period->streams);
	for (i=0; i<count; i++) {
		GF_DashStream *ds = gf_list_get(ctx->current_period->streams, i);
		if (ds->muxed_base) continue;

		if (ds->xlink && (ds->stream_type==GF_STREAM_FILE) ) {
			pdur = (u32) (1000*(s64)ds->period_dur.num / ds->period_dur.den);
		} else {
			u64 ds_dur = ds->max_period_dur;

			 
			 
			if (ds->subdur_forced_use_period_dur)
				ds_dur = ds->subdur_forced_use_period_dur;

			if (ds->clamped_dur.num && !ctx->loop) {
				u64 clamp_dur = (u64) (ds->clamped_dur.num * 1000);
				if (clamp_dur < ds->clamped_dur.den * ds_dur) ds_dur = clamp_dur / ds->clamped_dur.den;
			}

			if (ds->dur_purged && (ctx->mpd->type != GF_MPD_TYPE_DYNAMIC)) {
				u64 rem_dur = (u64) (ds->dur_purged * 1000);
				if (ds_dur>rem_dur) ds_dur -= rem_dur;
				else ds_dur = 0;
			}

			if (!min_dur || (min_dur > ds_dur)) min_dur = ds->max_period_dur;
			if (pdur < ds_dur) pdur = ds_dur;
		}
	}

	if (!count) {
		if (ctx->current_period->period && ctx->current_period->period->duration)
			pdur = ctx->current_period->period->duration;
	}

	if (!ctx->check_dur) {
		s32 diff = (s32) ((s64) pdur - (s64) min_dur);
		if (ABS(diff)>2000) {
			GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[Dasher] Adaptation sets in period are of unequal duration min %g max %g seconds\n", ((Double)min_dur)/1000, ((Double)pdur)/1000));
		}
	}

	dasher_purge_segments(ctx, &pdur);

	if (ctx->current_period->period) {
		ctx->current_period->period->duration = pdur;

		 
		if (ctx->current_period->period->start) {
			ctx->mpd->media_presentation_duration = ctx->current_period->period->start + pdur;
		} else {
			u32 k, pcount = gf_list_count(ctx->mpd->periods);
			ctx->mpd->media_presentation_duration = 0;
			for (k=0; k<pcount; k++) {
				GF_MPD_Period *p = gf_list_get(ctx->mpd->periods, k);
				if (p->start)
					ctx->mpd->media_presentation_duration = p->start + p->duration;
				else
					ctx->mpd->media_presentation_duration += p->duration;
				if (p==ctx->current_period->period)
					break;
			}
		}
	}

	if (ctx->refresh<0)
		ctx->mpd->media_presentation_duration = (u32) ( (-ctx->refresh) * 1000 );

	 
	if (ctx->dmode != GF_MPD_TYPE_DYNAMIC) {
		return;
	}
	assert(ctx->current_period->period);
	 

	ctx->mpd->gpac_mpd_time = ctx->mpd->media_presentation_duration;

	 
	if (ctx->subdur_done) {
		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;
	}

	ctx->mpd->gpac_next_ntp_ms = ctx->mpd->gpac_init_ntp_ms + ctx->mpd->gpac_mpd_time;
	if (ctx->asto<0)
		ctx->mpd->gpac_next_ntp_ms -= (u64) (-ctx->asto * 1000);
	if (ctx->_p_gentime) (*ctx->_p_gentime) = ctx->mpd->gpac_next_ntp_ms;
	if (ctx->_p_mpdtime) (*ctx->_p_mpdtime) = ctx->mpd->gpac_mpd_time;

	GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[Dasher] updated period %s duration "LLU" MPD time "LLU"\n", ctx->current_period->period->ID, pdur, ctx->mpd->gpac_mpd_time ));

	count = gf_list_count(ctx->mpd->periods);
	for (i=0; i<count; i++) {
		GF_MPD_Period *p = gf_list_get(ctx->mpd->periods, i);
		if (p->start) {
			p_start = p->start;
		} else {
			p->start = p_start;
		}