		if (!stl_e->start_time) stl_e->start_time = start_time;
		else if (stl_e->start_time != start_time) {
			GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[Dasher] Mismatch in segment timeline while purging, new start time "LLU" but entry indicates "LLU", keeping original one\n", start_time, stl_e->start_time ));
		}
	}
}

static void dasher_purge_segments(GF_DasherCtx *ctx, u64 *period_dur)
{
	Double min_valid_mpd_time;
	u64 max_rem_dur = 0;
	u32 i, count;

	//non-static mode, purge segments
	if (ctx->dmode == GF_MPD_TYPE_STATIC) return;
	if (ctx->tsb<0) return;


	min_valid_mpd_time = (Double) *period_dur;
	min_valid_mpd_time /= 1000;
	min_valid_mpd_time -= ctx->tsb;
	//negative asto, we produce segments earlier but we don't want to delete them before the asto
	if (ctx->asto<0) {
		min_valid_mpd_time += ctx->asto;
	}
	if (min_valid_mpd_time<=0) return;

	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->rep) continue;
		if (!ds->rep->state_seg_list) continue;

		while (1) {
			Double time, dur;
			Bool seg_url_found = GF_FALSE;
			Bool has_seg_list = GF_FALSE;
			GF_DASH_SegmentContext *sctx = gf_list_get(ds->rep->state_seg_list, 0);
			if (!sctx) break;
			/*not yet flushed*/
			if (gf_list_find(ds->pending_segment_states, sctx)>=0) break;
			time = (Double) sctx->time;
			time /= ds->mpd_timescale;
			dur = (Double) sctx->dur;
			dur/= ds->timescale;
			if (time + dur >= min_valid_mpd_time) break;
			if (sctx->filepath) {
				GF_FilterEvent evt;
				GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[Dasher] removing segment %s\n", sctx->filename ? sctx->filename : sctx->filepath));

				GF_FEVT_INIT(evt, GF_FEVT_FILE_DELETE, ds->opid);
				evt.file_del.url = sctx->filepath;
				gf_filter_pid_send_event(ds->opid, &evt);
				gf_free(sctx->filepath);
			}

			if (ds->rep->segment_list) {
				GF_MPD_SegmentURL *surl = gf_list_pop_front(ds->rep->segment_list->segment_URLs);
				has_seg_list = GF_TRUE;
				//can be NULL if we mutualize everything at AdaptatioSet level
				if (surl) {
					gf_mpd_segment_url_free(surl);
					seg_url_found = GF_TRUE;
				}
			}
			//not an else due to inheritance
			if (ds->owns_set && ds->set->segment_list) {
				GF_MPD_SegmentURL *surl = gf_list_pop_front(ds->set->segment_list->segment_URLs);
				has_seg_list = GF_TRUE;
				//can be NULL if we don't mutualize at AdaptatioSet level
				if (surl) {
					gf_mpd_segment_url_free(surl);
					seg_url_found = GF_TRUE;
				}
			}
			//but we must have at least one segment URL entry
			if (has_seg_list && !seg_url_found) {
				GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[Dasher] purging segment %s for AS %d rep %s but segment list is empty!\n",
						sctx->filename ? sctx->filename : "", ds->set->id, ds->rep->id));
			}

			if (ds->rep->segment_template) {
				if (ds->rep->segment_template->segment_timeline) {
					dasher_purge_segment_timeline(ds, ds->rep->segment_template->segment_timeline, sctx);
				}
			}
			//not an else due to inheritance
			if (ds->owns_set && ds->set->segment_template) {
				if (ds->set->segment_template->segment_timeline) {
					dasher_purge_segment_timeline(ds, ds->set->segment_template->segment_timeline, sctx);
				}
			}

			ds->nb_segments_purged ++;
			ds->dur_purged += dur;
			assert(gf_list_find(ds->pending_segment_states, sctx)<0);
			if (sctx->filename) gf_free(sctx->filename);
			if (sctx->hls_key_uri) gf_free(sctx->hls_key_uri);
			gf_free(sctx);
			gf_list_rem(ds->rep->state_seg_list, 0);
		}
		if (max_rem_dur < ds->dur_purged*1000) max_rem_dur = (u64) (ds->dur_purged * 1000);
		//final flush to static of live session: update start number
		if (ctx->dmode!=GF_MPD_TYPE_DYNAMIC) {
			if (ds->owns_set && ds->set && ds->set->segment_template) {
				ds->set->segment_template->start_number += ds->nb_segments_purged;
			} else if (ds->rep && ds->rep->segment_template) {
				ds->rep->segment_template->start_number += ds->nb_segments_purged;
			}
			ds->nb_segments_purged = 0;
		}
		if (!stl_e->start_time) stl_e->start_time = start_time;
		else if (stl_e->start_time != start_time) {
			GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[Dasher] Mismatch in segment timeline while purging, new start time "LLU" but entry indicates "LLU", keeping original one\n", start_time, stl_e->start_time ));
		}
	}
}

