mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-09-09 05:38:58 +00:00
dashdemux: complete support for manifest file updates
This commit is contained in:
parent
7092a9c1ac
commit
e0c55050e1
3 changed files with 73 additions and 28 deletions
|
@ -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++;
|
||||||
|
|
|
@ -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;
|
client->period_idx = period_idx;
|
||||||
|
ret = TRUE;
|
||||||
|
}
|
||||||
|
GST_MPD_CLIENT_UNLOCK (client);
|
||||||
|
|
||||||
return TRUE;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -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) */
|
||||||
|
|
Loading…
Reference in a new issue