if (ctx->state)
		dasher_context_update_period_start(ctx);

	return GF_OK;
}

static void dasher_insert_timeline_entry(GF_DasherCtx *ctx, GF_DashStream *ds)
{
	GF_MPD_SegmentTimelineEntry *s;
	u64 duration, pto;
	Bool is_first = GF_FALSE;
	Bool seg_align = GF_FALSE;
	GF_MPD_SegmentTimeline *tl=NULL;

	//we only store segment timeline for the main component in the representation
	if (ds->muxed_base) return;

	if (ds->rep && ds->rep->state_seg_list) {
		GF_DASH_SegmentContext *sctx = gf_list_last(ds->rep->state_seg_list);
		if (sctx)
			sctx->dur = ds->first_cts_in_next_seg - ds->first_cts_in_seg;
	}

	//we only use segment timeline with templates
	if (!ds->stl) return;

	if (gf_list_find(ds->set->representations, ds->rep)==0) is_first = GF_TRUE;
	assert(ds->first_cts_in_next_seg > ds->first_cts_in_seg);
	duration = ds->first_cts_in_next_seg - ds->first_cts_in_seg;
	pto = ds->presentation_time_offset;
	if (ds->timescale != ds->mpd_timescale) {
		duration *= ds->mpd_timescale;
		duration /= ds->timescale;

		pto = gf_timestamp_rescale(pto, ds->timescale, ds->mpd_timescale);
	}
	seg_align = (ds->set->segment_alignment || ds->set->subsegment_alignment) ? GF_TRUE : GF_FALSE;
	//not first and segment alignment, ignore
	if (!is_first && seg_align) {
		return;
	}

	//no segment alignment store in each rep
	if (!seg_align) {
		GF_MPD_SegmentTimeline **p_tl=NULL;
		if (!ds->rep) {
			GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[Dasher] failed to store timeline entry, no representation assigned !\n"));
			return;
		}

		if (ctx->tpl) {
			p_tl = &ds->rep->segment_template->segment_timeline;
			ds->rep->segment_template->duration = 0;
		} else {
			p_tl = &ds->rep->segment_list->segment_timeline;
			ds->rep->segment_list->duration = 0;
		}
		if (! (*p_tl)) {
			(*p_tl) = gf_mpd_segmentimeline_new();
		}
		tl = (*p_tl);
	} else {
		Bool new_tl = GF_FALSE;
		GF_MPD_SegmentTimeline **p_tl=NULL;

		if (!ds->set) {
			GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[Dasher] failed to store timeline entry, no AdpatationSet assigned !\n"));
			return;
		}
		assert(ds->set);
		if (ctx->tpl) {
			//in case we had no template at set level
			if (!ds->set->segment_template) {
				GF_SAFEALLOC(ds->set->segment_template, GF_MPD_SegmentTemplate);
				if (ds->set->segment_template) {
					ds->set->segment_template->start_number = (u32) -1;
					ds->set->segment_template->timescale = ds->mpd_timescale;
					ds->set->segment_template->presentation_time_offset = pto;
				}
				new_tl = GF_TRUE;
			}
			p_tl = &ds->set->segment_template->segment_timeline;
			ds->set->segment_template->duration = 0;
		} else {
			//in case we had no template at set level
			if (!ds->set->segment_list) {
				GF_SAFEALLOC(ds->set->segment_list, GF_MPD_SegmentList);
				if (ds->set->segment_list) {
					ds->set->segment_list->start_number = (u32) -1;
					ds->set->segment_list->timescale = ds->mpd_timescale;
					ds->set->segment_list->presentation_time_offset = pto;
				}
				new_tl = GF_TRUE;
			}
			p_tl = &ds->set->segment_list->segment_timeline;
			ds->set->segment_list->duration = 0;
		}

		if (! (*p_tl) ) {
			(*p_tl)  = gf_mpd_segmentimeline_new();
		}
		tl = (*p_tl);
		if (new_tl) {
			u32 i, count = gf_list_count(ds->set->representations);
			for (i=0; i<count; i++) {
				GF_MPD_Representation *arep = gf_list_get(ds->set->representations, i);
				if (arep && arep->segment_template) arep->segment_template->duration = 0;
				if (arep && arep->segment_list) arep->segment_list->duration = 0;
			}
		}
	}

	//append to previous entry if possible
	s = gf_list_last(tl->entries);
	if (s && (s->duration == duration) && (s->start_time + (s->repeat_count+1) * s->duration == ds->seg_start_time + pto)) {
		s->repeat_count++;
		return;
	}