mpdparser: fixed parsing of SegmentList syntax element, and eliminated Represention node list from Period node

SegmentList nodes are allowed into Period, AdaptationSet or Representation nodes
and there is at most 1 element, so no need to keep a list;

Period nodes cannot have any Represention elements, as AdaptationSet nodes are mandatory;
this breaks compatibility with some legacy DASH test sequences.
This commit is contained in:
Gianluca Gennari 2012-10-08 11:16:09 +02:00 committed by Thiago Santos
parent 8e3092661a
commit dd198bc86d
3 changed files with 49 additions and 39 deletions

View file

@ -1069,7 +1069,7 @@ static gboolean
gst_dash_demux_switch_playlist (GstDashDemux * demux, guint64 bitrate) gst_dash_demux_switch_playlist (GstDashDemux * demux, guint64 bitrate)
{ {
GstActiveStream *stream = NULL; GstActiveStream *stream = NULL;
GList *rep_list; GList *rep_list = NULL;
gint new_index; gint new_index;
gboolean ret = FALSE; gboolean ret = FALSE;
@ -1083,8 +1083,8 @@ gst_dash_demux_switch_playlist (GstDashDemux * demux, guint64 bitrate)
/* retrieve representation list */ /* retrieve representation list */
if (stream->cur_adapt_set) if (stream->cur_adapt_set)
rep_list = stream->cur_adapt_set->Representations; rep_list = stream->cur_adapt_set->Representations;
else if (!rep_list)
rep_list = demux->client->cur_period->Representations; return FALSE;
/* get representation index with current max_bandwidth */ /* get representation index with current max_bandwidth */
new_index = new_index =

View file

@ -60,7 +60,7 @@ static void gst_mpdparser_parse_seg_base_type_ext (GstSegmentBaseType ** pointer
static void gst_mpdparser_parse_s_node (GList ** list, xmlNode * a_node); static void gst_mpdparser_parse_s_node (GList ** list, xmlNode * a_node);
static void gst_mpdparser_parse_segment_timeline_node (GstSegmentTimelineNode ** pointer, xmlNode * a_node); static void gst_mpdparser_parse_segment_timeline_node (GstSegmentTimelineNode ** pointer, xmlNode * a_node);
static void gst_mpdparser_parse_mult_seg_base_type_ext (GstMultSegmentBaseType ** pointer, xmlNode * a_node); static void gst_mpdparser_parse_mult_seg_base_type_ext (GstMultSegmentBaseType ** pointer, xmlNode * a_node);
static void gst_mpdparser_parse_segment_list_node (GList ** list, xmlNode * a_node); static void gst_mpdparser_parse_segment_list_node (GstSegmentListNode ** pointer, xmlNode * a_node);
static void gst_mpdparser_parse_representation_base_type (GstRepresentationBaseType ** pointer, xmlNode * a_node); static void gst_mpdparser_parse_representation_base_type (GstRepresentationBaseType ** pointer, xmlNode * a_node);
static void gst_mpdparser_parse_representation_node (GList ** list, xmlNode * a_node); static void gst_mpdparser_parse_representation_node (GList ** list, xmlNode * a_node);
static void gst_mpdparser_parse_adaptation_set_node (GList ** list, xmlNode * a_node); static void gst_mpdparser_parse_adaptation_set_node (GList ** list, xmlNode * a_node);
@ -96,7 +96,7 @@ static GstRepresentationNode *gst_mpdparser_get_highest_representation (GList *
static GstRepresentationNode *gst_mpdparser_get_representation_with_max_bandwidth (GList * Representations, gint max_bandwidth); static GstRepresentationNode *gst_mpdparser_get_representation_with_max_bandwidth (GList * Representations, gint max_bandwidth);
#endif #endif
static GstSegmentBaseType *gst_mpdparser_get_segment_base (GstPeriodNode *Period, GstAdaptationSetNode * AdaptationSet, GstRepresentationNode * Representation); static GstSegmentBaseType *gst_mpdparser_get_segment_base (GstPeriodNode *Period, GstAdaptationSetNode * AdaptationSet, GstRepresentationNode * Representation);
static GstSegmentListNode *gst_mpdparser_get_first_segment_list (GList * SegmentList); static GstSegmentListNode *gst_mpdparser_get_segment_list (GstPeriodNode *Period, GstAdaptationSetNode * AdaptationSet, GstRepresentationNode * Representation);
/* Memory management */ /* Memory management */
static void gst_mpdparser_free_mpd_node (GstMPDNode * mpd_node); static void gst_mpdparser_free_mpd_node (GstMPDNode * mpd_node);
@ -1092,17 +1092,17 @@ gst_mpdparser_parse_mult_seg_base_type_ext (GstMultSegmentBaseType ** pointer, x
} }
static void static void
gst_mpdparser_parse_segment_list_node (GList ** list, xmlNode * a_node) gst_mpdparser_parse_segment_list_node (GstSegmentListNode ** pointer, xmlNode * a_node)
{ {
xmlNode *cur_node; xmlNode *cur_node;
GstSegmentListNode *new_segment_list; GstSegmentListNode *new_segment_list;
new_segment_list = g_slice_new0 (GstSegmentListNode); gst_mpdparser_free_segment_list_node (*pointer);
*pointer = new_segment_list = g_slice_new0 (GstSegmentListNode);
if (new_segment_list == NULL) { if (new_segment_list == NULL) {
GST_WARNING ("Allocation of SegmentList node failed!"); GST_WARNING ("Allocation of SegmentList node failed!");
return; return;
} }
*list = g_list_append (*list, new_segment_list);
GST_LOG ("extension of SegmentList node:"); GST_LOG ("extension of SegmentList node:");
gst_mpdparser_parse_mult_seg_base_type_ext (&new_segment_list->MultSegBaseType, a_node); gst_mpdparser_parse_mult_seg_base_type_ext (&new_segment_list->MultSegBaseType, a_node);
@ -1292,6 +1292,8 @@ gst_mpdparser_parse_adaptation_set_node (GList ** list, xmlNode * a_node)
gst_mpdparser_parse_baseURL_node (&new_adap_set->BaseURLs, cur_node); gst_mpdparser_parse_baseURL_node (&new_adap_set->BaseURLs, cur_node);
} else if (xmlStrcmp (cur_node->name, (xmlChar *) "SegmentBase") == 0) { } else if (xmlStrcmp (cur_node->name, (xmlChar *) "SegmentBase") == 0) {
gst_mpdparser_parse_seg_base_type_ext (&new_adap_set->SegmentBase, cur_node); gst_mpdparser_parse_seg_base_type_ext (&new_adap_set->SegmentBase, cur_node);
} else if (xmlStrcmp (cur_node->name, (xmlChar *) "SegmentList") == 0) {
gst_mpdparser_parse_segment_list_node (&new_adap_set->SegmentList, cur_node);
} else if (xmlStrcmp (cur_node->name, (xmlChar *) "ContentComponent") == 0) { } else if (xmlStrcmp (cur_node->name, (xmlChar *) "ContentComponent") == 0) {
gst_mpdparser_parse_content_component_node (&new_adap_set->ContentComponents, cur_node); gst_mpdparser_parse_content_component_node (&new_adap_set->ContentComponents, cur_node);
} else if (xmlStrcmp (cur_node->name, (xmlChar *) "SegmentTemplate") == 0) { } else if (xmlStrcmp (cur_node->name, (xmlChar *) "SegmentTemplate") == 0) {
@ -1365,13 +1367,14 @@ gst_mpdparser_parse_period_node (GList ** list, xmlNode * a_node)
/* explore children nodes */ /* explore children nodes */
for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) { for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {
if (cur_node->type == XML_ELEMENT_NODE) { if (cur_node->type == XML_ELEMENT_NODE) {
if (xmlStrcmp (cur_node->name, (xmlChar *) "Representation") == 0) { if (xmlStrcmp (cur_node->name, (xmlChar *) "AdaptationSet") == 0) {
gst_mpdparser_parse_representation_node (&new_period->Representations, cur_node);
} else if (xmlStrcmp (cur_node->name, (xmlChar *) "AdaptationSet") == 0) {
gst_mpdparser_parse_adaptation_set_node (&new_period->AdaptationSets, cur_node); gst_mpdparser_parse_adaptation_set_node (&new_period->AdaptationSets, cur_node);
} else if (xmlStrcmp (cur_node->name, } else if (xmlStrcmp (cur_node->name,
(xmlChar *) "SegmentBase") == 0) { (xmlChar *) "SegmentBase") == 0) {
gst_mpdparser_parse_seg_base_type_ext (&new_period->SegmentBase, cur_node); gst_mpdparser_parse_seg_base_type_ext (&new_period->SegmentBase, cur_node);
} else if (xmlStrcmp (cur_node->name,
(xmlChar *) "SegmentList") == 0) {
gst_mpdparser_parse_segment_list_node (&new_period->SegmentList, cur_node);
} else if (xmlStrcmp (cur_node->name, } else if (xmlStrcmp (cur_node->name,
(xmlChar *) "SegmentTemplate") == 0) { (xmlChar *) "SegmentTemplate") == 0) {
gst_mpdparser_parse_segment_template_node (&new_period->SegmentTemplate, cur_node); gst_mpdparser_parse_segment_template_node (&new_period->SegmentTemplate, cur_node);
@ -1782,16 +1785,20 @@ gst_mpdparser_get_rep_idx_with_max_bandwidth (GList * Representations,
} }
static GstSegmentListNode * static GstSegmentListNode *
gst_mpdparser_get_first_segment_list (GList * SegmentList) gst_mpdparser_get_segment_list (GstPeriodNode *Period,
GstAdaptationSetNode * AdaptationSet, GstRepresentationNode * Representation)
{ {
GList *list = NULL; GstSegmentListNode *SegmentList = NULL;
if (SegmentList == NULL) if (Representation && Representation->SegmentBase) {
return NULL; SegmentList = Representation->SegmentList;
} else if (AdaptationSet) {
SegmentList = AdaptationSet->SegmentList;
} else {
SegmentList = Period->SegmentList;
}
list = g_list_first (SegmentList); return SegmentList;
return list ? (GstSegmentListNode *) list->data : NULL;
} }
/* memory management functions */ /* memory management functions */
@ -1862,13 +1869,11 @@ gst_mpdparser_free_period_node (GstPeriodNode * period_node)
if (period_node) { if (period_node) {
g_free (period_node->id); g_free (period_node->id);
gst_mpdparser_free_seg_base_type_ext (period_node->SegmentBase); gst_mpdparser_free_seg_base_type_ext (period_node->SegmentBase);
gst_mpdparser_free_segment_list_node (period_node->SegmentList);
gst_mpdparser_free_segment_template_node (period_node->SegmentTemplate); gst_mpdparser_free_segment_template_node (period_node->SegmentTemplate);
g_list_foreach (period_node->AdaptationSets, g_list_foreach (period_node->AdaptationSets,
(GFunc) gst_mpdparser_free_adaptation_set_node, NULL); (GFunc) gst_mpdparser_free_adaptation_set_node, NULL);
g_list_free (period_node->AdaptationSets); g_list_free (period_node->AdaptationSets);
g_list_foreach (period_node->Representations,
(GFunc) gst_mpdparser_free_representation_node, NULL);
g_list_free (period_node->Representations);
g_list_foreach (period_node->Subsets, g_list_foreach (period_node->Subsets,
(GFunc) gst_mpdparser_free_subset_node, NULL); (GFunc) gst_mpdparser_free_subset_node, NULL);
g_list_free (period_node->Subsets); g_list_free (period_node->Subsets);
@ -1946,6 +1951,7 @@ gst_mpdparser_free_adaptation_set_node (GstAdaptationSetNode *
gst_mpdparser_free_representation_base_type gst_mpdparser_free_representation_base_type
(adaptation_set_node->RepresentationBase); (adaptation_set_node->RepresentationBase);
gst_mpdparser_free_seg_base_type_ext (adaptation_set_node->SegmentBase); gst_mpdparser_free_seg_base_type_ext (adaptation_set_node->SegmentBase);
gst_mpdparser_free_segment_list_node (adaptation_set_node->SegmentList);
gst_mpdparser_free_segment_template_node (adaptation_set_node->SegmentTemplate); gst_mpdparser_free_segment_template_node (adaptation_set_node->SegmentTemplate);
g_list_foreach (adaptation_set_node->BaseURLs, g_list_foreach (adaptation_set_node->BaseURLs,
(GFunc) gst_mpdparser_free_base_url_node, NULL); (GFunc) gst_mpdparser_free_base_url_node, NULL);
@ -1975,9 +1981,7 @@ gst_mpdparser_free_representation_node (GstRepresentationNode *
g_list_free (representation_node->SubRepresentations); g_list_free (representation_node->SubRepresentations);
gst_mpdparser_free_seg_base_type_ext (representation_node->SegmentBase); gst_mpdparser_free_seg_base_type_ext (representation_node->SegmentBase);
gst_mpdparser_free_segment_template_node (representation_node->SegmentTemplate); gst_mpdparser_free_segment_template_node (representation_node->SegmentTemplate);
g_list_foreach (representation_node->SegmentList, gst_mpdparser_free_segment_list_node (representation_node->SegmentList);
(GFunc) gst_mpdparser_free_segment_list_node, NULL);
g_list_free (representation_node->SegmentList);
g_list_foreach (representation_node->BaseURLs, g_list_foreach (representation_node->BaseURLs,
(GFunc) gst_mpdparser_free_base_url_node, NULL); (GFunc) gst_mpdparser_free_base_url_node, NULL);
g_list_free (representation_node->BaseURLs); g_list_free (representation_node->BaseURLs);
@ -2416,7 +2420,12 @@ gst_mpd_client_setup_representation (GstMpdClient * client, GstActiveStream *str
GstClockTime PeriodStart = 0, PeriodEnd, start_time, duration; GstClockTime PeriodStart = 0, PeriodEnd, start_time, duration;
guint i; guint i;
rep_list = stream->cur_adapt_set ? stream->cur_adapt_set->Representations : client->cur_period->Representations; if (stream->cur_adapt_set == NULL) {
GST_WARNING ("No valid AdaptationSet node in the MPD file, aborting...");
return FALSE;
}
rep_list = stream->cur_adapt_set->Representations;
stream->cur_representation = representation; stream->cur_representation = representation;
stream->representation_idx = g_list_index (rep_list, representation); stream->representation_idx = g_list_index (rep_list, representation);
@ -2457,7 +2466,7 @@ gst_mpd_client_setup_representation (GstMpdClient * client, GstActiveStream *str
/* get the first segment_list of the selected representation */ /* get the first segment_list of the selected representation */
if ((stream->cur_segment_list = if ((stream->cur_segment_list =
gst_mpdparser_get_first_segment_list (representation->SegmentList)) == NULL) { 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..."); GST_WARNING ("No valid SegmentList node in the MPD file, aborting...");
return FALSE; return FALSE;
} }
@ -2548,7 +2557,7 @@ gst_mpd_client_setup_streaming (GstMpdClient * client,
GstActiveStream *stream; GstActiveStream *stream;
GstAdaptationSetNode *adapt_set; GstAdaptationSetNode *adapt_set;
GstRepresentationNode *representation; GstRepresentationNode *representation;
GList *rep_list; GList *rep_list = NULL;
/* select a new period */ /* select a new period */
if (!client->cur_period) if (!client->cur_period)
@ -2569,11 +2578,12 @@ gst_mpd_client_setup_streaming (GstMpdClient * client,
adapt_set = adapt_set =
gst_mpdparser_get_first_adapt_set (client->cur_period-> gst_mpdparser_get_first_adapt_set (client->cur_period->
AdaptationSets); AdaptationSets);
if (!adapt_set) {
GST_INFO ("No adaptation set found, aborting...");
return FALSE;
}
/* retrive the list of representations */ /* retrive the list of representations */
if (adapt_set != NULL) rep_list = adapt_set->Representations;
rep_list = adapt_set->Representations;
else
rep_list = client->cur_period->Representations;
if (!rep_list) { if (!rep_list) {
GST_WARNING ("Can not retrieve any representation, aborting..."); GST_WARNING ("Can not retrieve any representation, aborting...");
return FALSE; return FALSE;
@ -2595,7 +2605,7 @@ gst_mpd_client_setup_streaming (GstMpdClient * client,
gst_mpdparser_get_first_adapt_set_with_mimeType (client-> gst_mpdparser_get_first_adapt_set_with_mimeType (client->
cur_period->AdaptationSets, "audio"); cur_period->AdaptationSets, "audio");
if (!adapt_set) { if (!adapt_set) {
GST_INFO ("No audio adaptation set found"); GST_INFO ("No audio adaptation set found, aborting...");
return FALSE; return FALSE;
} }
rep_list = adapt_set->Representations; rep_list = adapt_set->Representations;
@ -2620,7 +2630,7 @@ gst_mpd_client_setup_streaming (GstMpdClient * client,
gst_mpdparser_get_first_adapt_set_with_mimeType (client-> gst_mpdparser_get_first_adapt_set_with_mimeType (client->
cur_period->AdaptationSets, "application"); cur_period->AdaptationSets, "application");
if (!adapt_set) { if (!adapt_set) {
GST_INFO ("No application adaptation set found"); GST_INFO ("No application adaptation set found, aborting...");
return FALSE; return FALSE;
} }
rep_list = adapt_set->Representations; rep_list = adapt_set->Representations;
@ -2650,8 +2660,6 @@ gst_mpd_client_setup_streaming (GstMpdClient * client,
/* retrive representation list */ /* retrive representation list */
if (stream->cur_adapt_set != NULL) if (stream->cur_adapt_set != NULL)
rep_list = stream->cur_adapt_set->Representations; rep_list = stream->cur_adapt_set->Representations;
else
rep_list = client->cur_period->Representations;
#if 0 #if 0
/* fast start */ /* fast start */

View file

@ -239,8 +239,8 @@ struct _GstRepresentationNode
GstSegmentBaseType *SegmentBase; GstSegmentBaseType *SegmentBase;
/* SegmentTemplate node */ /* SegmentTemplate node */
GstSegmentTemplateNode *SegmentTemplate; GstSegmentTemplateNode *SegmentTemplate;
/* list of SegmentList nodes */ /* SegmentList node */
GList *SegmentList; GstSegmentListNode *SegmentList;
}; };
struct _GstDescriptorType struct _GstDescriptorType
@ -288,6 +288,8 @@ struct _GstAdaptationSetNode
GstRepresentationBaseType *RepresentationBase; GstRepresentationBaseType *RepresentationBase;
/* SegmentBase node */ /* SegmentBase node */
GstSegmentBaseType *SegmentBase; GstSegmentBaseType *SegmentBase;
/* SegmentList node */
GstSegmentListNode *SegmentList;
/* SegmentTemplate node */ /* SegmentTemplate node */
GstSegmentTemplateNode *SegmentTemplate; GstSegmentTemplateNode *SegmentTemplate;
/* list of BaseURL nodes */ /* list of BaseURL nodes */
@ -312,13 +314,13 @@ struct _GstPeriodNode
gboolean bitstreamSwitching; gboolean bitstreamSwitching;
/* SegmentBase node */ /* SegmentBase node */
GstSegmentBaseType *SegmentBase; GstSegmentBaseType *SegmentBase;
/* SegmentList node */
GstSegmentListNode *SegmentList;
/* SegmentTemplate node */ /* SegmentTemplate node */
GstSegmentTemplateNode *SegmentTemplate; GstSegmentTemplateNode *SegmentTemplate;
/* list of Adaptation Set nodes */ /* list of Adaptation Set nodes */
GList *AdaptationSets; GList *AdaptationSets;
/* list of Representation nodes */ /* list of Representation nodes */
GList *Representations;
/* list of Subset nodes */
GList *Subsets; GList *Subsets;
/* list of BaseURL nodes */ /* list of BaseURL nodes */
GList *BaseURLs; GList *BaseURLs;