dashdemux: fix playing of single-segment media streams

other fixes:
- fixed a buffering bug: now we stop buffering when we reach the end of manifest
- now gst_mpd_client_get_target_duration() always returns a valid duration
(in case of single-segment streams, we return either Period duration or mediaPresentation duration)
TODO: support SegmentTimeline
This commit is contained in:
Gianluca Gennari 2012-10-18 18:49:53 +02:00 committed by Thiago Santos
parent 5ade664680
commit b580ee8cd7
2 changed files with 53 additions and 34 deletions

View file

@ -1508,6 +1508,11 @@ gst_dash_demux_get_next_fragment_set (GstDashDemux * demux)
stream_idx, &discont, &next_fragment_uri, &duration, &timestamp)) {
GST_INFO_OBJECT (demux, "This manifest doesn't contain more fragments");
demux->end_of_manifest = TRUE;
if (GST_STATE (demux) != GST_STATE_PLAYING) {
/* Restart the pipeline regardless of the current buffering level */
gst_element_post_message (GST_ELEMENT (demux),
gst_message_new_buffering (GST_OBJECT (demux), 100));
}
gst_task_start (demux->stream_task);
return FALSE;
}

View file

@ -2501,43 +2501,52 @@ gst_mpd_client_setup_representation (GstMpdClient * client, GstActiveStream *str
/* get the first segment_base of the selected representation */
if ((stream->cur_segment_base =
gst_mpdparser_get_segment_base (client->cur_period, stream->cur_adapt_set, representation)) == NULL) {
GST_WARNING ("No valid SegmentBase node in the MPD file");
GST_DEBUG ("No useful SegmentBase node for the current Representation");
}
/* get the first segment_list of the selected representation */
if ((stream->cur_segment_list =
gst_mpdparser_get_segment_list (client->cur_period, stream->cur_adapt_set, representation)) == NULL) {
GST_WARNING ("No valid SegmentList node in the MPD file, aborting...");
return FALSE;
}
/* build the list of GstMediaSegment nodes from the SegmentList node */
SegmentURL = stream->cur_segment_list->SegmentURL;
if (SegmentURL == NULL) {
GST_WARNING ("No valid list of SegmentURL nodes in the MPD file, aborting...");
return FALSE;
}
/* build segment list */
i = stream->cur_segment_list->MultSegBaseType->startNumber;
start_time = 0;
duration = gst_mpd_client_get_target_duration (client);
while (SegmentURL) {
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 */
media_segment = g_slice_new0 (GstMediaSegment);
if (media_segment == NULL) {
GST_WARNING ("Allocation of GstMediaSegment struct failed!");
return FALSE;
}
stream->segments = g_list_append (stream->segments, media_segment);
/* TODO: support SegmentTimeline */
media_segment->SegmentURL = (GstSegmentURLNode *) SegmentURL->data;
media_segment->number = i;
media_segment->start_time = start_time;
media_segment->duration = duration;
i++;
start_time += duration;
SegmentURL = g_list_next (SegmentURL);
media_segment->number = 1;
media_segment->start_time = 0;
media_segment->duration = PeriodEnd;
} else {
/* build the list of GstMediaSegment nodes from the SegmentList node */
SegmentURL = stream->cur_segment_list->SegmentURL;
if (SegmentURL == NULL) {
GST_WARNING ("No valid list of SegmentURL nodes in the MPD file, aborting...");
return FALSE;
}
/* build segment list */
i = stream->cur_segment_list->MultSegBaseType->startNumber;
start_time = 0;
duration = gst_mpd_client_get_target_duration (client);
while (SegmentURL) {
media_segment = g_slice_new0 (GstMediaSegment);
if (media_segment == NULL) {
GST_WARNING ("Allocation of GstMediaSegment struct failed!");
return FALSE;
}
stream->segments = g_list_append (stream->segments, media_segment);
/* TODO: support SegmentTimeline */
media_segment->SegmentURL = (GstSegmentURLNode *) SegmentURL->data;
media_segment->number = i;
media_segment->start_time = start_time;
media_segment->duration = duration;
i++;
start_time += duration;
SegmentURL = g_list_next (SegmentURL);
}
}
} else {
if (representation->SegmentTemplate != NULL) {
@ -2836,7 +2845,6 @@ gst_mpd_client_get_current_position (GstMpdClient * client,
*timestamp = GST_CLOCK_TIME_NONE;
/* select stream TODO: support multiple streams */
stream = g_list_nth_data (client->active_streams, client->stream_idx);
g_return_if_fail (stream != NULL);
@ -2882,15 +2890,21 @@ gst_mpd_client_get_target_duration (GstMpdClient * client)
}
if (base == NULL || base->SegBaseType == NULL) {
return GST_CLOCK_TIME_NONE;
/* this may happen when we have a single segment */
/* TODO: support SegmentTimeline */
if (client->cur_period->duration) {
duration = client->cur_period->duration * GST_MSECOND;
} else {
duration = client->mpd_node->mediaPresentationDuration * GST_MSECOND;
}
} else {
duration = base->duration * GST_SECOND;
timescale = base->SegBaseType->timescale;
if (timescale > 1)
duration /= timescale;
}
duration = base->duration * GST_SECOND;
timescale = base->SegBaseType->timescale;
if (timescale > 1)
duration /= timescale;
return duration;
}