dashdemux: complete support for manifest file updates

This commit is contained in:
Gianluca Gennari 2012-12-17 15:19:33 +01:00 committed by Thiago Santos
parent 7092a9c1ac
commit e0c55050e1
3 changed files with 73 additions and 28 deletions

View file

@ -508,7 +508,7 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
GST_TIME_FORMAT, rate, start_type, GST_TIME_ARGS (start), GST_TIME_FORMAT, rate, start_type, GST_TIME_ARGS (start),
GST_TIME_ARGS (stop)); GST_TIME_ARGS (stop));
GST_MPD_CLIENT_LOCK (demux->client); //GST_MPD_CLIENT_LOCK (demux->client);
/* select the requested Period in the Media Presentation */ /* select the requested Period in the Media Presentation */
target_pos = (GstClockTime) start; target_pos = (GstClockTime) start;
@ -545,7 +545,7 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
break; break;
} }
} }
GST_MPD_CLIENT_UNLOCK (demux->client); //GST_MPD_CLIENT_UNLOCK (demux->client);
if (list == NULL) { if (list == NULL) {
GST_WARNING_OBJECT (demux, "Could not find seeked fragment"); GST_WARNING_OBJECT (demux, "Could not find seeked fragment");
@ -576,21 +576,15 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
/* FIXME: allow seeking in the buffering queue */ /* FIXME: allow seeking in the buffering queue */
gst_dash_demux_clear_queue (demux); gst_dash_demux_clear_queue (demux);
GST_MPD_CLIENT_LOCK (demux->client); //GST_MPD_CLIENT_LOCK (demux->client);
GST_DEBUG_OBJECT (demux, "Seeking to sequence %d", current_sequence); GST_DEBUG_OBJECT (demux, "Seeking to sequence %d", current_sequence);
/* Update the current sequence on all streams */ /* Update the current sequence on all streams */
for (stream_idx = 0; stream_idx < nb_active_stream; stream_idx++) { gst_mpd_client_set_segment_index_for_all_streams (demux->client, current_sequence);
stream =
gst_mpdparser_get_active_stream_by_index (demux->client,
stream_idx);
gst_mpd_client_set_segment_index (stream, current_sequence);
}
/* Calculate offset in the next fragment */ /* Calculate offset in the next fragment */
demux->position = gst_mpd_client_get_current_position (demux->client); demux->position = gst_mpd_client_get_current_position (demux->client);
demux->position_shift = start - demux->position; demux->position_shift = start - demux->position;
demux->need_segment = TRUE; demux->need_segment = TRUE;
GST_MPD_CLIENT_UNLOCK (demux->client); //GST_MPD_CLIENT_UNLOCK (demux->client);
if (flags & GST_SEEK_FLAG_FLUSH) { if (flags & GST_SEEK_FLAG_FLUSH) {
GST_DEBUG_OBJECT (demux, "Sending flush stop on all pad"); GST_DEBUG_OBJECT (demux, "Sending flush stop on all pad");
@ -624,6 +618,7 @@ gst_dash_demux_setup_all_streams (GstDashDemux * demux)
guint i, nb_audio; guint i, nb_audio;
gchar *lang; gchar *lang;
GST_MPD_CLIENT_LOCK (demux->client);
/* clean old active stream list, if any */ /* clean old active stream list, if any */
gst_active_streams_free (demux->client); gst_active_streams_free (demux->client);
@ -649,6 +644,7 @@ gst_dash_demux_setup_all_streams (GstDashDemux * demux)
GST_STREAM_APPLICATION, lang)) GST_STREAM_APPLICATION, lang))
GST_INFO_OBJECT (demux, "No application adaptation set found"); GST_INFO_OBJECT (demux, "No application adaptation set found");
} }
GST_MPD_CLIENT_UNLOCK (demux->client);
return TRUE; return TRUE;
} }
@ -712,6 +708,9 @@ gst_dash_demux_sink_event (GstPad * pad, GstEvent * event)
!gst_dash_demux_setup_all_streams (demux)) !gst_dash_demux_setup_all_streams (demux))
return FALSE; return FALSE;
/* start playing from the first segment */
gst_mpd_client_set_segment_index_for_all_streams (demux->client, 0);
/* Send duration message */ /* Send duration message */
if (!gst_mpd_client_is_live (demux->client)) { if (!gst_mpd_client_is_live (demux->client)) {
GstClockTime duration = GstClockTime duration =
@ -1230,7 +1229,12 @@ gst_dash_demux_download_loop (GstDashDemux * demux)
GST_WARNING_OBJECT (demux, "Error parsing the manifest."); GST_WARNING_OBJECT (demux, "Error parsing the manifest.");
gst_buffer_unref (buffer); gst_buffer_unref (buffer);
} else { } else {
GstActiveStream *stream;
guint segment_index;
gst_buffer_unref (buffer); gst_buffer_unref (buffer);
stream = gst_mpdparser_get_active_stream_by_index (demux->client, 0);
segment_index = gst_mpd_client_get_segment_index (stream);
/* setup video, audio and subtitle streams, starting from first Period */ /* setup video, audio and subtitle streams, starting from first Period */
if (!gst_mpd_client_setup_media_presentation (demux->client) || if (!gst_mpd_client_setup_media_presentation (demux->client) ||
!gst_mpd_client_set_period_index (demux->client, gst_mpd_client_get_period_index (demux->client)) || !gst_mpd_client_set_period_index (demux->client, gst_mpd_client_get_period_index (demux->client)) ||
@ -1238,6 +1242,10 @@ gst_dash_demux_download_loop (GstDashDemux * demux)
GST_DEBUG_OBJECT (demux, "Error setting up the updated manifest file"); GST_DEBUG_OBJECT (demux, "Error setting up the updated manifest file");
goto end_of_manifest; goto end_of_manifest;
} }
/* continue playing from the the next segment */
/* FIXME: support multiple streams with different segment duration */
gst_mpd_client_set_segment_index_for_all_streams (demux->client, segment_index);
/* Send an updated duration message */ /* Send an updated duration message */
duration = gst_mpd_client_get_media_presentation_duration (demux->client); duration = gst_mpd_client_get_media_presentation_duration (demux->client);
@ -1298,6 +1306,8 @@ gst_dash_demux_download_loop (GstDashDemux * demux)
gst_task_start (demux->stream_task); gst_task_start (demux->stream_task);
goto end_of_manifest; goto end_of_manifest;
} }
/* start playing from the first segment of the new period */
gst_mpd_client_set_segment_index_for_all_streams (demux->client, 0);
demux->end_of_period = FALSE; demux->end_of_period = FALSE;
} else if (!demux->cancelled) { } else if (!demux->cancelled) {
demux->client->update_failed_count++; demux->client->update_failed_count++;

View file

@ -70,7 +70,7 @@ static void gst_mpdparser_parse_period_node (GList ** list, xmlNode * a_node);
static void gst_mpdparser_parse_program_info_node (GList ** list, xmlNode * a_node); static void gst_mpdparser_parse_program_info_node (GList ** list, xmlNode * a_node);
static void gst_mpdparser_parse_metrics_range_node (GList ** list, xmlNode * a_node); static void gst_mpdparser_parse_metrics_range_node (GList ** list, xmlNode * a_node);
static void gst_mpdparser_parse_metrics_node (GList ** list, xmlNode * a_node); static void gst_mpdparser_parse_metrics_node (GList ** list, xmlNode * a_node);
static void gst_mpdparser_parse_root_node (GstMpdClient * client, xmlNode *a_node); static void gst_mpdparser_parse_root_node (GstMPDNode ** pointer, xmlNode * a_node);
/* Helper functions */ /* Helper functions */
static gint convert_to_millisecs (gint decimals, gint pos); static gint convert_to_millisecs (gint decimals, gint pos);
@ -84,6 +84,7 @@ static gchar *gst_mpdparser_build_URL_from_template (const gchar *url_template,
static gboolean gst_mpd_client_add_media_segment (GstActiveStream *stream, GstSegmentURLNode *url_node, guint number, guint start, GstClockTime start_time, GstClockTime duration); static gboolean gst_mpd_client_add_media_segment (GstActiveStream *stream, GstSegmentURLNode *url_node, guint number, guint start, GstClockTime start_time, GstClockTime duration);
static const gchar *gst_mpdparser_mimetype_to_caps (const gchar * mimeType); static const gchar *gst_mpdparser_mimetype_to_caps (const gchar * mimeType);
static GstClockTime gst_mpd_client_get_segment_duration (GstMpdClient * client); static GstClockTime gst_mpd_client_get_segment_duration (GstMpdClient * client);
static void gst_mpd_client_set_segment_index (GstActiveStream * stream, guint segment_idx);
/* Adaptation Set */ /* Adaptation Set */
static GstAdaptationSetNode *gst_mpdparser_get_first_adapt_set_with_mimeType (GList *AdaptationSets, const gchar *mimeType); static GstAdaptationSetNode *gst_mpdparser_get_first_adapt_set_with_mimeType (GList *AdaptationSets, const gchar *mimeType);
@ -1487,13 +1488,13 @@ gst_mpdparser_parse_metrics_node (GList ** list, xmlNode * a_node)
} }
static void static void
gst_mpdparser_parse_root_node (GstMpdClient * client, xmlNode *a_node) gst_mpdparser_parse_root_node (GstMPDNode ** pointer, xmlNode * a_node)
{ {
xmlNode *cur_node; xmlNode *cur_node;
GstMPDNode *new_mpd; GstMPDNode *new_mpd;
gst_mpdparser_free_mpd_node (client->mpd_node); gst_mpdparser_free_mpd_node (*pointer);
client->mpd_node = new_mpd = g_slice_new0 (GstMPDNode); *pointer = new_mpd = g_slice_new0 (GstMPDNode);
if (new_mpd == NULL) { if (new_mpd == NULL) {
GST_WARNING ("Allocation of MPD node failed!"); GST_WARNING ("Allocation of MPD node failed!");
return; return;
@ -2258,7 +2259,7 @@ gst_mpdparser_get_stream_period (GstMpdClient * client)
g_return_val_if_fail (client != NULL, NULL); g_return_val_if_fail (client != NULL, NULL);
g_return_val_if_fail (client->periods != NULL, NULL); g_return_val_if_fail (client->periods != NULL, NULL);
return g_list_nth_data (client->periods, gst_mpd_client_get_period_index (client)); return g_list_nth_data (client->periods, client->period_idx);
} }
/* select a stream and extract the baseURL (if present) */ /* select a stream and extract the baseURL (if present) */
@ -2446,7 +2447,7 @@ gst_mpd_parse (GstMpdClient * client, const gchar * data, gint size)
GST_ERROR ("can not find the root element MPD, failed to parse the MPD file"); GST_ERROR ("can not find the root element MPD, failed to parse the MPD file");
} else { } else {
/* now we can parse the MPD root node and all children nodes, recursively */ /* now we can parse the MPD root node and all children nodes, recursively */
gst_mpdparser_parse_root_node (client, root_element); gst_mpdparser_parse_root_node (&client->mpd_node, root_element);
} }
/* free the document */ /* free the document */
xmlFreeDoc (doc); xmlFreeDoc (doc);
@ -2726,6 +2727,7 @@ gst_mpd_client_setup_media_presentation (GstMpdClient *client)
g_return_val_if_fail (client->mpd_node != NULL, FALSE); g_return_val_if_fail (client->mpd_node != NULL, FALSE);
GST_DEBUG ("Building the list of Periods in the Media Presentation"); GST_DEBUG ("Building the list of Periods in the Media Presentation");
GST_MPD_CLIENT_LOCK (client);
/* clean the old period list, if any */ /* clean the old period list, if any */
if (client->periods) { if (client->periods) {
g_list_foreach (client->periods, g_list_foreach (client->periods,
@ -2786,18 +2788,22 @@ gst_mpd_client_setup_media_presentation (GstMpdClient *client)
GST_TIME_FORMAT, idx, GST_TIME_ARGS (start), GST_TIME_ARGS (duration)); GST_TIME_FORMAT, idx, GST_TIME_ARGS (start), GST_TIME_ARGS (duration));
} }
GST_MPD_CLIENT_UNLOCK (client);
GST_DEBUG ("Found a total of %d valid Periods in the Media Presentation", idx); GST_DEBUG ("Found a total of %d valid Periods in the Media Presentation", idx);
return ret; return ret;
early: early:
GST_MPD_CLIENT_UNLOCK (client);
GST_WARNING ("Found an Early Available Period, skipping the rest of the Media Presentation"); GST_WARNING ("Found an Early Available Period, skipping the rest of the Media Presentation");
return ret; return ret;
syntax_error: syntax_error:
GST_MPD_CLIENT_UNLOCK (client);
GST_WARNING ("Cannot get the duration of the Period %d, skipping the rest of the Media Presentation", idx); GST_WARNING ("Cannot get the duration of the Period %d, skipping the rest of the Media Presentation", idx);
return ret; return ret;
no_mem: no_mem:
GST_MPD_CLIENT_UNLOCK (client);
GST_WARNING ("Allocation of GstStreamPeriod struct failed!"); GST_WARNING ("Allocation of GstStreamPeriod struct failed!");
return FALSE; return FALSE;
} }
@ -2882,9 +2888,7 @@ gst_mpd_client_setup_streaming (GstMpdClient * client,
stream->baseURL_idx = 0; stream->baseURL_idx = 0;
stream->mimeType = mimeType; stream->mimeType = mimeType;
stream->representation_idx = 0;
stream->cur_adapt_set = adapt_set; stream->cur_adapt_set = adapt_set;
gst_mpd_client_set_segment_index (stream, 0);
/* retrive representation list */ /* retrive representation list */
if (stream->cur_adapt_set != NULL) if (stream->cur_adapt_set != NULL)
@ -3062,34 +3066,65 @@ gboolean
gst_mpd_client_set_period_index (GstMpdClient *client, guint period_idx) gst_mpd_client_set_period_index (GstMpdClient *client, guint period_idx)
{ {
GstStreamPeriod *next_stream_period; GstStreamPeriod *next_stream_period;
gboolean ret = FALSE;
g_return_val_if_fail (client != NULL, FALSE); g_return_val_if_fail (client != NULL, FALSE);
g_return_val_if_fail (client->periods != NULL, FALSE); g_return_val_if_fail (client->periods != NULL, FALSE);
GST_MPD_CLIENT_LOCK (client);
next_stream_period = g_list_nth_data (client->periods, period_idx); next_stream_period = g_list_nth_data (client->periods, period_idx);
if (next_stream_period == NULL) if (next_stream_period != NULL) {
return FALSE; client->period_idx = period_idx;
ret = TRUE;
}
GST_MPD_CLIENT_UNLOCK (client);
client->period_idx = period_idx; return ret;
return TRUE;
} }
guint guint
gst_mpd_client_get_period_index (GstMpdClient *client) gst_mpd_client_get_period_index (GstMpdClient *client)
{ {
return client->period_idx; guint period_idx;
g_return_val_if_fail (client != NULL, 0);
GST_MPD_CLIENT_LOCK (client);
period_idx = client->period_idx;
GST_MPD_CLIENT_UNLOCK (client);
return period_idx;
} }
void void
gst_mpd_client_set_segment_index_for_all_streams (GstMpdClient *client, guint segment_idx)
{
GList *list;
g_return_if_fail (client != NULL);
g_return_if_fail (client->active_streams != NULL);
/* FIXME: support multiple streams with different segment duration */
for (list = g_list_first (client->active_streams); list; list = g_list_next (list)) {
GstActiveStream *stream = (GstActiveStream *) list->data;
if (stream) {
stream->segment_idx = segment_idx;
}
}
}
static void
gst_mpd_client_set_segment_index (GstActiveStream * stream, guint segment_idx) gst_mpd_client_set_segment_index (GstActiveStream * stream, guint segment_idx)
{ {
g_return_if_fail (stream != NULL);
stream->segment_idx = segment_idx; stream->segment_idx = segment_idx;
} }
guint guint
gst_mpd_client_get_segment_index (GstActiveStream * stream) gst_mpd_client_get_segment_index (GstActiveStream * stream)
{ {
g_return_val_if_fail (stream != NULL, 0);
return stream->segment_idx; return stream->segment_idx;
} }
@ -3103,8 +3138,8 @@ gst_mpd_client_is_live (GstMpdClient * client)
} }
guint guint
gst_mpdparser_get_nb_active_stream (GstMpdClient *client){ gst_mpdparser_get_nb_active_stream (GstMpdClient *client)
{
g_return_val_if_fail (client != NULL, 0); g_return_val_if_fail (client != NULL, 0);
return g_list_length (client->active_streams); return g_list_length (client->active_streams);

View file

@ -493,7 +493,7 @@ GstActiveStream *gst_mpdparser_get_active_stream_by_index (GstMpdClient *client,
guint gst_mpdparser_get_nb_adaptationSet (GstMpdClient *client); guint gst_mpdparser_get_nb_adaptationSet (GstMpdClient *client);
/* Segment */ /* Segment */
void gst_mpd_client_set_segment_index (GstActiveStream * stream, guint segment_idx); void gst_mpd_client_set_segment_index_for_all_streams (GstMpdClient * client, guint segment_idx);
guint gst_mpd_client_get_segment_index (GstActiveStream * stream); guint gst_mpd_client_get_segment_index (GstActiveStream * stream);
/* Get audio/video stream parameters (mimeType, width, height, rate, number of channels) */ /* Get audio/video stream parameters (mimeType, width, height, rate, number of channels) */