static gchar *gst_mpdparser_build_URL_from_template (const gchar * url_template,
const gchar * id, guint number, guint bandwidth, guint64 time);
static gboolean gst_mpd_client_add_media_segment (GstActiveStream * stream,
- GstSegmentURLNode * url_node, guint number, guint64 start,
- GstClockTime start_time, GstClockTime duration);
+ GstSegmentURLNode * url_node, guint number, gint repeat, gint64 scale_start,
+ gint64 scale_duration, GstClockTime start, GstClockTime duration);
static const gchar *gst_mpdparser_mimetype_to_caps (const gchar * mimeType);
static GstClockTime gst_mpd_client_get_segment_duration (GstMpdClient * client,
- GstActiveStream * stream);
+ GstActiveStream * stream, gint64 * scale_duration);
static GstDateTime *gst_mpd_client_get_availability_start_time (GstMpdClient *
client);
static GstClockTime
gst_mpd_client_get_segment_duration (GstMpdClient * client,
- GstActiveStream * stream)
+ GstActiveStream * stream, gint64 * scale_dur)
{
GstStreamPeriod *stream_period;
GstMultSegmentBaseType *base = NULL;
if (base == NULL || base->SegBaseType == NULL) {
/* this may happen when we have a single segment */
duration = stream_period->duration;
+ if (scale_dur)
+ *scale_dur = duration;
} else {
duration = base->duration * GST_SECOND;
+ if (scale_dur)
+ *scale_dur = duration;
timescale = base->SegBaseType->timescale;
if (timescale > 1)
return stream->baseURL;
}
+static gboolean
+gst_mpdparser_find_segment_by_index (GstMpdClient * client,
+ GPtrArray * segments, gint index, GstMediaSegment * result)
+{
+ gint i;
+ for (i = 0; i < segments->len; i++) {
+ GstMediaSegment *s;
+
+ s = g_ptr_array_index (segments, i);
+ if (s->number + s->repeat >= index) {
+ /* it is in this segment */
+ result->SegmentURL = s->SegmentURL;
+ result->number = index;
+ result->scale_start =
+ s->scale_start + (index - s->number) * s->scale_duration;
+ result->scale_duration = s->scale_duration;
+ result->start = s->start + (index - s->number) * s->duration;
+ result->duration = s->duration;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
gboolean
gst_mpdparser_get_chunk_by_index (GstMpdClient * client, guint indexStream,
guint indexChunk, GstMediaSegment * segment)
stream = g_list_nth_data (client->active_streams, indexStream);
g_return_val_if_fail (stream != NULL, FALSE);
- if (stream->segments) {
- GstMediaSegment *list_segment;
- /* fixed list of segments */
- if (indexChunk >= stream->segments->len)
- return FALSE;
+ indexChunk += 1;
- list_segment = g_ptr_array_index (stream->segments, indexChunk);
- segment->SegmentURL = list_segment->SegmentURL;
- segment->number = list_segment->number;
- segment->start = list_segment->start;
- segment->start_time = list_segment->start_time;
- segment->duration = list_segment->duration;
+ if (stream->segments) {
+ return gst_mpdparser_find_segment_by_index (client, stream->segments,
+ indexChunk, segment);
} else {
GstClockTime duration;
GstStreamPeriod *stream_period;
+ gint64 scale_dur;
g_return_val_if_fail (stream->cur_seg_template->MultSegBaseType->
SegmentTimeline == NULL, FALSE);
/* segment template generator */
- duration = gst_mpd_client_get_segment_duration (client, stream);
+ duration = gst_mpd_client_get_segment_duration (client, stream, &scale_dur);
if (!GST_CLOCK_TIME_IS_VALID (duration))
return FALSE;
segment->number = indexChunk
+ stream->cur_seg_template->MultSegBaseType->startNumber;
- segment->start_time = duration * indexChunk;
+ segment->scale_start = indexChunk * scale_dur;
+ segment->scale_duration = scale_dur;
+ segment->start = duration * indexChunk;
segment->duration = duration;
segment->SegmentURL = NULL;
- if (segment->start_time >= stream_period->duration) {
+ if (segment->start >= stream_period->duration) {
return FALSE;
}
}
static gboolean
gst_mpd_client_add_media_segment (GstActiveStream * stream,
- GstSegmentURLNode * url_node, guint number, guint64 start,
- GstClockTime start_time, GstClockTime duration)
+ GstSegmentURLNode * url_node, guint number, gint repeat,
+ gint64 scale_start, gint64 scale_duration,
+ GstClockTime start, GstClockTime duration)
{
GstMediaSegment *media_segment;
media_segment->SegmentURL = url_node;
media_segment->number = number;
+ media_segment->scale_start = scale_start;
+ media_segment->scale_duration = scale_duration;
media_segment->start = start;
- media_segment->start_time = start_time;
media_segment->duration = duration;
+ media_segment->repeat = repeat;
g_ptr_array_add (stream->segments, media_segment);
- GST_LOG ("Added new segment: number %d, ts: %" GST_TIME_FORMAT ", dur: %"
- GST_TIME_FORMAT " start time %" GST_TIME_FORMAT, number,
- GST_TIME_ARGS (start), GST_TIME_ARGS (duration),
- GST_TIME_ARGS (start_time));
+ GST_LOG ("Added new segment: number %d, repeat %d, "
+ "ts: %" GST_TIME_FORMAT ", dur: %"
+ GST_TIME_FORMAT, number, repeat,
+ GST_TIME_ARGS (start), GST_TIME_ARGS (duration));
return TRUE;
}
stream->cur_adapt_set, representation)) == NULL) {
GST_DEBUG ("No useful SegmentList node for the current Representation");
/* here we should have a single segment for each representation, whose URL is encoded in the baseURL element */
- if (!gst_mpd_client_add_media_segment (stream, NULL, 1, 0, PeriodStart,
- PeriodEnd)) {
+ if (!gst_mpd_client_add_media_segment (stream, NULL, 1, 0, 0,
+ PeriodEnd - PeriodStart, PeriodStart, PeriodEnd)) {
return FALSE;
}
} else {
timeline = stream->cur_segment_list->MultSegBaseType->SegmentTimeline;
for (list = g_queue_peek_head_link (&timeline->S); list;
list = g_list_next (list)) {
- guint j, timescale;
+ guint timescale;
S = (GstSNode *) list->data;
GST_LOG ("Processing S node: d=%" G_GUINT64_FORMAT " r=%d t=%"
start_time /= timescale;
}
- for (j = 0; j <= S->r && SegmentURL != NULL; j++) {
- if (!gst_mpd_client_add_media_segment (stream, SegmentURL->data, i,
- start, start_time, duration)) {
- return FALSE;
- }
- i++;
- start += S->d;
- start_time += duration;
- SegmentURL = g_list_next (SegmentURL);
+ if (!gst_mpd_client_add_media_segment (stream, SegmentURL->data, i,
+ S->r, start, S->d, start_time, duration)) {
+ return FALSE;
}
+ i += S->r + 1;
+ start_time += duration * (S->r + 1);
+ start += S->d * (S->r + 1);
+ SegmentURL = g_list_next (SegmentURL);
}
} else {
- duration = gst_mpd_client_get_segment_duration (client, stream);
+ gint64 scale_dur;
+
+ duration =
+ gst_mpd_client_get_segment_duration (client, stream, &scale_dur);
if (!GST_CLOCK_TIME_IS_VALID (duration))
return FALSE;
while (SegmentURL) {
- if (!gst_mpd_client_add_media_segment (stream, SegmentURL->data, i, 0,
- start_time, duration)) {
+ if (!gst_mpd_client_add_media_segment (stream, SegmentURL->data, i,
+ 0, start, scale_dur, start_time, duration)) {
return FALSE;
}
i++;
+ start += scale_dur;
start_time += duration;
SegmentURL = g_list_next (SegmentURL);
}
gst_mpdparser_init_active_stream_segments (stream);
/* here we should have a single segment for each representation, whose URL is encoded in the baseURL element */
- if (!gst_mpd_client_add_media_segment (stream, NULL, 1, 0, 0, PeriodEnd)) {
+ if (!gst_mpd_client_add_media_segment (stream, NULL, 1, 0, 0, PeriodEnd,
+ 0, PeriodEnd)) {
return FALSE;
}
} else {
gst_mpdparser_init_active_stream_segments (stream);
for (list = g_queue_peek_head_link (&timeline->S); list;
list = g_list_next (list)) {
- guint j, timescale;
+ guint timescale;
S = (GstSNode *) list->data;
GST_LOG ("Processing S node: d=%" G_GUINT64_FORMAT " r=%u t=%"
start_time /= timescale;
}
- for (j = 0; j <= S->r; j++) {
- if (!gst_mpd_client_add_media_segment (stream, NULL, i, start,
- start_time, duration)) {
- return FALSE;
- }
- i++;
- start += S->d;
- start_time += duration;
+ if (!gst_mpd_client_add_media_segment (stream, NULL, i, S->r, start,
+ S->d, start_time, duration)) {
+ return FALSE;
}
+ i += S->r + 1;
+ start += S->d * (S->r + 1);
+ start_time += duration * (S->r + 1);
}
} else {
/* NOP - The segment is created on demand with the template, no need
g_ptr_array_index (stream->segments, stream->segments->len - 1) : NULL;
if (last_media_segment && GST_CLOCK_TIME_IS_VALID (PeriodEnd)) {
- if (last_media_segment->start_time + last_media_segment->duration >
- PeriodEnd) {
- last_media_segment->duration = PeriodEnd - last_media_segment->start_time;
+ if (last_media_segment->start + last_media_segment->duration > PeriodEnd) {
+ last_media_segment->duration = PeriodEnd - last_media_segment->start;
GST_LOG ("Fixed duration of last segment: %" GST_TIME_FORMAT,
GST_TIME_ARGS (last_media_segment->duration));
}
GstMediaSegment *segment = g_ptr_array_index (stream->segments, index);
GST_DEBUG ("Looking at fragment sequence chunk %d", index);
- if (segment->start_time <= ts
- && ts < segment->start_time + segment->duration) {
+ if (segment->start <= ts
+ && ts < segment->start + (segment->repeat + 1) * segment->duration) {
selectedChunk = segment;
+ index = segment->number + (ts - segment->start) / segment->duration;
break;
}
}
}
} else {
GstClockTime duration =
- gst_mpd_client_get_segment_duration (client, stream);
+ gst_mpd_client_get_segment_duration (client, stream, NULL);
g_return_val_if_fail (stream->cur_seg_template->
MultSegBaseType->SegmentTimeline == NULL, FALSE);
if (!GST_CLOCK_TIME_IS_VALID (duration)) {
gst_mpd_client_set_segment_index (stream, index);
-
return TRUE;
}
return FALSE;
}
- *ts = currentChunk.start_time;
+ *ts = currentChunk.start;
return TRUE;
}
return FALSE;
}
- *ts = currentChunk.start_time;
+ *ts = currentChunk.start;
return TRUE;
}
mediaURL =
gst_mpdparser_build_URL_from_template (stream->cur_seg_template->media,
stream->cur_representation->id, currentChunk.number,
- stream->cur_representation->bandwidth, currentChunk.start);
+ stream->cur_representation->bandwidth, currentChunk.scale_start);
if (stream->cur_seg_template->index) {
indexURL =
gst_mpdparser_build_URL_from_template (stream->
cur_seg_template->index, stream->cur_representation->id,
currentChunk.number, stream->cur_representation->bandwidth,
- currentChunk.start);
+ currentChunk.scale_start);
}
}
GST_DEBUG ("mediaURL = %s", mediaURL);
GST_DEBUG ("indexURL = %s", indexURL);
- fragment->timestamp = currentChunk.start_time;
+ fragment->timestamp = currentChunk.start;
fragment->duration = currentChunk.duration;
fragment->discontinuity = segment_idx != currentChunk.number;
fragment->range_start = 0;
return media_segment == NULL ? 0 : media_segment->duration;
} else {
GstClockTime duration =
- gst_mpd_client_get_segment_duration (client, stream);
+ gst_mpd_client_get_segment_duration (client, stream, NULL);
g_return_val_if_fail (stream->cur_seg_template->MultSegBaseType->
SegmentTimeline == NULL, 0);
stream_period = gst_mpdparser_get_stream_period (client);
seg_idx = gst_mpd_client_get_segment_index (stream);
- seg_duration = gst_mpd_client_get_segment_duration (client, stream);
+ seg_duration = gst_mpd_client_get_segment_duration (client, stream, NULL);
if (seg_duration == 0)
return NULL;
availability_start_time = gst_mpd_client_get_availability_start_time (client);
g_return_val_if_fail (gst_mpd_client_is_live (client), 0);
- duration = gst_mpd_client_get_segment_duration (client, stream);
+ duration = gst_mpd_client_get_segment_duration (client, stream, NULL);
stream_now = g_date_time_difference (now, start);
g_date_time_unref (now);
g_date_time_unref (start);