dashdemux: various fixes

This commit is contained in:
Louis-Francis Ratté-Boulianne 2013-01-16 13:58:52 -05:00 committed by Thiago Santos
parent c901f610c2
commit 04004cdf65
3 changed files with 111 additions and 39 deletions

View file

@ -474,6 +474,7 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
GstDashDemux *demux;
demux = GST_DASH_DEMUX (gst_pad_get_element_private (pad));
GST_WARNING_OBJECT (demux, "Received an event");
switch (event->type) {
case GST_EVENT_SEEK:
@ -492,6 +493,8 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
guint nb_active_stream;
guint stream_idx;
GST_WARNING_OBJECT (demux, "Received seek event");
if (gst_mpd_client_is_live (demux->client)) {
GST_WARNING_OBJECT (demux, "Received seek event for live stream");
return FALSE;
@ -537,15 +540,18 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
stream = gst_mpdparser_get_active_stream_by_index (demux->client, 0);
current_pos = 0;
current_sequence = 0;
for (list = g_list_first (stream->segments); list;
list = g_list_next (list)) {
chunk = list->data;
current_pos = chunk->start_time;
current_sequence = chunk->number;
//current_sequence = chunk->number;
GST_WARNING_OBJECT (demux, "%i <= %i (%i)", current_pos, target_pos, chunk->duration);
if (current_pos <= target_pos
&& target_pos < current_pos + chunk->duration) {
break;
}
current_sequence++;
}
//GST_MPD_CLIENT_UNLOCK (demux->client);
@ -601,6 +607,7 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
/* Restart the demux */
demux->cancelled = FALSE;
demux->end_of_manifest = FALSE;
gst_dash_demux_resume_download_task (demux);
gst_dash_demux_resume_stream_task (demux);
g_static_rec_mutex_unlock (&demux->stream_lock);
@ -637,10 +644,10 @@ gst_dash_demux_setup_all_streams (GstDashDemux * demux)
for (i = 0; i < nb_audio; i++) {
lang = (gchar *) g_list_nth_data (listLang, i);
if (gst_mpdparser_get_nb_adaptationSet (demux->client) > 1)
if (!gst_mpd_client_setup_streaming (demux->client, GST_STREAM_AUDIO,
lang))
GST_INFO_OBJECT (demux, "No audio adaptation set found");
GST_INFO ("nb adaptation set: %i", gst_mpdparser_get_nb_adaptationSet (demux->client));
if (!gst_mpd_client_setup_streaming (demux->client, GST_STREAM_AUDIO,
lang))
GST_INFO_OBJECT (demux, "No audio adaptation set found");
if (gst_mpdparser_get_nb_adaptationSet (demux->client) > nb_audio)
if (!gst_mpd_client_setup_streaming (demux->client,
@ -779,11 +786,13 @@ gst_dash_demux_src_query (GstPad * pad, GstQuery * query)
}
case GST_QUERY_SEEKING:{
GstFormat fmt;
gint64 start;
gint64 end;
gint64 stop = -1;
gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
GST_DEBUG_OBJECT (dashdemux, "Received GST_QUERY_SEEKING with format %d",
fmt);
gst_query_parse_seeking (query, &fmt, NULL, &start, &end);
GST_DEBUG_OBJECT (dashdemux, "Received GST_QUERY_SEEKING with format %d - %i %i",
fmt, start, end);
if (fmt == GST_FORMAT_TIME) {
GstClockTime duration;
@ -876,6 +885,8 @@ switch_pads (GstDashDemux * demux, guint nb_adaptation_set)
gst_pad_set_active (demux->srcpad[i], TRUE);
gst_pad_set_caps (demux->srcpad[i], demux->output_caps[i]);
gst_element_add_pad (GST_ELEMENT (demux), demux->srcpad[i]);
GST_INFO_OBJECT (demux, "Adding srcpad %s:%s with caps %" GST_PTR_FORMAT,
GST_DEBUG_PAD_NAME (demux->srcpad[i]), demux->output_caps[i]);
i++;
}
/* Send 'no-more-pads' to have decodebin create the new group */
@ -923,8 +934,7 @@ needs_pad_switch (GstDashDemux * demux, GList * fragment)
if (G_LIKELY (demux->srcpad[i]))
srccaps = gst_pad_get_negotiated_caps (demux->srcpad[i]);
if (G_UNLIKELY (!srccaps
|| (!gst_caps_is_equal_fixed (demux->output_caps[i], srccaps))
|| demux->need_segment)) {
|| (!gst_caps_is_equal_fixed (demux->output_caps[i], srccaps)))) {
switch_pad = TRUE;
}
if (G_LIKELY (srccaps))
@ -982,6 +992,7 @@ gst_dash_demux_stream_loop (GstDashDemux * demux)
demux->min_buffering_time) {
/* Warn we are below our threshold: this will eventually pause
* the pipeline */
GST_WARNING ("Below the threshold: this will eventually pause the pipeline");
gst_element_post_message (GST_ELEMENT (demux),
gst_message_new_buffering (GST_OBJECT (demux),
100 * gst_dash_demux_get_buffering_ratio (demux)));
@ -1007,10 +1018,9 @@ gst_dash_demux_stream_loop (GstDashDemux * demux)
gst_pad_push_event (demux->srcpad[i],
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
start, GST_CLOCK_TIME_NONE, start));
demux->position_shift = 0;
}
GST_DEBUG_OBJECT (demux, "Pushing fragment #%d", fragment->index);
GST_DEBUG_OBJECT (demux, "Pushing fragment #%d (stream %i)", fragment->index, i);
buffer_list = gst_fragment_get_buffer_list (fragment);
g_object_unref (fragment);
ret = gst_pad_push_list (demux->srcpad[i], buffer_list);
@ -1018,6 +1028,7 @@ gst_dash_demux_stream_loop (GstDashDemux * demux)
goto error_pushing;
}
demux->need_segment = FALSE;
demux->position_shift = 0;
g_list_free (listfragment);
if (GST_STATE (demux) == GST_STATE_PLAYING) {
/* Wait for the duration of a fragment before resuming this task */
@ -1284,6 +1295,7 @@ gst_dash_demux_download_loop (GstDashDemux * demux)
/* Target buffering time MUST at least exceeds mimimum buffering time
* by the duration of a fragment, but SHOULD NOT exceed maximum
* buffering time */
GST_DEBUG_OBJECT (demux, "download loop %i", demux->end_of_manifest);
GstClockTime target_buffering_time =
demux->min_buffering_time +
gst_mpd_client_get_next_fragment_duration (demux->client);
@ -1428,8 +1440,9 @@ gst_dash_demux_select_representations (GstDashDemux * demux, guint64 bitrate)
/* if no representation has the required bandwidth, take the lowest one */
if (new_index == -1)
new_index = 0;
new_index = gst_mpdparser_get_rep_idx_with_min_bandwidth (rep_list);
#if 0
if (new_index != stream->representation_idx) {
GST_MPD_CLIENT_LOCK (demux->client);
ret =
@ -1444,6 +1457,7 @@ gst_dash_demux_select_representations (GstDashDemux * demux, guint64 bitrate)
"Can not switch representation, aborting...");
}
}
#endif
i++;
}
return ret;
@ -1462,7 +1476,7 @@ gst_dash_demux_get_next_header (GstDashDemux * demux, guint stream_idx)
if (strncmp (initializationURL, "http://", 7) != 0) {
next_header_uri =
g_strconcat (gst_mpdparser_get_baseURL (demux->client),
g_strconcat (gst_mpdparser_get_baseURL (demux->client, stream_idx),
initializationURL, NULL);
} else {
next_header_uri = g_strdup (initializationURL);
@ -1673,6 +1687,7 @@ gst_dash_demux_get_next_fragment_set (GstDashDemux * demux)
return FALSE;
}
GST_INFO_OBJECT (demux, "Next fragment for stream #%i", stream_idx);
GST_INFO_OBJECT (demux, "Fetching next fragment %s", next_fragment_uri);
download = gst_uri_downloader_fetch_uri (demux->downloader,

View file

@ -108,10 +108,11 @@ static void gst_mpdparser_parse_root_node (GstMPDNode ** pointer,
static gint convert_to_millisecs (gint decimals, gint pos);
static int strncmp_ext (const char *s1, const char *s2);
static GstStreamPeriod *gst_mpdparser_get_stream_period (GstMpdClient * client);
static gchar *gst_mpdparser_parse_baseURL (GstMpdClient * client);
static gchar *gst_mpdparser_parse_baseURL (GstMpdClient * client,
GstActiveStream *stream);
static gchar *gst_mpdparser_get_segmentURL_for_range (gchar * url,
GstRange * range);
static gchar *gst_mpdparser_get_mediaURL (GstMpdClient * client,
static gchar *gst_mpdparser_get_mediaURL (GstActiveStream * stream,
GstSegmentURLNode * segmentURL);
static gchar *gst_mpdparser_get_initializationURL (GstURLType *
InitializationURL);
@ -1463,6 +1464,8 @@ gst_mpdparser_parse_period_node (GList ** list, xmlNode * a_node)
}
*list = g_list_append (*list, new_period);
new_period->start = GST_CLOCK_TIME_NONE;
GST_LOG ("attributes of Period node:");
new_period->id = gst_mpdparser_get_xml_prop_string (a_node, "id");
new_period->start = gst_mpdparser_get_xml_prop_duration (a_node, "start");
@ -1681,6 +1684,7 @@ gst_mpdparser_get_first_adapt_set_with_mimeType (GList * AdaptationSets,
if (!this_mimeType && adapt_set->RepresentationBase) {
this_mimeType = adapt_set->RepresentationBase->mimeType;
}
GST_DEBUG("Looking for mime type %s -> %s", mimeType, this_mimeType);
if (strncmp_ext (this_mimeType, mimeType) == 0)
return adapt_set;
}
@ -1703,6 +1707,8 @@ gst_mpdparser_get_adapt_set_with_mimeType_and_idx (GList * AdaptationSets,
if (AdaptationSets == NULL)
return NULL;
// FIXME Use ContentComponent to determine if this adaptation set contains
// the content type we're looking for.
for (list = g_list_first (AdaptationSets); list; list = g_list_next (list)) {
adapt_set = (GstAdaptationSetNode *) list->data;
if (adapt_set) {
@ -1712,9 +1718,9 @@ gst_mpdparser_get_adapt_set_with_mimeType_and_idx (GList * AdaptationSets,
gst_mpdparser_get_lowest_representation (adapt_set->Representations);
if (rep->RepresentationBase)
this_mimeType = rep->RepresentationBase->mimeType;
if (!this_mimeType && adapt_set->RepresentationBase) {
if (!this_mimeType && adapt_set->RepresentationBase)
this_mimeType = adapt_set->RepresentationBase->mimeType;
}
GST_DEBUG("Looking for mime type %s -> %i: %s", mimeType, i, this_mimeType);
if (strncmp_ext (this_mimeType, mimeType) == 0) {
if (idx < 0 || i <= idx)
selected = adapt_set;
@ -1744,11 +1750,16 @@ gst_mpdparser_get_first_adapt_set_with_mimeType_and_lang (GList *
gchar *this_mimeType = NULL;
rep =
gst_mpdparser_get_lowest_representation (adapt_set->Representations);
if (rep && rep->BaseURLs) {
GstBaseURL *url = rep->BaseURLs->data;
GST_DEBUG("%s", url->baseURL);
}
if (rep->RepresentationBase)
this_mimeType = rep->RepresentationBase->mimeType;
if (!this_mimeType && adapt_set->RepresentationBase) {
this_mimeType = adapt_set->RepresentationBase->mimeType;
}
GST_DEBUG("Looking for mime type %s -> %s", mimeType, this_mimeType);
if (strncmp_ext (this_mimeType, mimeType) == 0
&& strncmp_ext (this_lang, lang) == 0)
return adapt_set;
@ -1762,13 +1773,20 @@ static GstRepresentationNode *
gst_mpdparser_get_lowest_representation (GList * Representations)
{
GList *list = NULL;
GstRepresentationNode *rep = NULL;
GstRepresentationNode *lowest = NULL;
if (Representations == NULL)
return NULL;
list = g_list_first (Representations);
for (list = g_list_first (Representations); list; list = g_list_next (list)) {
rep = (GstRepresentationNode *) list->data;
if (rep && (!lowest || rep->bandwidth < lowest->bandwidth)) {
lowest = rep;
}
}
return list ? (GstRepresentationNode *) list->data : NULL;
return lowest;
}
#if 0
@ -1851,12 +1869,36 @@ gst_mpdparser_get_segment_base (GstPeriodNode * Period,
return SegmentBase;
}
gint
gst_mpdparser_get_rep_idx_with_min_bandwidth (GList * Representations)
{
GList *list = NULL, *lowest;
GstRepresentationNode *rep = NULL;
gint lowest_bandwidth = -1;
if (Representations == NULL)
return NULL;
for (list = g_list_first (Representations); list; list = g_list_next (list)) {
rep = (GstRepresentationNode *) list->data;
if (rep && (!lowest || rep->bandwidth < lowest_bandwidth)) {
lowest = list;
lowest_bandwidth = rep->bandwidth;
}
}
return lowest ? g_list_position (Representations, lowest) : -1;
}
gint
gst_mpdparser_get_rep_idx_with_max_bandwidth (GList * Representations,
gint max_bandwidth)
{
GList *list = NULL, *best = NULL;
GstRepresentationNode *representation;
gint best_bandwidth = 0;
GST_DEBUG ("max_bandwidth = %i", max_bandwidth);
if (Representations == NULL)
return -1;
@ -1866,8 +1908,10 @@ gst_mpdparser_get_rep_idx_with_max_bandwidth (GList * Representations,
for (list = g_list_first (Representations); list; list = g_list_next (list)) {
representation = (GstRepresentationNode *) list->data;
if (representation && representation->bandwidth <= max_bandwidth) {
if (representation && representation->bandwidth <= max_bandwidth &&
representation->bandwidth > best_bandwidth) {
best = list;
best_bandwidth = representation->bandwidth;
}
}
@ -2280,17 +2324,15 @@ gst_mpdparser_get_segmentURL_for_range (gchar * url, GstRange * range)
}
static gchar *
gst_mpdparser_get_mediaURL (GstMpdClient * client,
gst_mpdparser_get_mediaURL (GstActiveStream *stream,
GstSegmentURLNode * segmentURL)
{
const gchar *url_prefix;
g_return_val_if_fail (client != NULL, NULL);
g_return_val_if_fail (stream != NULL, NULL);
g_return_val_if_fail (segmentURL != NULL, NULL);
url_prefix =
segmentURL->media ? segmentURL->
media : gst_mpdparser_get_baseURL (client);
url_prefix = segmentURL->media ? segmentURL->media : stream->baseURL;
g_return_val_if_fail (url_prefix != NULL, NULL);
return gst_mpdparser_get_segmentURL_for_range (segmentURL->media,
@ -2381,9 +2423,9 @@ gst_mpdparser_get_stream_period (GstMpdClient * client)
/* select a stream and extract the baseURL (if present) */
static gchar *
gst_mpdparser_parse_baseURL (GstMpdClient * client)
gst_mpdparser_parse_baseURL (GstMpdClient * client, GstActiveStream *stream)
{
GstActiveStream *stream;
//GstActiveStream *stream;
GstStreamPeriod *stream_period;
GstBaseURL *baseURL;
GList *list;
@ -2391,8 +2433,9 @@ gst_mpdparser_parse_baseURL (GstMpdClient * client)
static gchar empty[] = "";
gchar *ret = NULL;
stream =
gst_mpdparser_get_active_stream_by_index (client, client->stream_idx);
//stream =
// gst_mpdparser_get_active_stream_by_index (client, client->stream_idx);
g_return_val_if_fail (stream != NULL, empty);
stream_period = gst_mpdparser_get_stream_period (client);
g_return_val_if_fail (stream_period != NULL, empty);
@ -2417,6 +2460,9 @@ gst_mpdparser_parse_baseURL (GstMpdClient * client)
}
baseURL_array[1] = baseURL->baseURL;
}
GST_DEBUG("Current adaptation set id %i (%s)", stream->cur_adapt_set->id,
stream->cur_adapt_set->contentType);
if ((list = stream->cur_adapt_set->BaseURLs) != NULL) {
baseURL = g_list_nth_data (list, stream->baseURL_idx);
if (!baseURL) {
@ -2424,6 +2470,7 @@ gst_mpdparser_parse_baseURL (GstMpdClient * client)
}
baseURL_array[2] = baseURL->baseURL;
}
if ((list = stream->cur_representation->BaseURLs) != NULL) {
baseURL = g_list_nth_data (list, stream->baseURL_idx);
if (!baseURL) {
@ -2588,13 +2635,13 @@ gst_mpd_parse (GstMpdClient * client, const gchar * data, gint size)
}
const gchar *
gst_mpdparser_get_baseURL (GstMpdClient * client)
gst_mpdparser_get_baseURL (GstMpdClient * client, guint indexStream)
{
GstActiveStream *stream;
g_return_val_if_fail (client != NULL, NULL);
g_return_val_if_fail (client->active_streams != NULL, NULL);
stream = g_list_nth_data (client->active_streams, client->stream_idx);
stream = g_list_nth_data (client->active_streams, indexStream);
g_return_val_if_fail (stream != NULL, NULL);
return stream->baseURL;
@ -2822,10 +2869,11 @@ gst_mpd_client_setup_representation (GstMpdClient * client,
} else {
duration = gst_mpd_client_get_segment_duration (client);
if (!GST_CLOCK_TIME_IS_VALID (duration)
|| !GST_CLOCK_TIME_IS_VALID (PeriodEnd))
|| !GST_CLOCK_TIME_IS_VALID (PeriodEnd)
|| duration <= 0)
return FALSE;
while (PeriodStart + start_time < PeriodEnd) {
while (start_time < PeriodEnd) {
if (!gst_mpd_client_add_media_segment (stream, NULL, i, 0, start_time,
duration)) {
return FALSE;
@ -2850,7 +2898,7 @@ gst_mpd_client_setup_representation (GstMpdClient * client,
}
g_free (stream->baseURL);
stream->baseURL = gst_mpdparser_parse_baseURL (client);
stream->baseURL = gst_mpdparser_parse_baseURL (client, stream);
return TRUE;
}
@ -2966,6 +3014,9 @@ gst_mpd_client_setup_streaming (GstMpdClient * client,
GstRepresentationNode *representation;
GList *rep_list = NULL;
GstRepresentationNode *rep;
GstBaseURL *url;
stream_period = gst_mpdparser_get_stream_period (client);
if (stream_period == NULL || stream_period->period == NULL) {
GST_DEBUG ("No more Period nodes in the MPD file, terminating...");
@ -3043,6 +3094,8 @@ gst_mpd_client_setup_streaming (GstMpdClient * client,
stream->mimeType = mimeType;
stream->cur_adapt_set = adapt_set;
GST_DEBUG("0. Current stream %p", stream);
/* retrive representation list */
if (stream->cur_adapt_set != NULL)
rep_list = stream->cur_adapt_set->Representations;
@ -3106,23 +3159,25 @@ gst_mpd_client_get_next_fragment (GstMpdClient * client,
return FALSE;
}
GST_DEBUG("currentChunk->SegmentURL = %s", currentChunk->SegmentURL);
if (currentChunk->SegmentURL != NULL) {
mediaURL = gst_mpdparser_get_mediaURL (client, currentChunk->SegmentURL);
mediaURL = gst_mpdparser_get_mediaURL (stream, currentChunk->SegmentURL);
} else if (stream->cur_seg_template != NULL) {
mediaURL =
gst_mpdparser_build_URL_from_template (stream->cur_seg_template->media,
stream->cur_representation->id, currentChunk->number,
stream->cur_representation->bandwidth, currentChunk->start);
}
GST_DEBUG("mediaURL = %s", mediaURL);
*timestamp = currentChunk->start_time;
*duration = currentChunk->duration;
*discontinuity = segment_idx != currentChunk->number;
if (mediaURL == NULL) {
/* single segment with URL encoded in the baseURL syntax element */
*uri = g_strdup (gst_mpdparser_get_baseURL (client));
*uri = g_strdup (stream->baseURL);
} else if (strncmp (mediaURL, "http://", 7) != 0) {
*uri = g_strconcat (gst_mpdparser_get_baseURL (client), mediaURL, NULL);
*uri = g_strconcat (stream->baseURL, mediaURL, NULL);
g_free (mediaURL);
} else {
*uri = mediaURL;
@ -3199,6 +3254,7 @@ gst_mpd_client_get_next_fragment_duration (GstMpdClient * client)
GstActiveStream *stream;
GstMediaSegment *media_segment;
GST_WARNING ("Stream index: %i", client->stream_idx);
stream = g_list_nth_data (client->active_streams, client->stream_idx);
g_return_val_if_fail (stream != NULL, 0);

View file

@ -480,9 +480,10 @@ guint gst_mpd_client_get_period_index (GstMpdClient *client);
/* Representation selection */
gint gst_mpdparser_get_rep_idx_with_max_bandwidth (GList *Representations, gint max_bandwidth);
gint gst_mpdparser_get_rep_idx_with_min_bandwidth (GList * Representations);
/* URL management */
const gchar *gst_mpdparser_get_baseURL (GstMpdClient *client);
const gchar *gst_mpdparser_get_baseURL (GstMpdClient *client, guint indexStream);
GstMediaSegment *gst_mpdparser_get_chunk_by_index (GstMpdClient *client, guint indexStream, guint indexChunk);
/* Active stream */