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:
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;
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);
/* 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);
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,
}
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;
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 */
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))
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)));
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);
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 */
/* 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);
/* 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 =
"Can not switch representation, aborting...");
}
}
+#endif
i++;
}
return ret;
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);
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,
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);
}
*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");
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;
}
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) {
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;
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;
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
}
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;
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;
}
}
}
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,
/* 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;
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);
}
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) {
}
baseURL_array[2] = baseURL->baseURL;
}
+
if ((list = stream->cur_representation->BaseURLs) != NULL) {
baseURL = g_list_nth_data (list, stream->baseURL_idx);
if (!baseURL) {
}
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;
} 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;
}
g_free (stream->baseURL);
- stream->baseURL = gst_mpdparser_parse_baseURL (client);
+ stream->baseURL = gst_mpdparser_parse_baseURL (client, stream);
return TRUE;
}
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...");
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;
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;
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);