static void dasher_purge_segments(GF_DasherCtx *ctx, u64 *period_dur)
{
	Double min_valid_mpd_time;
	u64 max_rem_dur = 0;
	u32 i, count;

	 
	if (ctx->dmode == GF_MPD_TYPE_STATIC) return;
	if (ctx->tsb<0) return;


	min_valid_mpd_time = (Double) *period_dur;
	min_valid_mpd_time /= 1000;
	min_valid_mpd_time -= ctx->tsb;
	 
	if (ctx->asto<0) {
		min_valid_mpd_time += ctx->asto;
	}
	if (min_valid_mpd_time<=0) return;

	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->rep) continue;
		if (!ds->rep->state_seg_list) continue;

		while (1) {
			Double time, dur;
			Bool seg_url_found = GF_FALSE;
			Bool has_seg_list = GF_FALSE;
			GF_DASH_SegmentContext *sctx = gf_list_get(ds->rep->state_seg_list, 0);
			if (!sctx) break;
			 
			if (gf_list_find(ds->pending_segment_states, sctx)>=0) break;
			time = (Double) sctx->time;
			time /= ds->mpd_timescale;
			dur = (Double) sctx->dur;
			dur/= ds->timescale;
			if (time + dur >= min_valid_mpd_time) break;
			if (sctx->filepath) {
				GF_FilterEvent evt;
				GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[Dasher] removing segment %s\n", sctx->filename ? sctx->filename : sctx->filepath));

				GF_FEVT_INIT(evt, GF_FEVT_FILE_DELETE, ds->opid);
				evt.file_del.url = sctx->filepath;
				gf_filter_pid_send_event(ds->opid, &evt);
				gf_free(sctx->filepath);
			}

			if (ds->rep->segment_list) {
				GF_MPD_SegmentURL *surl = gf_list_pop_front(ds->rep->segment_list->segment_URLs);
				has_seg_list = GF_TRUE;
				 
				if (surl) {
					gf_mpd_segment_url_free(surl);
					seg_url_found = GF_TRUE;
				}
			}
			 
			if (ds->owns_set && ds->set->segment_list) {
				GF_MPD_SegmentURL *surl = gf_list_pop_front(ds->set->segment_list->segment_URLs);
				has_seg_list = GF_TRUE;
				 
				if (surl) {
					gf_mpd_segment_url_free(surl);
					seg_url_found = GF_TRUE;
				}
			}
			 
			if (has_seg_list && !seg_url_found) {
				GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[Dasher] purging segment %s for AS %d rep %s but segment list is empty!\n",
						sctx->filename ? sctx->filename : "", ds->set->id, ds->rep->id));
			}

			if (ds->rep->segment_template) {
				if (ds->rep->segment_template->segment_timeline) {
					dasher_purge_segment_timeline(ds, ds->rep->segment_template->segment_timeline, sctx);
				}
			}
			 
			if (ds->owns_set && ds->set->segment_template) {
				if (ds->set->segment_template->segment_timeline) {
					dasher_purge_segment_timeline(ds, ds->set->segment_template->segment_timeline, sctx);
				}
			}

			ds->nb_segments_purged ++;
			ds->dur_purged += dur;
			assert(gf_list_find(ds->pending_segment_states, sctx)<0);
			if (sctx->filename) gf_free(sctx->filename);
			if (sctx->hls_key_uri) gf_free(sctx->hls_key_uri);
			gf_free(sctx);
			gf_list_rem(ds->rep->state_seg_list, 0);
		}
		if (max_rem_dur < ds->dur_purged*1000) max_rem_dur = (u64) (ds->dur_purged * 1000);
		 
		if (ctx->dmode!=GF_MPD_TYPE_DYNAMIC) {
			if (ds->owns_set && ds->set && ds->set->segment_template) {
				ds->set->segment_template->start_number += ds->nb_segments_purged;
			} else if (ds->rep && ds->rep->segment_template) {
				ds->rep->segment_template->start_number += ds->nb_segments_purged;
			}
			ds->nb_segments_purged = 0;
		}