dash: Generate an XML content from object.
authorStéphane Cerveau <scerveau@collabora.com>
Wed, 4 Dec 2019 16:25:24 +0000 (17:25 +0100)
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Fri, 3 Jan 2020 20:50:27 +0000 (20:50 +0000)
Add mpd node base class to provide
xml generation facilities for child
objects.

61 files changed:
ext/dash/gstdashdemux.c
ext/dash/gstmpdadaptationsetnode.c
ext/dash/gstmpdadaptationsetnode.h
ext/dash/gstmpdbaseurlnode.c
ext/dash/gstmpdbaseurlnode.h
ext/dash/gstmpdclient.c
ext/dash/gstmpdclient.h
ext/dash/gstmpdcontentcomponentnode.c
ext/dash/gstmpdcontentcomponentnode.h
ext/dash/gstmpddescriptortypenode.c [new file with mode: 0644]
ext/dash/gstmpddescriptortypenode.h [new file with mode: 0644]
ext/dash/gstmpdhelper.c
ext/dash/gstmpdhelper.h
ext/dash/gstmpdlocationnode.c [new file with mode: 0644]
ext/dash/gstmpdlocationnode.h [new file with mode: 0644]
ext/dash/gstmpdmetricsnode.c
ext/dash/gstmpdmetricsnode.h
ext/dash/gstmpdmetricsrangenode.c
ext/dash/gstmpdmetricsrangenode.h
ext/dash/gstmpdmultsegmentbasenode.c [new file with mode: 0644]
ext/dash/gstmpdmultsegmentbasenode.h [new file with mode: 0644]
ext/dash/gstmpdnode.c [new file with mode: 0644]
ext/dash/gstmpdnode.h [new file with mode: 0644]
ext/dash/gstmpdparser.c
ext/dash/gstmpdparser.h
ext/dash/gstmpdperiodnode.c
ext/dash/gstmpdperiodnode.h
ext/dash/gstmpdprograminformationnode.c
ext/dash/gstmpdprograminformationnode.h
ext/dash/gstmpdreportingnode.c [new file with mode: 0644]
ext/dash/gstmpdreportingnode.h [new file with mode: 0644]
ext/dash/gstmpdrepresentationbasenode.c [new file with mode: 0644]
ext/dash/gstmpdrepresentationbasenode.h [new file with mode: 0644]
ext/dash/gstmpdrepresentationnode.c
ext/dash/gstmpdrepresentationnode.h
ext/dash/gstmpdrootnode.c
ext/dash/gstmpdrootnode.h
ext/dash/gstmpdsegmentbasenode.c [new file with mode: 0644]
ext/dash/gstmpdsegmentbasenode.h [new file with mode: 0644]
ext/dash/gstmpdsegmentlistnode.c
ext/dash/gstmpdsegmentlistnode.h
ext/dash/gstmpdsegmenttemplatenode.c
ext/dash/gstmpdsegmenttemplatenode.h
ext/dash/gstmpdsegmenttimelinenode.c
ext/dash/gstmpdsegmenttimelinenode.h
ext/dash/gstmpdsegmenturlnode.c
ext/dash/gstmpdsegmenturlnode.h
ext/dash/gstmpdsnode.c
ext/dash/gstmpdsnode.h
ext/dash/gstmpdsubrepresentationnode.c
ext/dash/gstmpdsubrepresentationnode.h
ext/dash/gstmpdsubsetnode.c
ext/dash/gstmpdsubsetnode.h
ext/dash/gstmpdurltypenode.c [new file with mode: 0644]
ext/dash/gstmpdurltypenode.h [new file with mode: 0644]
ext/dash/gstmpdutctimingnode.c
ext/dash/gstmpdutctimingnode.h
ext/dash/gstxmlhelper.c
ext/dash/gstxmlhelper.h
ext/dash/meson.build
tests/check/elements/dash_mpd.c

index 05bb85b..8aecfaf 100644 (file)
@@ -862,12 +862,13 @@ gst_dash_demux_setup_all_streams (GstDashDemux * demux)
     stream->target_time = GST_CLOCK_TIME_NONE;
     /* Set a default average keyframe download time of a quarter of a second */
     stream->average_download_time = 250 * GST_MSECOND;
+
     if (active_stream->cur_adapt_set &&
-        active_stream->cur_adapt_set->RepresentationBase &&
-        active_stream->cur_adapt_set->RepresentationBase->ContentProtection) {
+        GST_MPD_REPRESENTATION_BASE_NODE (active_stream->
+            cur_adapt_set)->ContentProtection) {
       GST_DEBUG_OBJECT (demux, "Adding ContentProtection events to source pad");
-      g_list_foreach (active_stream->cur_adapt_set->
-          RepresentationBase->ContentProtection,
+      g_list_foreach (GST_MPD_REPRESENTATION_BASE_NODE
+          (active_stream->cur_adapt_set)->ContentProtection,
           gst_dash_demux_send_content_protection_event, stream);
     }
 
@@ -880,7 +881,7 @@ gst_dash_demux_setup_all_streams (GstDashDemux * demux)
 static void
 gst_dash_demux_send_content_protection_event (gpointer data, gpointer userdata)
 {
-  GstMPDDescriptorType *cp = (GstMPDDescriptorType *) data;
+  GstMPDDescriptorTypeNode *cp = (GstMPDDescriptorTypeNode *) data;
   GstDashDemuxStream *stream = (GstDashDemuxStream *) userdata;
   GstEvent *event;
   GstBuffer *pssi;
index a47bd91..5d2ed9d 100644 (file)
@@ -22,7 +22,7 @@
 #include "gstmpdparser.h"
 
 G_DEFINE_TYPE (GstMPDAdaptationSetNode, gst_mpd_adaptation_set_node,
-    GST_TYPE_OBJECT);
+    GST_TYPE_MPD_REPRESENTATION_BASE_NODE);
 
 /* GObject VMethods */
 
@@ -39,15 +39,14 @@ gst_mpd_adaptation_set_node_finalize (GObject * object)
   g_slice_free (GstXMLConditionalUintType, self->segmentAlignment);
   g_slice_free (GstXMLConditionalUintType, self->subsegmentAlignment);
   g_list_free_full (self->Accessibility,
-      (GDestroyNotify) gst_mpd_helper_descriptor_type_free);
+      (GDestroyNotify) gst_mpd_descriptor_type_node_free);
   g_list_free_full (self->Role,
-      (GDestroyNotify) gst_mpd_helper_descriptor_type_free);
+      (GDestroyNotify) gst_mpd_descriptor_type_node_free);
   g_list_free_full (self->Rating,
-      (GDestroyNotify) gst_mpd_helper_descriptor_type_free);
+      (GDestroyNotify) gst_mpd_descriptor_type_node_free);
   g_list_free_full (self->Viewpoint,
-      (GDestroyNotify) gst_mpd_helper_descriptor_type_free);
-  gst_mpd_helper_representation_base_type_free (self->RepresentationBase);
-  gst_mpd_helper_segment_base_type_free (self->SegmentBase);
+      (GDestroyNotify) gst_mpd_descriptor_type_node_free);
+  gst_mpd_segment_base_node_free (self->SegmentBase);
   gst_mpd_segment_list_node_free (self->SegmentList);
   gst_mpd_segment_template_node_free (self->SegmentTemplate);
   g_list_free_full (self->BaseURLs, (GDestroyNotify) gst_mpd_baseurl_node_free);
@@ -61,11 +60,105 @@ gst_mpd_adaptation_set_node_finalize (GObject * object)
   G_OBJECT_CLASS (gst_mpd_adaptation_set_node_parent_class)->finalize (object);
 }
 
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_adaptation_set_get_xml_node (GstMPDNode * node)
+{
+  xmlNodePtr adaptation_set_xml_node = NULL;
+  GstMPDAdaptationSetNode *self = GST_MPD_ADAPTATION_SET_NODE (node);
+
+  adaptation_set_xml_node = xmlNewNode (NULL, (xmlChar *) "AdaptationSet");
+
+  if (self->id)
+    gst_xml_helper_set_prop_uint (adaptation_set_xml_node, "id", self->id);
+  if (self->group)
+    gst_xml_helper_set_prop_uint (adaptation_set_xml_node, "group",
+        self->group);
+
+  if (self->lang)
+    gst_xml_helper_set_prop_string (adaptation_set_xml_node, "lang",
+        self->lang);
+
+  if (self->contentType)
+    gst_xml_helper_set_prop_string (adaptation_set_xml_node, "contentType",
+        self->contentType);
+
+  if (self->minBandwidth)
+    gst_xml_helper_set_prop_uint (adaptation_set_xml_node, "minBandwidth",
+        self->minBandwidth);
+  if (self->maxBandwidth)
+    gst_xml_helper_set_prop_uint (adaptation_set_xml_node, "maxBandwidth",
+        self->maxBandwidth);
+  if (self->minWidth)
+    gst_xml_helper_set_prop_uint (adaptation_set_xml_node, "minWidth",
+        self->minWidth);
+  if (self->maxWidth)
+    gst_xml_helper_set_prop_uint (adaptation_set_xml_node, "maxWidth",
+        self->maxWidth);
+  if (self->minHeight)
+    gst_xml_helper_set_prop_uint (adaptation_set_xml_node, "minHeight",
+        self->minHeight);
+  if (self->maxHeight)
+    gst_xml_helper_set_prop_uint (adaptation_set_xml_node, "maxHeight",
+        self->maxHeight);
+
+  if (self->par)
+    gst_xml_helper_set_prop_ratio (adaptation_set_xml_node, "par", self->par);
+
+  gst_xml_helper_set_prop_cond_uint (adaptation_set_xml_node,
+      "segmentAlignment", self->segmentAlignment);
+  gst_xml_helper_set_prop_cond_uint (adaptation_set_xml_node,
+      "subsegmentAlignment", self->subsegmentAlignment);
+  gst_xml_helper_set_prop_uint (adaptation_set_xml_node,
+      "subsegmentStartsWithSAP", self->subsegmentStartsWithSAP);
+  gst_xml_helper_set_prop_boolean (adaptation_set_xml_node,
+      "bitstreamSwitching", self->bitstreamSwitching);
+
+  g_list_foreach (self->Accessibility, gst_mpd_node_get_list_item,
+      adaptation_set_xml_node);
+  g_list_foreach (self->Role, gst_mpd_node_get_list_item,
+      adaptation_set_xml_node);
+  g_list_foreach (self->Rating, gst_mpd_node_get_list_item,
+      adaptation_set_xml_node);
+  g_list_foreach (self->Viewpoint, gst_mpd_node_get_list_item,
+      adaptation_set_xml_node);
+
+  gst_mpd_node_add_child_node (GST_MPD_NODE (self->SegmentBase),
+      adaptation_set_xml_node);
+  gst_mpd_mult_segment_base_node_add_child_node (GST_MPD_NODE
+      (self->SegmentList), adaptation_set_xml_node);
+  gst_mpd_mult_segment_base_node_add_child_node (GST_MPD_NODE
+      (self->SegmentTemplate), adaptation_set_xml_node);
+
+  g_list_foreach (self->BaseURLs, gst_mpd_node_get_list_item,
+      adaptation_set_xml_node);
+  g_list_foreach (self->Representations,
+      gst_mpd_representation_base_node_get_list_item, adaptation_set_xml_node);
+  g_list_foreach (self->ContentComponents, gst_mpd_node_get_list_item,
+      adaptation_set_xml_node);
+
+  if (self->xlink_href)
+    gst_xml_helper_set_prop_string (adaptation_set_xml_node, "xlink_href",
+        self->xlink_href);
+  if (self->actuate == GST_MPD_XLINK_ACTUATE_ON_LOAD)
+    gst_xml_helper_set_prop_string (adaptation_set_xml_node, "actuate",
+        (gchar *) GST_MPD_XLINK_ACTUATE_ON_LOAD_STR);
+  return adaptation_set_xml_node;
+}
+
 static void
 gst_mpd_adaptation_set_node_class_init (GstMPDAdaptationSetNodeClass * klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GObjectClass *object_class;
+  GstMPDNodeClass *m_klass;
+
+  object_class = G_OBJECT_CLASS (klass);
+  m_klass = GST_MPD_NODE_CLASS (klass);
+
   object_class->finalize = gst_mpd_adaptation_set_node_finalize;
+
+  m_klass->get_xml_node = gst_mpd_adaptation_set_get_xml_node;
 }
 
 static void
@@ -94,8 +187,6 @@ gst_mpd_adaptation_set_node_init (GstMPDAdaptationSetNode * self)
   self->Rating = NULL;
   /* list of Viewpoint DescriptorType nodes */
   self->Viewpoint = NULL;
-  /* RepresentationBase extension */
-  self->RepresentationBase = NULL;
   /* SegmentBase node */
   self->SegmentBase = NULL;
   /* SegmentList node */
index 1a0977f..ce91a4b 100644 (file)
 
 #include <gst/gst.h>
 #include "gstmpdhelper.h"
+#include "gstmpdrepresentationbasenode.h"
 #include "gstmpdsegmentlistnode.h"
 #include "gstmpdsegmenttemplatenode.h"
 
 G_BEGIN_DECLS
 
 #define GST_TYPE_MPD_ADAPTATION_SET_NODE gst_mpd_adaptation_set_node_get_type ()
-#define GST_MPD_ADAPTATION_SET_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MPD_ADAPTATION_SET_NODE, GstMPDAdaptationSetNode))
-#define GST_MPD_ADAPTATION_SET_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MPD_ADAPTATION_SET_NODE, GstMPDAdaptationSetNodeClass))
-#define GST_IS_MPD_ADAPTATION_SET_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MPD_ADAPTATION_SET_NODE))
-#define GST_IS_MPD_ADAPTATION_SET_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MPD_ADAPTATION_SET_NODE))
-#define GST_MPD_ADAPTATION_SET_NODE_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MPD_ADAPTATION_SET_NODE, GstMPDAdaptationSetNodeClass))
-
-typedef struct _GstMPDAdaptationSetNode                GstMPDAdaptationSetNode;
-typedef struct _GstMPDAdaptationSetNodeClass           GstMPDAdaptationSetNodeClass;
-
+G_DECLARE_FINAL_TYPE (GstMPDAdaptationSetNode, gst_mpd_adaptation_set_node, GST, MPD_ADAPTATION_SET_NODE, GstMPDRepresentationBaseNode)
 
 struct _GstMPDAdaptationSetNode
 {
-  GstObject parent_instance;
+  GstMPDRepresentationBaseNode parent_instance;
   guint id;
   guint group;
   gchar *lang;                      /* LangVectorType RFC 5646 */
@@ -70,10 +58,8 @@ struct _GstMPDAdaptationSetNode
   GList *Rating;
   /* list of Viewpoint DescriptorType nodes */
   GList *Viewpoint;
-  /* RepresentationBase extension */
-  GstMPDRepresentationBaseType *RepresentationBase;
   /* SegmentBase node */
-  GstMPDSegmentBaseType *SegmentBase;
+  GstMPDSegmentBaseNode *SegmentBase;
   /* SegmentList node */
   GstMPDSegmentListNode *SegmentList;
   /* SegmentTemplate node */
@@ -89,13 +75,6 @@ struct _GstMPDAdaptationSetNode
   GstMPDXLinkActuate actuate;
 };
 
-struct _GstMPDAdaptationSetNodeClass {
-  GstObjectClass parent_class;
-};
-
-
-G_GNUC_INTERNAL GType gst_mpd_adaptation_set_node_get_type (void);
-
 GstMPDAdaptationSetNode * gst_mpd_adaptation_set_node_new (void);
 void gst_mpd_adaptation_set_node_free (GstMPDAdaptationSetNode* self);
 
index 4e5f89e..53043ed 100644 (file)
@@ -21,7 +21,7 @@
 #include "gstmpdbaseurlnode.h"
 #include "gstmpdparser.h"
 
-G_DEFINE_TYPE (GstMPDBaseURLNode, gst_mpd_baseurl_node, GST_TYPE_OBJECT);
+G_DEFINE_TYPE (GstMPDBaseURLNode, gst_mpd_baseurl_node, GST_TYPE_MPD_NODE);
 
 /* GObject VMethods */
 
@@ -37,11 +37,42 @@ gst_mpd_baseurl_node_finalize (GObject * object)
   G_OBJECT_CLASS (gst_mpd_baseurl_node_parent_class)->finalize (object);
 }
 
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_baseurl_get_xml_node (GstMPDNode * node)
+{
+  xmlNodePtr baseurl_xml_node = NULL;
+  GstMPDBaseURLNode *self = GST_MPD_BASEURL_NODE (node);
+
+  baseurl_xml_node = xmlNewNode (NULL, (xmlChar *) "BaseURL");
+
+  if (self->serviceLocation)
+    gst_xml_helper_set_prop_string (baseurl_xml_node, "serviceLocation",
+        self->serviceLocation);
+
+  if (self->byteRange)
+    gst_xml_helper_set_prop_string (baseurl_xml_node, "byteRange",
+        self->byteRange);
+
+  if (self->baseURL)
+    gst_xml_helper_set_content (baseurl_xml_node, self->baseURL);
+
+  return baseurl_xml_node;
+}
+
 static void
 gst_mpd_baseurl_node_class_init (GstMPDBaseURLNodeClass * klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GObjectClass *object_class;
+  GstMPDNodeClass *m_klass;
+
+  object_class = G_OBJECT_CLASS (klass);
+  m_klass = GST_MPD_NODE_CLASS (klass);
+
   object_class->finalize = gst_mpd_baseurl_node_finalize;
+
+  m_klass->get_xml_node = gst_mpd_baseurl_get_xml_node;
 }
 
 static void
index be28dc8..078d754 100644 (file)
 G_BEGIN_DECLS
 
 #define GST_TYPE_MPD_BASEURL_NODE gst_mpd_baseurl_node_get_type ()
-#define GST_MPD_BASEURL_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MPD_BASEURL_NODE, GstMPDBaseURLNode))
-#define GST_MPD_BASEURL_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MPD_BASEURL_NODE, GstMPDBaseURLNodeClass))
-#define GST_IS_MPD_BASEURL_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MPD_BASEURL_NODE))
-#define GST_IS_MPD_BASEURL_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MPD_BASEURL_NODE))
-#define GST_MPD_BASEURL_NODE_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MPD_BASEURL_NODE, GstMPDBaseURLNodeClass))
-
-typedef struct _GstMPDBaseURLNode                GstMPDBaseURLNode;
-typedef struct _GstMPDBaseURLNodeClass           GstMPDBaseURLNodeClass;
-
+G_DECLARE_FINAL_TYPE (GstMPDBaseURLNode, gst_mpd_baseurl_node, GST, MPD_BASEURL_NODE, GstMPDNode)
 
 struct _GstMPDBaseURLNode
 {
@@ -51,13 +38,6 @@ struct _GstMPDBaseURLNode
   /* TODO add missing fields such as weight etc.*/
 };
 
-struct _GstMPDBaseURLNodeClass {
-  GstObjectClass parent_class;
-};
-
-
-G_GNUC_INTERNAL GType gst_mpd_baseurl_node_get_type (void);
-
 GstMPDBaseURLNode * gst_mpd_baseurl_node_new (void);
 void gst_mpd_baseurl_node_free (GstMPDBaseURLNode* self);
 
index b2fdea9..99878d3 100644 (file)
@@ -28,7 +28,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_dash_mpd_client_debug);
 
 G_DEFINE_TYPE (GstMPDClient, gst_mpd_client, GST_TYPE_OBJECT);
 
-static GstMPDSegmentBaseType *gst_mpd_client_get_segment_base (GstMPDPeriodNode
+static GstMPDSegmentBaseNode *gst_mpd_client_get_segment_base (GstMPDPeriodNode
     * Period, GstMPDAdaptationSetNode * AdaptationSet,
     GstMPDRepresentationNode * Representation);
 static GstMPDSegmentListNode *gst_mpd_client_get_segment_list (GstMPDClient *
@@ -202,12 +202,12 @@ gst_mpd_client_fetch_external_segment_list (GstMPDClient * client,
   return new_segment_list;
 }
 
-static GstMPDSegmentBaseType *
+static GstMPDSegmentBaseNode *
 gst_mpd_client_get_segment_base (GstMPDPeriodNode * Period,
     GstMPDAdaptationSetNode * AdaptationSet,
     GstMPDRepresentationNode * Representation)
 {
-  GstMPDSegmentBaseType *SegmentBase = NULL;
+  GstMPDSegmentBaseNode *SegmentBase = NULL;
 
   if (Representation && Representation->SegmentBase) {
     SegmentBase = Representation->SegmentBase;
@@ -219,17 +219,24 @@ gst_mpd_client_get_segment_base (GstMPDPeriodNode * Period,
   /* the SegmentBase element could be encoded also inside a SegmentList element */
   if (SegmentBase == NULL) {
     if (Representation && Representation->SegmentList
-        && Representation->SegmentList->MultSegBaseType
-        && Representation->SegmentList->MultSegBaseType->SegBaseType) {
-      SegmentBase = Representation->SegmentList->MultSegBaseType->SegBaseType;
+        && GST_MPD_MULT_SEGMENT_BASE_NODE (Representation->SegmentList)
+        && GST_MPD_MULT_SEGMENT_BASE_NODE (Representation->
+            SegmentList)->SegmentBase) {
+      SegmentBase =
+          GST_MPD_MULT_SEGMENT_BASE_NODE (Representation->
+          SegmentList)->SegmentBase;
     } else if (AdaptationSet && AdaptationSet->SegmentList
-        && AdaptationSet->SegmentList->MultSegBaseType
-        && AdaptationSet->SegmentList->MultSegBaseType->SegBaseType) {
-      SegmentBase = AdaptationSet->SegmentList->MultSegBaseType->SegBaseType;
+        && GST_MPD_MULT_SEGMENT_BASE_NODE (AdaptationSet->SegmentList)
+        && GST_MPD_MULT_SEGMENT_BASE_NODE (AdaptationSet->
+            SegmentList)->SegmentBase) {
+      SegmentBase =
+          GST_MPD_MULT_SEGMENT_BASE_NODE (AdaptationSet->
+          SegmentList)->SegmentBase;
     } else if (Period && Period->SegmentList
-        && Period->SegmentList->MultSegBaseType
-        && Period->SegmentList->MultSegBaseType->SegBaseType) {
-      SegmentBase = Period->SegmentList->MultSegBaseType->SegBaseType;
+        && GST_MPD_MULT_SEGMENT_BASE_NODE (Period->SegmentList)
+        && GST_MPD_MULT_SEGMENT_BASE_NODE (Period->SegmentList)->SegmentBase) {
+      SegmentBase =
+          GST_MPD_MULT_SEGMENT_BASE_NODE (Period->SegmentList)->SegmentBase;
     }
   }
 
@@ -281,7 +288,7 @@ gst_mpd_client_get_segment_duration (GstMPDClient * client,
     GstActiveStream * stream, guint64 * scale_dur)
 {
   GstStreamPeriod *stream_period;
-  GstMPDMultSegmentBaseType *base = NULL;
+  GstMPDMultSegmentBaseNode *base = NULL;
   GstClockTime duration = 0;
 
   g_return_val_if_fail (stream != NULL, GST_CLOCK_TIME_NONE);
@@ -289,12 +296,12 @@ gst_mpd_client_get_segment_duration (GstMPDClient * client,
   g_return_val_if_fail (stream_period != NULL, GST_CLOCK_TIME_NONE);
 
   if (stream->cur_segment_list) {
-    base = stream->cur_segment_list->MultSegBaseType;
+    base = GST_MPD_MULT_SEGMENT_BASE_NODE (stream->cur_segment_list);
   } else if (stream->cur_seg_template) {
-    base = stream->cur_seg_template->MultSegBaseType;
+    base = GST_MPD_MULT_SEGMENT_BASE_NODE (stream->cur_seg_template);
   }
 
-  if (base == NULL || base->SegBaseType == NULL) {
+  if (base == NULL || base->SegmentBase == NULL) {
     /* this may happen when we have a single segment */
     duration = stream_period->duration;
     if (scale_dur)
@@ -304,7 +311,7 @@ gst_mpd_client_get_segment_duration (GstMPDClient * client,
     duration = base->duration * GST_SECOND;
     if (scale_dur)
       *scale_dur = duration;
-    duration /= base->SegBaseType->timescale;
+    duration /= base->SegmentBase->timescale;
   }
 
   return duration;
@@ -391,6 +398,22 @@ gst_mpd_client_parse (GstMPDClient * client, const gchar * data, gint size)
   return ret;
 }
 
+
+gboolean
+gst_mpd_client_get_xml_content (GstMPDClient * client, gchar ** data,
+    gint * size)
+{
+  gboolean ret = FALSE;
+
+  g_return_val_if_fail (client != NULL, ret);
+  g_return_val_if_fail (client->mpd_root_node != NULL, ret);
+
+  ret = gst_mpd_node_get_xml_buffer (GST_MPD_NODE (client->mpd_root_node),
+      data, (int *) size);
+
+  return ret;
+}
+
 GstDateTime *
 gst_mpd_client_get_availability_start_time (GstMPDClient * client)
 {
@@ -695,13 +718,15 @@ static void
 gst_mpd_client_stream_update_presentation_time_offset (GstMPDClient * client,
     GstActiveStream * stream)
 {
-  GstMPDSegmentBaseType *segbase = NULL;
+  GstMPDSegmentBaseNode *segbase = NULL;
 
   /* Find the used segbase */
   if (stream->cur_segment_list) {
-    segbase = stream->cur_segment_list->MultSegBaseType->SegBaseType;
+    segbase =
+        GST_MPD_MULT_SEGMENT_BASE_NODE (stream->cur_segment_list)->SegmentBase;
   } else if (stream->cur_seg_template) {
-    segbase = stream->cur_seg_template->MultSegBaseType->SegBaseType;
+    segbase =
+        GST_MPD_MULT_SEGMENT_BASE_NODE (stream->cur_seg_template)->SegmentBase;
   } else if (stream->cur_segment_base) {
     segbase = stream->cur_segment_base;
   }
@@ -792,26 +817,32 @@ gst_mpd_client_setup_representation (GstMPDClient * client,
       }
 
       /* build segment list */
-      i = stream->cur_segment_list->MultSegBaseType->startNumber;
+      i = GST_MPD_MULT_SEGMENT_BASE_NODE (stream->
+          cur_segment_list)->startNumber;
       start = 0;
       start_time = PeriodStart;
 
       GST_LOG ("Building media segment list using a SegmentList node");
-      if (stream->cur_segment_list->MultSegBaseType->SegmentTimeline) {
+      if (GST_MPD_MULT_SEGMENT_BASE_NODE (stream->
+              cur_segment_list)->SegmentTimeline) {
         GstMPDSegmentTimelineNode *timeline;
         GstMPDSNode *S;
         GList *list;
         GstClockTime presentationTimeOffset;
-        GstMPDSegmentBaseType *segbase;
+        GstMPDSegmentBaseNode *segbase;
 
-        segbase = stream->cur_segment_list->MultSegBaseType->SegBaseType;
+        segbase =
+            GST_MPD_MULT_SEGMENT_BASE_NODE (stream->
+            cur_segment_list)->SegmentBase;
         presentationTimeOffset =
             gst_util_uint64_scale (segbase->presentationTimeOffset, GST_SECOND,
             segbase->timescale);
         GST_LOG ("presentationTimeOffset = %" G_GUINT64_FORMAT,
             presentationTimeOffset);
 
-        timeline = stream->cur_segment_list->MultSegBaseType->SegmentTimeline;
+        timeline =
+            GST_MPD_MULT_SEGMENT_BASE_NODE (stream->
+            cur_segment_list)->SegmentTimeline;
         for (list = g_queue_peek_head_link (&timeline->S); list;
             list = g_list_next (list)) {
           guint timescale;
@@ -820,7 +851,8 @@ gst_mpd_client_setup_representation (GstMPDClient * client,
           GST_LOG ("Processing S node: d=%" G_GUINT64_FORMAT " r=%d t=%"
               G_GUINT64_FORMAT, S->d, S->r, S->t);
           timescale =
-              stream->cur_segment_list->MultSegBaseType->SegBaseType->timescale;
+              GST_MPD_MULT_SEGMENT_BASE_NODE (stream->
+              cur_segment_list)->SegmentBase->timescale;
           duration = gst_util_uint64_scale (S->d, GST_SECOND, timescale);
 
           if (S->t > 0) {
@@ -873,8 +905,7 @@ gst_mpd_client_setup_representation (GstMPDClient * client,
       stream->cur_seg_template = stream_period->period->SegmentTemplate;
     }
 
-    if (stream->cur_seg_template == NULL
-        || stream->cur_seg_template->MultSegBaseType == NULL) {
+    if (stream->cur_seg_template == NULL) {
 
       gst_mpdparser_init_active_stream_segments (stream);
       /* here we should have a single segment for each representation, whose URL is encoded in the baseURL element */
@@ -884,11 +915,11 @@ gst_mpd_client_setup_representation (GstMPDClient * client,
       }
     } else {
       GstClockTime presentationTimeOffset;
-      GstMPDMultSegmentBaseType *mult_seg =
-          stream->cur_seg_template->MultSegBaseType;
+      GstMPDMultSegmentBaseNode *mult_seg =
+          GST_MPD_MULT_SEGMENT_BASE_NODE (stream->cur_seg_template);
       presentationTimeOffset =
-          gst_util_uint64_scale (mult_seg->SegBaseType->presentationTimeOffset,
-          GST_SECOND, mult_seg->SegBaseType->timescale);
+          gst_util_uint64_scale (mult_seg->SegmentBase->presentationTimeOffset,
+          GST_SECOND, mult_seg->SegmentBase->timescale);
       GST_LOG ("presentationTimeOffset = %" GST_TIME_FORMAT,
           GST_TIME_ARGS (presentationTimeOffset));
       /* build segment list */
@@ -913,7 +944,7 @@ gst_mpd_client_setup_representation (GstMPDClient * client,
           S = (GstMPDSNode *) list->data;
           GST_LOG ("Processing S node: d=%" G_GUINT64_FORMAT " r=%u t=%"
               G_GUINT64_FORMAT, S->d, S->r, S->t);
-          timescale = mult_seg->SegBaseType->timescale;
+          timescale = mult_seg->SegmentBase->timescale;
           duration = gst_util_uint64_scale (S->d, GST_SECOND, timescale);
           if (S->t > 0) {
             start = S->t;
@@ -1625,8 +1656,8 @@ gst_mpd_client_stream_seek (GstMPDClient * client, GstActiveStream * stream,
     guint segments_count = gst_mpd_client_get_segments_counts (client, stream);
     GstClockTime index_time;
 
-    g_return_val_if_fail (stream->cur_seg_template->MultSegBaseType->
-        SegmentTimeline == NULL, FALSE);
+    g_return_val_if_fail (GST_MPD_MULT_SEGMENT_BASE_NODE
+        (stream->cur_seg_template)->SegmentTimeline == NULL, FALSE);
     if (!GST_CLOCK_TIME_IS_VALID (duration)) {
       return FALSE;
     }
@@ -1775,8 +1806,8 @@ gst_mpd_client_get_next_fragment_timestamp (GstMPDClient * client,
         gst_mpd_client_get_segment_duration (client, stream, NULL);
     guint segments_count = gst_mpd_client_get_segments_counts (client, stream);
 
-    g_return_val_if_fail (stream->cur_seg_template->MultSegBaseType->
-        SegmentTimeline == NULL, FALSE);
+    g_return_val_if_fail (GST_MPD_MULT_SEGMENT_BASE_NODE
+        (stream->cur_seg_template)->SegmentTimeline == NULL, FALSE);
     if (!GST_CLOCK_TIME_IS_VALID (duration) || (segments_count > 0
             && stream->segment_index >= segments_count)) {
       return FALSE;
@@ -1878,8 +1909,8 @@ gst_mpd_client_get_next_fragment (GstMPDClient * client,
         stream, NULL);
     guint segments_count = gst_mpd_client_get_segments_counts (client, stream);
 
-    g_return_val_if_fail (stream->cur_seg_template->MultSegBaseType->
-        SegmentTimeline == NULL, FALSE);
+    g_return_val_if_fail (GST_MPD_MULT_SEGMENT_BASE_NODE
+        (stream->cur_seg_template)->SegmentTimeline == NULL, FALSE);
     if (!GST_CLOCK_TIME_IS_VALID (duration) || (segments_count > 0
             && stream->segment_index >= segments_count)) {
       return FALSE;
@@ -1949,7 +1980,8 @@ gst_mpd_client_get_next_fragment (GstMPDClient * client,
           gst_mpdparser_build_URL_from_template (stream->cur_seg_template->
           media, stream->cur_representation->id,
           stream->segment_index +
-          stream->cur_seg_template->MultSegBaseType->startNumber,
+          GST_MPD_MULT_SEGMENT_BASE_NODE (stream->
+              cur_seg_template)->startNumber,
           stream->cur_representation->bandwidth,
           stream->segment_index * fragment->duration);
       if (stream->cur_seg_template->index) {
@@ -1957,7 +1989,8 @@ gst_mpd_client_get_next_fragment (GstMPDClient * client,
             gst_mpdparser_build_URL_from_template (stream->cur_seg_template->
             index, stream->cur_representation->id,
             stream->segment_index +
-            stream->cur_seg_template->MultSegBaseType->startNumber,
+            GST_MPD_MULT_SEGMENT_BASE_NODE (stream->
+                cur_seg_template)->startNumber,
             stream->cur_representation->bandwidth,
             stream->segment_index * fragment->duration);
       }
@@ -2255,8 +2288,8 @@ gst_mpd_client_get_next_fragment_duration (GstMPDClient * client,
         gst_mpd_client_get_segment_duration (client, stream, NULL);
     guint segments_count = gst_mpd_client_get_segments_counts (client, stream);
 
-    g_return_val_if_fail (stream->cur_seg_template->
-        MultSegBaseType->SegmentTimeline == NULL, 0);
+    g_return_val_if_fail (GST_MPD_MULT_SEGMENT_BASE_NODE
+        (stream->cur_seg_template)->SegmentTimeline == NULL, 0);
 
     if (!GST_CLOCK_TIME_IS_VALID (duration) || (segments_count > 0
             && seg_idx >= segments_count)) {
@@ -2440,9 +2473,10 @@ gst_mpd_client_get_rep_idx_with_max_bandwidth (GList * Representations,
     if (!representation)
       continue;
 
-    framerate = representation->RepresentationBase->frameRate;
+    framerate = GST_MPD_REPRESENTATION_BASE_NODE (representation)->frameRate;
     if (!framerate)
-      framerate = representation->RepresentationBase->maxFrameRate;
+      framerate =
+          GST_MPD_REPRESENTATION_BASE_NODE (representation)->maxFrameRate;
 
     if (framerate && max_video_framerate_n > 0) {
       if (gst_util_fraction_compare (framerate->num, framerate->den,
@@ -2451,10 +2485,12 @@ gst_mpd_client_get_rep_idx_with_max_bandwidth (GList * Representations,
     }
 
     if (max_video_width > 0
-        && representation->RepresentationBase->width > max_video_width)
+        && GST_MPD_REPRESENTATION_BASE_NODE (representation)->width >
+        max_video_width)
       continue;
     if (max_video_height > 0
-        && representation->RepresentationBase->height > max_video_height)
+        && GST_MPD_REPRESENTATION_BASE_NODE (representation)->height >
+        max_video_height)
       continue;
 
     if (representation->bandwidth <= max_bandwidth &&
@@ -2495,8 +2531,8 @@ gst_mpd_client_get_segments_counts (GstMPDClient * client,
 
   if (stream->segments)
     return stream->segments->len;
-  g_return_val_if_fail (stream->cur_seg_template->
-      MultSegBaseType->SegmentTimeline == NULL, 0);
+  g_return_val_if_fail (GST_MPD_MULT_SEGMENT_BASE_NODE
+      (stream->cur_seg_template)->SegmentTimeline == NULL, 0);
 
   stream_period = gst_mpd_client_get_stream_period (client);
   if (stream_period->duration != -1)
@@ -2552,16 +2588,20 @@ gst_mpd_client_active_stream_contains_subtitles (GstActiveStream * stream)
   const gchar *adapt_set_codecs;
   const gchar *rep_codecs;
 
-  mimeType = stream->cur_representation->RepresentationBase->mimeType;
+  mimeType =
+      GST_MPD_REPRESENTATION_BASE_NODE (stream->cur_representation)->mimeType;
   if (!mimeType)
-    mimeType = stream->cur_adapt_set->RepresentationBase->mimeType;
+    mimeType =
+        GST_MPD_REPRESENTATION_BASE_NODE (stream->cur_adapt_set)->mimeType;
 
   if (g_strcmp0 (mimeType, "application/ttml+xml") == 0 ||
       g_strcmp0 (mimeType, "text/vtt") == 0)
     return TRUE;
 
-  adapt_set_codecs = stream->cur_adapt_set->RepresentationBase->codecs;
-  rep_codecs = stream->cur_representation->RepresentationBase->codecs;
+  adapt_set_codecs =
+      GST_MPD_REPRESENTATION_BASE_NODE (stream->cur_adapt_set)->codecs;
+  rep_codecs =
+      GST_MPD_REPRESENTATION_BASE_NODE (stream->cur_representation)->codecs;
 
   return (adapt_set_codecs && g_str_has_prefix (adapt_set_codecs, "stpp"))
       || (rep_codecs && g_str_has_prefix (rep_codecs, "stpp"));
@@ -2577,9 +2617,11 @@ gst_mpd_client_get_stream_caps (GstActiveStream * stream)
       || stream->cur_representation == NULL)
     return NULL;
 
-  mimeType = stream->cur_representation->RepresentationBase->mimeType;
+  mimeType =
+      GST_MPD_REPRESENTATION_BASE_NODE (stream->cur_representation)->mimeType;
   if (mimeType == NULL) {
-    mimeType = stream->cur_adapt_set->RepresentationBase->mimeType;
+    mimeType =
+        GST_MPD_REPRESENTATION_BASE_NODE (stream->cur_adapt_set)->mimeType;
   }
 
   caps_string = gst_mpd_helper_mimetype_to_caps (mimeType);
@@ -2612,9 +2654,9 @@ gst_mpd_client_get_video_stream_width (GstActiveStream * stream)
       || stream->cur_representation == NULL)
     return 0;
 
-  width = stream->cur_representation->RepresentationBase->width;
+  width = GST_MPD_REPRESENTATION_BASE_NODE (stream->cur_representation)->width;
   if (width == 0) {
-    width = stream->cur_adapt_set->RepresentationBase->width;
+    width = GST_MPD_REPRESENTATION_BASE_NODE (stream->cur_adapt_set)->width;
   }
 
   return width;
@@ -2629,9 +2671,10 @@ gst_mpd_client_get_video_stream_height (GstActiveStream * stream)
       || stream->cur_representation == NULL)
     return 0;
 
-  height = stream->cur_representation->RepresentationBase->height;
+  height =
+      GST_MPD_REPRESENTATION_BASE_NODE (stream->cur_representation)->height;
   if (height == 0) {
-    height = stream->cur_adapt_set->RepresentationBase->height;
+    height = GST_MPD_REPRESENTATION_BASE_NODE (stream->cur_adapt_set)->height;
   }
 
   return height;
@@ -2645,32 +2688,50 @@ gst_mpd_client_get_video_stream_framerate (GstActiveStream * stream,
     return FALSE;
 
   if (stream->cur_adapt_set &&
-      stream->cur_adapt_set->RepresentationBase->frameRate != NULL) {
-    *fps_num = stream->cur_adapt_set->RepresentationBase->frameRate->num;
-    *fps_den = stream->cur_adapt_set->RepresentationBase->frameRate->den;
+      GST_MPD_REPRESENTATION_BASE_NODE (stream->cur_adapt_set)->frameRate !=
+      NULL) {
+    *fps_num =
+        GST_MPD_REPRESENTATION_BASE_NODE (stream->cur_adapt_set)->
+        frameRate->num;
+    *fps_den =
+        GST_MPD_REPRESENTATION_BASE_NODE (stream->cur_adapt_set)->
+        frameRate->den;
     return TRUE;
   }
 
   if (stream->cur_adapt_set &&
-      stream->cur_adapt_set->RepresentationBase->maxFrameRate != NULL) {
-    *fps_num = stream->cur_adapt_set->RepresentationBase->maxFrameRate->num;
-    *fps_den = stream->cur_adapt_set->RepresentationBase->maxFrameRate->den;
+      GST_MPD_REPRESENTATION_BASE_NODE (stream->cur_adapt_set)->maxFrameRate !=
+      NULL) {
+    *fps_num =
+        GST_MPD_REPRESENTATION_BASE_NODE (stream->cur_adapt_set)->
+        maxFrameRate->num;
+    *fps_den =
+        GST_MPD_REPRESENTATION_BASE_NODE (stream->cur_adapt_set)->
+        maxFrameRate->den;
     return TRUE;
   }
 
   if (stream->cur_representation &&
-      stream->cur_representation->RepresentationBase->frameRate != NULL) {
-    *fps_num = stream->cur_representation->RepresentationBase->frameRate->num;
-    *fps_den = stream->cur_representation->RepresentationBase->frameRate->den;
+      GST_MPD_REPRESENTATION_BASE_NODE (stream->
+          cur_representation)->frameRate != NULL) {
+    *fps_num =
+        GST_MPD_REPRESENTATION_BASE_NODE (stream->
+        cur_representation)->frameRate->num;
+    *fps_den =
+        GST_MPD_REPRESENTATION_BASE_NODE (stream->
+        cur_representation)->frameRate->den;
     return TRUE;
   }
 
   if (stream->cur_representation &&
-      stream->cur_representation->RepresentationBase->maxFrameRate != NULL) {
+      GST_MPD_REPRESENTATION_BASE_NODE (stream->
+          cur_representation)->maxFrameRate != NULL) {
     *fps_num =
-        stream->cur_representation->RepresentationBase->maxFrameRate->num;
+        GST_MPD_REPRESENTATION_BASE_NODE (stream->
+        cur_representation)->maxFrameRate->num;
     *fps_den =
-        stream->cur_representation->RepresentationBase->maxFrameRate->den;
+        GST_MPD_REPRESENTATION_BASE_NODE (stream->
+        cur_representation)->maxFrameRate->den;
     return TRUE;
   }
 
@@ -2686,9 +2747,13 @@ gst_mpd_client_get_audio_stream_rate (GstActiveStream * stream)
       || stream->cur_representation == NULL)
     return 0;
 
-  rate = stream->cur_representation->RepresentationBase->audioSamplingRate;
+  rate =
+      GST_MPD_REPRESENTATION_BASE_NODE (stream->
+      cur_representation)->audioSamplingRate;
   if (rate == NULL) {
-    rate = stream->cur_adapt_set->RepresentationBase->audioSamplingRate;
+    rate =
+        GST_MPD_REPRESENTATION_BASE_NODE (stream->
+        cur_adapt_set)->audioSamplingRate;
   }
 
   return rate ? atoi (rate) : 0;
@@ -2729,10 +2794,10 @@ gst_mpd_client_get_list_and_nb_of_audio_language (GstMPDClient * client,
       rep =
           gst_mpd_client_get_lowest_representation (adapt_set->Representations);
       mimeType = NULL;
-      if (rep->RepresentationBase)
-        mimeType = rep->RepresentationBase->mimeType;
-      if (!mimeType && adapt_set->RepresentationBase) {
-        mimeType = adapt_set->RepresentationBase->mimeType;
+      if (GST_MPD_REPRESENTATION_BASE_NODE (rep))
+        mimeType = GST_MPD_REPRESENTATION_BASE_NODE (rep)->mimeType;
+      if (!mimeType && GST_MPD_REPRESENTATION_BASE_NODE (adapt_set)) {
+        mimeType = GST_MPD_REPRESENTATION_BASE_NODE (adapt_set)->mimeType;
       }
 
       if (gst_mpd_helper_strncmp_ext (mimeType, this_mimeType) == 0) {
index 8d165a9..ccf9923 100644 (file)
@@ -57,6 +57,9 @@ void gst_mpd_client_free (GstMPDClient * client);
 /* main mpd parsing methods from xml data */
 gboolean gst_mpd_client_parse (GstMPDClient * client, const gchar * data, gint size);
 
+/* xml generator */
+gboolean gst_mpd_client_get_xml_content (GstMPDClient * client, gchar ** data, gint * size);
+
 void gst_mpd_client_set_uri_downloader (GstMPDClient * client, GstUriDownloader * download);
 void  gst_mpd_client_check_profiles (GstMPDClient * client);
 void gst_mpd_client_fetch_on_load_external_resources (GstMPDClient * client);
index e8983f7..9498aa4 100644 (file)
@@ -21,9 +21,8 @@
 #include "gstmpdcontentcomponentnode.h"
 #include "gstmpdparser.h"
 
-
 G_DEFINE_TYPE (GstMPDContentComponentNode, gst_mpd_content_component_node,
-    GST_TYPE_OBJECT);
+    GST_TYPE_MPD_NODE);
 
 /* GObject VMethods */
 
@@ -38,24 +37,60 @@ gst_mpd_content_component_node_finalize (GObject * object)
     xmlFree (self->contentType);
   g_slice_free (GstXMLRatio, self->par);
   g_list_free_full (self->Accessibility,
-      (GDestroyNotify) gst_mpd_helper_descriptor_type_free);
+      (GDestroyNotify) gst_mpd_descriptor_type_node_free);
   g_list_free_full (self->Role,
-      (GDestroyNotify) gst_mpd_helper_descriptor_type_free);
+      (GDestroyNotify) gst_mpd_descriptor_type_node_free);
   g_list_free_full (self->Rating,
-      (GDestroyNotify) gst_mpd_helper_descriptor_type_free);
+      (GDestroyNotify) gst_mpd_descriptor_type_node_free);
   g_list_free_full (self->Viewpoint,
-      (GDestroyNotify) gst_mpd_helper_descriptor_type_free);
+      (GDestroyNotify) gst_mpd_descriptor_type_node_free);
 
   G_OBJECT_CLASS (gst_mpd_content_component_node_parent_class)->finalize
       (object);
 }
 
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_content_component_get_xml_node (GstMPDNode * node)
+{
+  xmlNodePtr content_component_xml_node = NULL;
+  GstMPDContentComponentNode *self = GST_MPD_CONTENT_COMPONENT_NODE (node);
+  content_component_xml_node =
+      xmlNewNode (NULL, (xmlChar *) "ContentComponent");
+
+  gst_xml_helper_set_prop_uint (content_component_xml_node, "id", self->id);
+  gst_xml_helper_set_prop_string (content_component_xml_node, "lang",
+      self->lang);
+  gst_xml_helper_set_prop_string (content_component_xml_node, "contentType",
+      self->contentType);
+  gst_xml_helper_set_prop_ratio (content_component_xml_node, "par", self->par);
+
+  g_list_foreach (self->Accessibility, gst_mpd_node_get_list_item,
+      content_component_xml_node);
+  g_list_foreach (self->Role, gst_mpd_node_get_list_item,
+      content_component_xml_node);
+  g_list_foreach (self->Rating, gst_mpd_node_get_list_item,
+      content_component_xml_node);
+  g_list_foreach (self->Viewpoint, gst_mpd_node_get_list_item,
+      content_component_xml_node);
+
+  return content_component_xml_node;
+}
+
 static void
 gst_mpd_content_component_node_class_init (GstMPDContentComponentNodeClass *
     klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GObjectClass *object_class;
+  GstMPDNodeClass *m_klass;
+
+  object_class = G_OBJECT_CLASS (klass);
+  m_klass = GST_MPD_NODE_CLASS (klass);
+
   object_class->finalize = gst_mpd_content_component_node_finalize;
+
+  m_klass->get_xml_node = gst_mpd_content_component_get_xml_node;
 }
 
 static void
index 9521100..51a3b24 100644 (file)
 G_BEGIN_DECLS
 
 #define GST_TYPE_MPD_CONTENT_COMPONENT_NODE gst_mpd_content_component_node_get_type ()
-#define GST_MPD_CONTENT_COMPONENT_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MPD_CONTENT_COMPONENT_NODE, GstMPDContentComponentNode))
-#define GST_MPD_CONTENT_COMPONENT_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MPD_CONTENT_COMPONENT_NODE, GstMPDContentComponentNodeClass))
-#define GST_IS_MPD_CONTENT_COMPONENT_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MPD_CONTENT_COMPONENT_NODE))
-#define GST_IS_MPD_CONTENT_COMPONENT_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MPD_CONTENT_COMPONENT_NODE))
-#define GST_MPD_CONTENT_COMPONENT_NODE_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MPD_CONTENT_COMPONENT_NODE, GstMPDContentComponentNodeClass))
-
-typedef struct _GstMPDContentComponentNode                GstMPDContentComponentNode;
-typedef struct _GstMPDContentComponentNodeClass           GstMPDContentComponentNodeClass;
-
+G_DECLARE_FINAL_TYPE (GstMPDContentComponentNode, gst_mpd_content_component_node, GST, MPD_CONTENT_COMPONENT_NODE, GstMPDNode)
 
 struct _GstMPDContentComponentNode
 {
@@ -59,13 +46,6 @@ struct _GstMPDContentComponentNode
   GList *Viewpoint;
 };
 
-struct _GstMPDContentComponentNodeClass {
-  GstObjectClass parent_class;
-};
-
-
-G_GNUC_INTERNAL GType gst_mpd_content_component_node_get_type (void);
-
 GstMPDContentComponentNode * gst_mpd_content_component_node_new (void);
 void gst_mpd_content_component_node_free (GstMPDContentComponentNode* self);
 
diff --git a/ext/dash/gstmpddescriptortypenode.c b/ext/dash/gstmpddescriptortypenode.c
new file mode 100644 (file)
index 0000000..a91d4b0
--- /dev/null
@@ -0,0 +1,99 @@
+/* GStreamer
+ *
+ * Copyright (C) 2019 Collabora Ltd.
+ *   Author: Stéphane Cerveau <scerveau@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+#include "gstmpddescriptortypenode.h"
+#include "gstmpdparser.h"
+
+G_DEFINE_TYPE (GstMPDDescriptorTypeNode, gst_mpd_descriptor_type_node,
+    GST_TYPE_MPD_NODE);
+
+/* GObject VMethods */
+
+static void
+gst_mpd_descriptor_type_node_finalize (GObject * object)
+{
+  GstMPDDescriptorTypeNode *self = GST_MPD_DESCRIPTOR_TYPE_NODE (object);
+
+  if (self->schemeIdUri)
+    xmlFree (self->schemeIdUri);
+  if (self->value)
+    xmlFree (self->value);
+  g_free (self->node_name);
+
+  G_OBJECT_CLASS (gst_mpd_descriptor_type_node_parent_class)->finalize (object);
+}
+
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_descriptor_type_get_xml_node (GstMPDNode * node)
+{
+  xmlNodePtr descriptor_type_xml_node = NULL;
+  GstMPDDescriptorTypeNode *self = GST_MPD_DESCRIPTOR_TYPE_NODE (node);
+
+  descriptor_type_xml_node = xmlNewNode (NULL, (xmlChar *) self->node_name);
+
+  gst_xml_helper_set_prop_string (descriptor_type_xml_node, "schemeIdUri",
+      self->schemeIdUri);
+
+  gst_xml_helper_set_prop_string (descriptor_type_xml_node, "value",
+      self->value);
+
+  return descriptor_type_xml_node;
+}
+
+static void
+gst_mpd_descriptor_type_node_class_init (GstMPDDescriptorTypeNodeClass * klass)
+{
+  GObjectClass *object_class;
+  GstMPDNodeClass *m_klass;
+
+  object_class = G_OBJECT_CLASS (klass);
+  m_klass = GST_MPD_NODE_CLASS (klass);
+
+  object_class->finalize = gst_mpd_descriptor_type_node_finalize;
+
+  m_klass->get_xml_node = gst_mpd_descriptor_type_get_xml_node;
+}
+
+static void
+gst_mpd_descriptor_type_node_init (GstMPDDescriptorTypeNode * self)
+{
+  if (self->schemeIdUri)
+    xmlFree (self->schemeIdUri);
+  if (self->value)
+    xmlFree (self->value);
+}
+
+GstMPDDescriptorTypeNode *
+gst_mpd_descriptor_type_node_new (const gchar * name)
+{
+  GstMPDDescriptorTypeNode *self =
+      g_object_new (GST_TYPE_MPD_DESCRIPTOR_TYPE_NODE, NULL);
+  self->node_name = g_strdup (name);
+  return self;
+}
+
+void
+gst_mpd_descriptor_type_node_free (GstMPDDescriptorTypeNode * self)
+{
+  if (self)
+    gst_object_unref (self);
+}
diff --git a/ext/dash/gstmpddescriptortypenode.h b/ext/dash/gstmpddescriptortypenode.h
new file mode 100644 (file)
index 0000000..d4cbbd5
--- /dev/null
@@ -0,0 +1,46 @@
+/* GStreamer
+ *
+ * Copyright (C) 2019 Collabora Ltd.
+ *   Author: Stéphane Cerveau <scerveau@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library (COPYING); if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSTMPDDESCRIPTORTYPENODE_H__
+#define __GSTMPDDESCRIPTORTYPENODE_H__
+
+#include <gst/gst.h>
+#include "gstmpdhelper.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_MPD_DESCRIPTOR_TYPE_NODE gst_mpd_descriptor_type_node_get_type ()
+G_DECLARE_FINAL_TYPE (GstMPDDescriptorTypeNode, gst_mpd_descriptor_type_node, GST, MPD_DESCRIPTOR_TYPE_NODE, GstMPDNode)
+
+
+struct _GstMPDDescriptorTypeNode
+{
+  GstObject     parent_instance;
+  gchar *node_name;
+  gchar *schemeIdUri;
+  gchar *value;
+};
+
+GstMPDDescriptorTypeNode * gst_mpd_descriptor_type_node_new (const gchar* name);
+void gst_mpd_descriptor_type_node_free (GstMPDDescriptorTypeNode* self);
+
+G_END_DECLS
+
+#endif /* __GSTMPDDESCRIPTORTYPENODE_H__ */
index 7c10225..a66de89 100644 (file)
@@ -78,102 +78,6 @@ gst_mpd_helper_get_SAP_type (xmlNode * a_node,
   return exists;
 }
 
-GstMPDURLType *
-gst_mpd_helper_URLType_clone (GstMPDURLType * url)
-{
-
-  GstMPDURLType *clone = NULL;
-
-  if (url) {
-    clone = g_slice_new0 (GstMPDURLType);
-    if (url->sourceURL) {
-      clone->sourceURL = xmlMemStrdup (url->sourceURL);
-    }
-    clone->range = gst_xml_helper_clone_range (url->range);
-  }
-
-  return clone;
-}
-
-void
-gst_mpd_helper_url_type_node_free (GstMPDURLType * url_type_node)
-{
-  if (url_type_node) {
-    if (url_type_node->sourceURL)
-      xmlFree (url_type_node->sourceURL);
-    g_slice_free (GstXMLRange, url_type_node->range);
-    g_slice_free (GstMPDURLType, url_type_node);
-  }
-}
-
-void
-gst_mpd_helper_descriptor_type_free (GstMPDDescriptorType * descriptor_type)
-{
-  if (descriptor_type) {
-    if (descriptor_type->schemeIdUri)
-      xmlFree (descriptor_type->schemeIdUri);
-    if (descriptor_type->value)
-      xmlFree (descriptor_type->value);
-    g_slice_free (GstMPDDescriptorType, descriptor_type);
-  }
-}
-
-void
-gst_mpd_helper_segment_base_type_free (GstMPDSegmentBaseType * seg_base_type)
-{
-  if (seg_base_type) {
-    if (seg_base_type->indexRange)
-      g_slice_free (GstXMLRange, seg_base_type->indexRange);
-    gst_mpd_helper_url_type_node_free (seg_base_type->Initialization);
-    gst_mpd_helper_url_type_node_free (seg_base_type->RepresentationIndex);
-    g_slice_free (GstMPDSegmentBaseType, seg_base_type);
-  }
-}
-
-void
-gst_mpd_helper_mult_seg_base_type_free (GstMPDMultSegmentBaseType *
-    mult_seg_base_type)
-{
-  if (mult_seg_base_type) {
-    /* SegmentBaseType extension */
-    gst_mpd_helper_segment_base_type_free (mult_seg_base_type->SegBaseType);
-    gst_mpd_segment_timeline_node_free (mult_seg_base_type->SegmentTimeline);
-    gst_mpd_helper_url_type_node_free (mult_seg_base_type->BitstreamSwitching);
-    g_slice_free (GstMPDMultSegmentBaseType, mult_seg_base_type);
-  }
-}
-
-void
-gst_mpd_helper_representation_base_type_free (GstMPDRepresentationBaseType *
-    representation_base)
-{
-  if (representation_base) {
-    if (representation_base->profiles)
-      xmlFree (representation_base->profiles);
-    g_slice_free (GstXMLRatio, representation_base->sar);
-    g_slice_free (GstXMLFrameRate, representation_base->frameRate);
-    g_slice_free (GstXMLFrameRate, representation_base->minFrameRate);
-    g_slice_free (GstXMLFrameRate, representation_base->maxFrameRate);
-    if (representation_base->audioSamplingRate)
-      xmlFree (representation_base->audioSamplingRate);
-    if (representation_base->mimeType)
-      xmlFree (representation_base->mimeType);
-    if (representation_base->segmentProfiles)
-      xmlFree (representation_base->segmentProfiles);
-    if (representation_base->codecs)
-      xmlFree (representation_base->codecs);
-    if (representation_base->scanType)
-      xmlFree (representation_base->scanType);
-    g_list_free_full (representation_base->FramePacking,
-        (GDestroyNotify) gst_mpd_helper_descriptor_type_free);
-    g_list_free_full (representation_base->AudioChannelConfiguration,
-        (GDestroyNotify) gst_mpd_helper_descriptor_type_free);
-    g_list_free_full (representation_base->ContentProtection,
-        (GDestroyNotify) gst_mpd_helper_descriptor_type_free);
-    g_slice_free (GstMPDRepresentationBaseType, representation_base);
-  }
-}
-
 const gchar *
 gst_mpd_helper_mimetype_to_caps (const gchar * mimeType)
 {
index 5bf35b6..95eaec9 100644 (file)
 #define __GST_MPDHELPER_H__
 
 #include "gstxmlhelper.h"
+#include "gstmpdnode.h"
+#include "gstmpdurltypenode.h"
+#include "gstmpddescriptortypenode.h"
 #include "gstmpdsegmenttimelinenode.h"
+#include "gstmpdsegmentbasenode.h"
 
-G_BEGIN_DECLS
 
-typedef enum
-{
-  GST_MPD_FILE_TYPE_STATIC,
-  GST_MPD_FILE_TYPE_DYNAMIC
-} GstMPDFileType;
+G_BEGIN_DECLS
 
 typedef enum
 {
@@ -45,86 +44,22 @@ typedef enum
 
 typedef enum
 {
-  GST_MPD_XLINK_ACTUATE_ON_REQUEST,
-  GST_MPD_XLINK_ACTUATE_ON_LOAD
-} GstMPDXLinkActuate;
-
-typedef struct _GstMPDURLType
-{
-  gchar *sourceURL;
-  GstXMLRange *range;
-} GstMPDURLType;
-
-typedef struct _GstMPDDescriptorType
-{
-  gchar *schemeIdUri;
-  gchar *value;
-} GstMPDDescriptorType;
+  GST_MPD_FILE_TYPE_STATIC = 0,
+  GST_MPD_FILE_TYPE_DYNAMIC
+} GstMPDFileType;
 
-typedef struct _GstMPDSegmentBaseType
-{
-  guint timescale;
-  guint64 presentationTimeOffset;
-  GstXMLRange *indexRange;
-  gboolean indexRangeExact;
-  /* Initialization node */
-  GstMPDURLType *Initialization;
-  /* RepresentationIndex node */
-  GstMPDURLType *RepresentationIndex;
-} GstMPDSegmentBaseType;
+#define GST_MPD_XLINK_ACTUATE_ON_LOAD_STR "onLoad"
 
-typedef struct _GstMPDMultSegmentBaseType
+typedef enum
 {
-  guint duration;                  /* in seconds */
-  guint startNumber;
-  /* SegmentBaseType extension */
-  GstMPDSegmentBaseType *SegBaseType;
-  /* SegmentTimeline node */
-  GstMPDSegmentTimelineNode *SegmentTimeline;
-  /* BitstreamSwitching node */
-  GstMPDURLType *BitstreamSwitching;
-} GstMPDMultSegmentBaseType;
+  GST_MPD_XLINK_ACTUATE_ON_REQUEST,
+  GST_MPD_XLINK_ACTUATE_ON_LOAD
+} GstMPDXLinkActuate;
 
-typedef struct _GstMPDRepresentationBaseType
-{
-  gchar *profiles;
-  guint width;
-  guint height;
-  GstXMLRatio *sar;
-  GstXMLFrameRate *minFrameRate;
-  GstXMLFrameRate *maxFrameRate;
-  GstXMLFrameRate *frameRate;
-  gchar *audioSamplingRate;
-  gchar *mimeType;
-  gchar *segmentProfiles;
-  gchar *codecs;
-  gdouble maximumSAPPeriod;
-  GstMPDSAPType startWithSAP;
-  gdouble maxPlayoutRate;
-  gboolean codingDependency;
-  gchar *scanType;
-  /* list of FramePacking DescriptorType nodes */
-  GList *FramePacking;
-  /* list of AudioChannelConfiguration DescriptorType nodes */
-  GList *AudioChannelConfiguration;
-  /* list of ContentProtection DescriptorType nodes */
-  GList *ContentProtection;
-} GstMPDRepresentationBaseType;
 
 gboolean gst_mpd_helper_get_mpd_type (xmlNode * a_node, const gchar * property_name, GstMPDFileType * property_value);
 gboolean gst_mpd_helper_get_SAP_type (xmlNode * a_node, const gchar * property_name, GstMPDSAPType * property_value);
 
-GstMPDURLType *gst_mpd_helper_URLType_clone (GstMPDURLType * url);
-void gst_mpd_helper_url_type_node_free (GstMPDURLType * url_type_node);
-void gst_mpd_helper_descriptor_type_free (GstMPDDescriptorType *
-    descriptor_type);
-void gst_mpd_helper_segment_base_type_free (GstMPDSegmentBaseType * seg_base_type);
-void gst_mpd_helper_mult_seg_base_type_free (GstMPDMultSegmentBaseType *
-    mult_seg_base_type);
-void
-gst_mpd_helper_representation_base_type_free (GstMPDRepresentationBaseType *
-    representation_base);
-
 const gchar * gst_mpd_helper_mimetype_to_caps (const gchar * mimeType);
 GstUri *gst_mpd_helper_combine_urls (GstUri * base, GList * list, gchar ** query, guint idx);
 int gst_mpd_helper_strncmp_ext (const char *s1, const char *s2);
diff --git a/ext/dash/gstmpdlocationnode.c b/ext/dash/gstmpdlocationnode.c
new file mode 100644 (file)
index 0000000..69459be
--- /dev/null
@@ -0,0 +1,84 @@
+/* GStreamer
+ *
+ * Copyright (C) 2019 Collabora Ltd.
+ *   Author: Stéphane Cerveau <scerveau@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+#include "gstmpdlocationnode.h"
+#include "gstmpdparser.h"
+
+G_DEFINE_TYPE (GstMPDLocationNode, gst_mpd_location_node, GST_TYPE_MPD_NODE);
+
+/* GObject VMethods */
+
+static void
+gst_mpd_location_node_finalize (GObject * object)
+{
+  GstMPDLocationNode *self = GST_MPD_LOCATION_NODE (object);
+
+  g_free (self->location);
+
+  G_OBJECT_CLASS (gst_mpd_location_node_parent_class)->finalize (object);
+}
+
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_location_get_xml_node (GstMPDNode * node)
+{
+  xmlNodePtr location_xml_node = NULL;
+  GstMPDLocationNode *self = GST_MPD_LOCATION_NODE (node);
+
+  location_xml_node = xmlNewNode (NULL, (xmlChar *) "Location");
+
+  if (self->location)
+    gst_xml_helper_set_content (location_xml_node, self->location);
+
+  return location_xml_node;
+}
+
+static void
+gst_mpd_location_node_class_init (GstMPDLocationNodeClass * klass)
+{
+  GObjectClass *object_class;
+  GstMPDNodeClass *m_klass;
+
+  object_class = G_OBJECT_CLASS (klass);
+  object_class->finalize = gst_mpd_location_node_finalize;
+
+  m_klass = GST_MPD_NODE_CLASS (klass);
+  m_klass->get_xml_node = gst_mpd_location_get_xml_node;
+}
+
+static void
+gst_mpd_location_node_init (GstMPDLocationNode * self)
+{
+  self->location = NULL;
+}
+
+GstMPDLocationNode *
+gst_mpd_location_node_new (void)
+{
+  return g_object_new (GST_TYPE_MPD_LOCATION_NODE, NULL);
+}
+
+void
+gst_mpd_location_node_free (GstMPDLocationNode * self)
+{
+  if (self)
+    gst_object_unref (self);
+}
diff --git a/ext/dash/gstmpdlocationnode.h b/ext/dash/gstmpdlocationnode.h
new file mode 100644 (file)
index 0000000..2c2f338
--- /dev/null
@@ -0,0 +1,44 @@
+/* GStreamer
+ *
+ * Copyright (C) 2019 Collabora Ltd.
+ *   Author: Stéphane Cerveau <scerveau@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library (COPYING); if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSTMPDLOCATIONNODE_H__
+#define __GSTMPDLOCATIONNODE_H__
+
+#include <gst/gst.h>
+#include "gstmpdhelper.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_MPD_LOCATION_NODE gst_mpd_location_node_get_type ()
+G_DECLARE_FINAL_TYPE (GstMPDLocationNode, gst_mpd_location_node, GST, MPD_LOCATION_NODE, GstMPDNode)
+
+
+struct _GstMPDLocationNode
+{
+  GstObject     parent_instance;
+  gchar *location;
+};
+
+GstMPDLocationNode * gst_mpd_location_node_new (void);
+void gst_mpd_location_node_free (GstMPDLocationNode* self);
+
+G_END_DECLS
+
+#endif /* __GSTMPDLOCATIONNODE_H__ */
index 1c1d5e4..79d6c5c 100644 (file)
@@ -21,7 +21,7 @@
 #include "gstmpdmetricsnode.h"
 #include "gstmpdparser.h"
 
-G_DEFINE_TYPE (GstMPDMetricsNode, gst_mpd_metrics_node, GST_TYPE_OBJECT);
+G_DEFINE_TYPE (GstMPDMetricsNode, gst_mpd_metrics_node, GST_TYPE_MPD_NODE);
 
 /* GObject VMethods */
 
@@ -37,11 +37,39 @@ gst_mpd_metrics_node_finalize (GObject * object)
   G_OBJECT_CLASS (gst_mpd_metrics_node_parent_class)->finalize (object);
 }
 
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_metrics_get_xml_node (GstMPDNode * node)
+{
+  xmlNodePtr metrics_xml_node = NULL;
+  GstMPDMetricsNode *self = GST_MPD_METRICS_NODE (node);
+
+  metrics_xml_node = xmlNewNode (NULL, (xmlChar *) "Metrics");
+
+  if (self->metrics)
+    gst_xml_helper_set_prop_string (metrics_xml_node, "metrics", self->metrics);
+
+  g_list_foreach (self->Reportings, gst_mpd_node_get_list_item,
+      metrics_xml_node);
+  g_list_foreach (self->MetricsRanges, gst_mpd_node_get_list_item,
+      metrics_xml_node);
+
+  return metrics_xml_node;
+}
+
 static void
 gst_mpd_metrics_node_class_init (GstMPDMetricsNodeClass * klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GObjectClass *object_class;
+  GstMPDNodeClass *m_klass;
+
+  object_class = G_OBJECT_CLASS (klass);
+  m_klass = GST_MPD_NODE_CLASS (klass);
+
   object_class->finalize = gst_mpd_metrics_node_finalize;
+
+  m_klass->get_xml_node = gst_mpd_metrics_get_xml_node;
 }
 
 static void
index ef3ec2b..87ad39d 100644 (file)
@@ -1,11 +1,7 @@
-/*
- * No description.
+/* GStreamer
  *
- * gstmpdmetricsnode.h
- *
- * Copyright (C) 2019 Collabora inc.
- * Authors:
- *   Stéphane Cerveau <scerveau@collabora.com>
+ * Copyright (C) 2019 Collabora Ltd.
+ *   Author: Stéphane Cerveau <scerveau@collabora.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 G_BEGIN_DECLS
 
 #define GST_TYPE_MPD_METRICS_NODE gst_mpd_metrics_node_get_type ()
-#define GST_MPD_METRICS_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MPD_METRICS_NODE, GstMPDMetricsNode))
-#define GST_MPD_METRICS_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MPD_METRICS_NODE, GstMPDMetricsNodeClass))
-#define GST_IS_MPD_METRICS_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MPD_METRICS_NODE))
-#define GST_IS_MPD_METRICS_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MPD_METRICS_NODE))
-#define GST_MPD_METRICS_NODE_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MPD_METRICS_NODE, GstMPDMetricsNodeClass))
-
-typedef struct _GstMPDMetricsNode                GstMPDMetricsNode;
-typedef struct _GstMPDMetricsNodeClass           GstMPDMetricsNodeClass;
+G_DECLARE_FINAL_TYPE (GstMPDMetricsNode, gst_mpd_metrics_node, GST, MPD_METRICS_NODE, GstMPDNode)
 
 
 struct _GstMPDMetricsNode
@@ -56,13 +40,6 @@ struct _GstMPDMetricsNode
   GList *Reportings;
 };
 
-struct _GstMPDMetricsNodeClass {
-  GstObjectClass parent_class;
-};
-
-
-G_GNUC_INTERNAL GType gst_mpd_metrics_node_get_type (void);
-
 GstMPDMetricsNode * gst_mpd_metrics_node_new (void);
 void gst_mpd_metrics_node_free (GstMPDMetricsNode* self);
 
index 1b8a9bd..5ceb498 100644 (file)
 #include "gstmpdparser.h"
 
 G_DEFINE_TYPE (GstMPDMetricsRangeNode, gst_mpd_metrics_range_node,
-    GST_TYPE_OBJECT);
+    GST_TYPE_MPD_NODE);
 
-/* GObject VMethods */
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_metrics_range_get_xml_node (GstMPDNode * node)
+{
+  xmlNodePtr metrics_range_xml_node = NULL;
+  GstMPDMetricsRangeNode *self = GST_MPD_METRICS_RANGE_NODE (node);
+
+  metrics_range_xml_node = xmlNewNode (NULL, (xmlChar *) "Range");
+
+  if (self->starttime)
+    gst_xml_helper_set_prop_duration (metrics_range_xml_node, "starttime",
+        self->starttime);
+  if (self->duration)
+    gst_xml_helper_set_prop_duration (metrics_range_xml_node, "duration",
+        self->duration);
+
+  return metrics_range_xml_node;
+}
 
 static void
 gst_mpd_metrics_range_node_class_init (GstMPDMetricsRangeNodeClass * klass)
 {
+  GstMPDNodeClass *m_klass;
+
+  m_klass = GST_MPD_NODE_CLASS (klass);
+
+  m_klass->get_xml_node = gst_mpd_metrics_range_get_xml_node;
 }
 
 static void
index 90709f9..ef3dae0 100644 (file)
 G_BEGIN_DECLS
 
 #define GST_TYPE_MPD_METRICS_RANGE_NODE gst_mpd_metrics_range_node_get_type ()
-#define GST_MPD_METRICS_RANGE_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MPD_METRICS_RANGE_NODE, GstMPDMetricsRangeNode))
-#define GST_MPD_METRICS_RANGE_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MPD_METRICS_RANGE_NODE, GstMPDMetricsRangeNodeClass))
-#define GST_IS_MPD_METRICS_RANGE_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MPD_METRICS_RANGE_NODE))
-#define GST_IS_MPD_METRICS_RANGE_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MPD_METRICS_RANGE_NODE))
-#define GST_MPD_METRICS_RANGE_NODE_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MPD_METRICS_RANGE_NODE, GstMPDMetricsRangeNodeClass))
-
-typedef struct _GstMPDMetricsRangeNode                GstMPDMetricsRangeNode;
-typedef struct _GstMPDMetricsRangeNodeClass           GstMPDMetricsRangeNodeClass;
-
+G_DECLARE_FINAL_TYPE (GstMPDMetricsRangeNode, gst_mpd_metrics_range_node, GST, MPD_METRICS_RANGE_NODE, GstMPDNode)
 
 struct _GstMPDMetricsRangeNode
 {
@@ -49,13 +36,6 @@ struct _GstMPDMetricsRangeNode
   guint64 duration;                  /* [ms] */
 };
 
-struct _GstMPDMetricsRangeNodeClass {
-  GstObjectClass parent_class;
-};
-
-
-G_GNUC_INTERNAL GType gst_mpd_metrics_range_node_get_type (void);
-
 GstMPDMetricsRangeNode * gst_mpd_metrics_range_node_new (void);
 void gst_mpd_metrics_range_node_free (GstMPDMetricsRangeNode* self);
 
diff --git a/ext/dash/gstmpdmultsegmentbasenode.c b/ext/dash/gstmpdmultsegmentbasenode.c
new file mode 100644 (file)
index 0000000..349bfa1
--- /dev/null
@@ -0,0 +1,97 @@
+/* GStreamer
+ *
+ * Copyright (C) 2019 Collabora Ltd.
+ *   Author: Stéphane Cerveau <scerveau@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+#include "gstmpdmultsegmentbasenode.h"
+#include "gstmpdparser.h"
+
+G_DEFINE_TYPE (GstMPDMultSegmentBaseNode, gst_mpd_mult_segment_base_node,
+    GST_TYPE_MPD_NODE);
+
+/* GObject VMethods */
+
+static void
+gst_mpd_mult_segment_base_node_finalize (GObject * object)
+{
+  GstMPDMultSegmentBaseNode *self = GST_MPD_MULT_SEGMENT_BASE_NODE (object);
+
+  gst_mpd_segment_base_node_free (self->SegmentBase);
+  gst_mpd_segment_timeline_node_free (self->SegmentTimeline);
+  gst_mpd_url_type_node_free (self->BitstreamSwitching);
+
+  G_OBJECT_CLASS (gst_mpd_mult_segment_base_node_parent_class)->finalize
+      (object);
+}
+
+/* Base class */
+
+static void
+gst_mpd_mult_segment_base_get_xml_node (GstMPDNode * node,
+    xmlNodePtr mult_segment_base_node)
+{
+  GstMPDMultSegmentBaseNode *self = GST_MPD_MULT_SEGMENT_BASE_NODE (node);
+
+  if (self->duration)
+    gst_xml_helper_set_prop_uint (mult_segment_base_node, "duration",
+        self->duration);
+  if (self->startNumber)
+    gst_xml_helper_set_prop_uint (mult_segment_base_node, "startNumber",
+        self->startNumber);
+  if (self->SegmentBase)
+    gst_mpd_node_add_child_node (GST_MPD_NODE (self->SegmentBase),
+        mult_segment_base_node);
+  if (self->SegmentTimeline)
+    gst_mpd_node_add_child_node (GST_MPD_NODE (self->SegmentTimeline),
+        mult_segment_base_node);
+  if (self->BitstreamSwitching)
+    gst_mpd_node_add_child_node (GST_MPD_NODE (self->BitstreamSwitching),
+        mult_segment_base_node);
+}
+
+static void
+gst_mpd_mult_segment_base_node_class_init (GstMPDMultSegmentBaseNodeClass *
+    klass)
+{
+  GObjectClass *object_class;
+
+  object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gst_mpd_mult_segment_base_node_finalize;
+}
+
+static void
+gst_mpd_mult_segment_base_node_init (GstMPDMultSegmentBaseNode * self)
+{
+  self->duration = 0;
+  self->startNumber = 0;
+  self->SegmentBase = NULL;
+  self->SegmentTimeline = NULL;
+  self->BitstreamSwitching = NULL;
+}
+
+void
+gst_mpd_mult_segment_base_node_add_child_node (GstMPDNode * node,
+    xmlNodePtr parent_xml_node)
+{
+  if (node) {
+    xmlNodePtr new_xml_node = gst_mpd_node_get_xml_pointer (node);
+    gst_mpd_mult_segment_base_get_xml_node (node, new_xml_node);
+    xmlAddChild (parent_xml_node, new_xml_node);
+  }
+}
diff --git a/ext/dash/gstmpdmultsegmentbasenode.h b/ext/dash/gstmpdmultsegmentbasenode.h
new file mode 100644 (file)
index 0000000..7f16549
--- /dev/null
@@ -0,0 +1,48 @@
+/* GStreamer
+ *
+ * Copyright (C) 2019 Collabora Ltd.
+ *   Author: Stéphane Cerveau <scerveau@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library (COPYING); if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSTMPDMULTSEGMENTBASENODE_H__
+#define __GSTMPDMULTSEGMENTBASENODE_H__
+
+#include <gst/gst.h>
+#include "gstmpdhelper.h"
+G_BEGIN_DECLS
+
+#define GST_TYPE_MPD_MULT_SEGMENT_BASE_NODE gst_mpd_mult_segment_base_node_get_type ()
+G_DECLARE_FINAL_TYPE (GstMPDMultSegmentBaseNode, gst_mpd_mult_segment_base_node, GST, MPD_MULT_SEGMENT_BASE_NODE, GstMPDNode)
+
+struct _GstMPDMultSegmentBaseNode
+{
+  GstObject     base;
+  guint duration;                  /* in seconds */
+  guint startNumber;
+  /* SegmentBaseType extension */
+  GstMPDSegmentBaseNode *SegmentBase;
+  /* SegmentTimeline node */
+  GstMPDSegmentTimelineNode *SegmentTimeline;
+  /* BitstreamSwitching node */
+  GstMPDURLTypeNode *BitstreamSwitching;
+};
+
+
+void gst_mpd_mult_segment_base_node_add_child_node (GstMPDNode* node, xmlNodePtr parent_xml_node);
+
+G_END_DECLS
+#endif /* __GSTMPDMULTSEGMENTBASENODE_H__ */
diff --git a/ext/dash/gstmpdnode.c b/ext/dash/gstmpdnode.c
new file mode 100644 (file)
index 0000000..f19dd0b
--- /dev/null
@@ -0,0 +1,78 @@
+/* GStreamer
+ *
+ * Copyright (C) 2019 Collabora Ltd.
+ *   Author: Stéphane Cerveau <scerveau@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+#include "gstmpdnode.h"
+
+G_DEFINE_TYPE (GstMPDNode, gst_mpd_node, GST_TYPE_OBJECT);
+
+/* GObject VMethods */
+
+static void
+gst_mpd_node_class_init (GstMPDNodeClass * klass)
+{
+}
+
+static void
+gst_mpd_node_init (GstMPDNode * self)
+{
+}
+
+void
+gst_mpd_node_get_list_item (gpointer data, gpointer user_data)
+{
+  GstMPDNode *node = (GstMPDNode *) data;
+  xmlNodePtr parent_xml_node = (xmlNodePtr) user_data;
+  xmlNodePtr new_xml_node = gst_mpd_node_get_xml_pointer (node);
+
+  xmlAddChild (parent_xml_node, new_xml_node);
+}
+
+void
+gst_mpd_node_add_child_node (GstMPDNode * child, xmlNodePtr parent)
+{
+  xmlNodePtr new_xml_node = gst_mpd_node_get_xml_pointer (child);
+  xmlAddChild (parent, new_xml_node);
+}
+
+gboolean
+gst_mpd_node_get_xml_buffer (GstMPDNode * node, gchar ** xml_content,
+    int *xml_size)
+{
+  GstMPDNodeClass *klass;
+
+  klass = GST_MPD_NODE_GET_CLASS (node);
+  if (klass->get_xml_buffer)
+    return klass->get_xml_buffer (node, xml_content, xml_size);
+  else
+    return FALSE;
+}
+
+xmlNodePtr
+gst_mpd_node_get_xml_pointer (GstMPDNode * node)
+{
+  GstMPDNodeClass *klass;
+  if (!node)
+    return NULL;
+  klass = GST_MPD_NODE_GET_CLASS (node);
+  if (klass->get_xml_node)
+    return klass->get_xml_node (node);
+  else
+    return NULL;
+}
diff --git a/ext/dash/gstmpdnode.h b/ext/dash/gstmpdnode.h
new file mode 100644 (file)
index 0000000..d0f48e1
--- /dev/null
@@ -0,0 +1,48 @@
+/* GStreamer
+ *
+ * Copyright (C) 2019 Collabora Ltd.
+ *   Author: Stéphane Cerveau <scerveau@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library (COPYING); if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSTMPDNODE_H__
+#define __GSTMPDNODE_H__
+
+#include <gst/gst.h>
+#include "gstxmlhelper.h"
+G_BEGIN_DECLS
+
+#define GST_TYPE_MPD_NODE gst_mpd_node_get_type ()
+G_DECLARE_DERIVABLE_TYPE (GstMPDNode, gst_mpd_node,GST, MPD_NODE, GstObject)
+
+typedef gboolean (*GstMPDGetXMLBuffer) (GstMPDNode * n, gchar ** doc_content, int *doc_size);
+typedef xmlNodePtr (*GstMPDGetXMLNode) (GstMPDNode * n);
+
+struct _GstMPDNodeClass {
+    GstObjectClass base;
+
+    GstMPDGetXMLBuffer get_xml_buffer;
+    GstMPDGetXMLNode get_xml_node;
+};
+
+gboolean gst_mpd_node_get_xml_buffer (GstMPDNode * node, gchar ** xml_content, int * xml_size);
+xmlNodePtr gst_mpd_node_get_xml_pointer (GstMPDNode * node);
+
+void gst_mpd_node_get_list_item (gpointer data, gpointer user_data);
+void gst_mpd_node_add_child_node (GstMPDNode* data, xmlNodePtr user_data);
+
+G_END_DECLS
+#endif /* __GSTMPDNODE_H__ */
index 9dcc3bb..8cd2858 100644 (file)
@@ -43,20 +43,20 @@ static void gst_mpdparser_parse_subrepresentation_node (GList ** list,
     xmlNode * a_node);
 static void gst_mpdparser_parse_segment_url_node (GList ** list,
     xmlNode * a_node);
-static void gst_mpdparser_parse_url_type_node (GstMPDURLType ** pointer,
+static void gst_mpdparser_parse_url_type_node (GstMPDURLTypeNode ** pointer,
     xmlNode * a_node);
-static void gst_mpdparser_parse_seg_base_type_ext (GstMPDSegmentBaseType **
-    pointer, xmlNode * a_node, GstMPDSegmentBaseType * parent);
+static void gst_mpdparser_parse_seg_base_type_ext (GstMPDSegmentBaseNode **
+    pointer, xmlNode * a_node, GstMPDSegmentBaseNode * parent);
 static void gst_mpdparser_parse_s_node (GQueue * queue, xmlNode * a_node);
 static void gst_mpdparser_parse_segment_timeline_node (GstMPDSegmentTimelineNode
     ** pointer, xmlNode * a_node);
 static gboolean
-gst_mpdparser_parse_mult_seg_base_type_ext (GstMPDMultSegmentBaseType **
-    pointer, xmlNode * a_node, GstMPDMultSegmentBaseType * parent);
+gst_mpdparser_parse_mult_seg_base_node (GstMPDMultSegmentBaseNode *
+    pointer, xmlNode * a_node, GstMPDMultSegmentBaseNode * parent);
 static gboolean gst_mpdparser_parse_segment_list_node (GstMPDSegmentListNode **
     pointer, xmlNode * a_node, GstMPDSegmentListNode * parent);
 static void
-gst_mpdparser_parse_representation_base_type (GstMPDRepresentationBaseType **
+gst_mpdparser_parse_representation_base (GstMPDRepresentationBaseNode *
     pointer, xmlNode * a_node);
 static gboolean gst_mpdparser_parse_representation_node (GList ** list,
     xmlNode * a_node, GstMPDAdaptationSetNode * parent,
@@ -79,41 +79,6 @@ static gboolean gst_mpdparser_parse_root_node (GstMPDRootNode ** pointer,
 static void gst_mpdparser_parse_utctiming_node (GList ** list,
     xmlNode * a_node);
 
-/* Memory management */
-
-struct GstMpdParserUtcTimingMethod
-{
-  const gchar *name;
-  GstMPDUTCTimingType method;
-};
-
-static const struct GstMpdParserUtcTimingMethod
-    gst_mpdparser_utc_timing_methods[] = {
-  {"urn:mpeg:dash:utc:ntp:2014", GST_MPD_UTCTIMING_TYPE_NTP},
-  {"urn:mpeg:dash:utc:sntp:2014", GST_MPD_UTCTIMING_TYPE_SNTP},
-  {"urn:mpeg:dash:utc:http-head:2014", GST_MPD_UTCTIMING_TYPE_HTTP_HEAD},
-  {"urn:mpeg:dash:utc:http-xsdate:2014", GST_MPD_UTCTIMING_TYPE_HTTP_XSDATE},
-  {"urn:mpeg:dash:utc:http-iso:2014", GST_MPD_UTCTIMING_TYPE_HTTP_ISO},
-  {"urn:mpeg:dash:utc:http-ntp:2014", GST_MPD_UTCTIMING_TYPE_HTTP_NTP},
-  {"urn:mpeg:dash:utc:direct:2014", GST_MPD_UTCTIMING_TYPE_DIRECT},
-  /*
-   * Early working drafts used the :2012 namespace and this namespace is
-   * used by some DASH packagers. To work-around these packagers, we also
-   * accept the early draft scheme names.
-   */
-  {"urn:mpeg:dash:utc:ntp:2012", GST_MPD_UTCTIMING_TYPE_NTP},
-  {"urn:mpeg:dash:utc:sntp:2012", GST_MPD_UTCTIMING_TYPE_SNTP},
-  {"urn:mpeg:dash:utc:http-head:2012", GST_MPD_UTCTIMING_TYPE_HTTP_HEAD},
-  {"urn:mpeg:dash:utc:http-xsdate:2012", GST_MPD_UTCTIMING_TYPE_HTTP_XSDATE},
-  {"urn:mpeg:dash:utc:http-iso:2012", GST_MPD_UTCTIMING_TYPE_HTTP_ISO},
-  {"urn:mpeg:dash:utc:http-ntp:2012", GST_MPD_UTCTIMING_TYPE_HTTP_NTP},
-  {"urn:mpeg:dash:utc:direct:2012", GST_MPD_UTCTIMING_TYPE_DIRECT},
-  {NULL, 0}
-};
-
-
-
-
 /*
   Duration Data Type
 
@@ -156,9 +121,10 @@ gst_mpdparser_parse_baseURL_node (GList ** list, xmlNode * a_node)
 static void
 gst_mpdparser_parse_descriptor_type (GList ** list, xmlNode * a_node)
 {
-  GstMPDDescriptorType *new_descriptor;
+  GstMPDDescriptorTypeNode *new_descriptor;
 
-  new_descriptor = g_slice_new0 (GstMPDDescriptorType);
+  new_descriptor =
+      gst_mpd_descriptor_type_node_new ((const gchar *) a_node->name);
   *list = g_list_append (*list, new_descriptor);
 
   GST_LOG ("attributes of %s node:", a_node->name);
@@ -211,10 +177,14 @@ static void
 gst_mpdparser_parse_location_node (GList ** list, xmlNode * a_node)
 {
   gchar *location = NULL;
+  GstMPDLocationNode *locationNode;
 
   GST_LOG ("content of Location node:");
-  if (gst_xml_helper_get_node_content (a_node, &location))
-    *list = g_list_append (*list, location);
+  if (gst_xml_helper_get_node_content (a_node, &location)) {
+    locationNode = gst_mpd_location_node_new ();
+    locationNode->location = location;
+    *list = g_list_append (*list, locationNode);
+  }
 }
 
 static void
@@ -229,15 +199,15 @@ gst_mpdparser_parse_subrepresentation_node (GList ** list, xmlNode * a_node)
   gst_xml_helper_get_prop_unsigned_integer (a_node, "level", 0,
       &new_subrep->level);
   gst_xml_helper_get_prop_uint_vector_type (a_node, "dependencyLevel",
-      &new_subrep->dependencyLevel, &new_subrep->size);
+      &new_subrep->dependencyLevel, &new_subrep->dependencyLevel_size);
   gst_xml_helper_get_prop_unsigned_integer (a_node, "bandwidth", 0,
       &new_subrep->bandwidth);
   gst_xml_helper_get_prop_string_vector_type (a_node,
       "contentComponent", &new_subrep->contentComponent);
 
   /* RepresentationBase extension */
-  gst_mpdparser_parse_representation_base_type (&new_subrep->RepresentationBase,
-      a_node);
+  gst_mpdparser_parse_representation_base (GST_MPD_REPRESENTATION_BASE_NODE
+      (new_subrep), a_node);
 }
 
 
@@ -260,12 +230,14 @@ gst_mpdparser_parse_segment_url_node (GList ** list, xmlNode * a_node)
 }
 
 static void
-gst_mpdparser_parse_url_type_node (GstMPDURLType ** pointer, xmlNode * a_node)
+gst_mpdparser_parse_url_type_node (GstMPDURLTypeNode ** pointer,
+    xmlNode * a_node)
 {
-  GstMPDURLType *new_url_type;
+  GstMPDURLTypeNode *new_url_type;
 
-  gst_mpd_helper_url_type_node_free (*pointer);
-  *pointer = new_url_type = g_slice_new0 (GstMPDURLType);
+  gst_mpd_url_type_node_free (*pointer);
+  *pointer = new_url_type =
+      gst_mpd_url_type_node_new ((const gchar *) a_node->name);
 
   GST_LOG ("attributes of URLType node:");
   gst_xml_helper_get_prop_string (a_node, "sourceURL",
@@ -274,18 +246,18 @@ gst_mpdparser_parse_url_type_node (GstMPDURLType ** pointer, xmlNode * a_node)
 }
 
 static void
-gst_mpdparser_parse_seg_base_type_ext (GstMPDSegmentBaseType ** pointer,
-    xmlNode * a_node, GstMPDSegmentBaseType * parent)
+gst_mpdparser_parse_seg_base_type_ext (GstMPDSegmentBaseNode ** pointer,
+    xmlNode * a_node, GstMPDSegmentBaseNode * parent)
 {
   xmlNode *cur_node;
-  GstMPDSegmentBaseType *seg_base_type;
+  GstMPDSegmentBaseNode *seg_base_type;
   guint intval;
   guint64 int64val;
   gboolean boolval;
   GstXMLRange *rangeval;
 
-  gst_mpd_helper_segment_base_type_free (*pointer);
-  *pointer = seg_base_type = g_slice_new0 (GstMPDSegmentBaseType);
+  gst_mpd_segment_base_node_free (*pointer);
+  *pointer = seg_base_type = gst_mpd_segment_base_node_new ();
 
   /* Initialize values that have defaults */
   seg_base_type->indexRangeExact = FALSE;
@@ -298,9 +270,9 @@ gst_mpdparser_parse_seg_base_type_ext (GstMPDSegmentBaseType ** pointer,
     seg_base_type->indexRange = gst_xml_helper_clone_range (parent->indexRange);
     seg_base_type->indexRangeExact = parent->indexRangeExact;
     seg_base_type->Initialization =
-        gst_mpd_helper_URLType_clone (parent->Initialization);
+        gst_mpd_url_type_node_clone (parent->Initialization);
     seg_base_type->RepresentationIndex =
-        gst_mpd_helper_URLType_clone (parent->RepresentationIndex);
+        gst_mpd_url_type_node_clone (parent->RepresentationIndex);
   }
 
   /* We must retrieve each value first to see if it exists.  If it does not
@@ -386,47 +358,43 @@ gst_mpdparser_parse_segment_timeline_node (GstMPDSegmentTimelineNode ** pointer,
 }
 
 static gboolean
-gst_mpdparser_parse_mult_seg_base_type_ext (GstMPDMultSegmentBaseType **
-    pointer, xmlNode * a_node, GstMPDMultSegmentBaseType * parent)
+gst_mpdparser_parse_mult_seg_base_node (GstMPDMultSegmentBaseNode *
+    mult_seg_base_node, xmlNode * a_node, GstMPDMultSegmentBaseNode * parent)
 {
   xmlNode *cur_node;
-  GstMPDMultSegmentBaseType *mult_seg_base_type;
+
   guint intval;
   gboolean has_timeline = FALSE, has_duration = FALSE;
 
-  gst_mpd_helper_mult_seg_base_type_free (*pointer);
-  mult_seg_base_type = g_slice_new0 (GstMPDMultSegmentBaseType);
-
-  mult_seg_base_type->duration = 0;
-  mult_seg_base_type->startNumber = 1;
+  mult_seg_base_node->duration = 0;
+  mult_seg_base_node->startNumber = 1;
 
   /* Inherit attribute values from parent */
   if (parent) {
-    mult_seg_base_type->duration = parent->duration;
-    mult_seg_base_type->startNumber = parent->startNumber;
-    mult_seg_base_type->SegmentTimeline =
+    mult_seg_base_node->duration = parent->duration;
+    mult_seg_base_node->startNumber = parent->startNumber;
+    mult_seg_base_node->SegmentTimeline =
         gst_mpd_segment_timeline_node_clone (parent->SegmentTimeline);
-    mult_seg_base_type->BitstreamSwitching =
-        gst_mpd_helper_URLType_clone (parent->BitstreamSwitching);
+    mult_seg_base_node->BitstreamSwitching =
+        gst_mpd_url_type_node_clone (parent->BitstreamSwitching);
   }
-
   GST_LOG ("attributes of MultipleSegmentBaseType extension:");
   if (gst_xml_helper_get_prop_unsigned_integer (a_node, "duration", 0, &intval)) {
-    mult_seg_base_type->duration = intval;
+    mult_seg_base_node->duration = intval;
   }
 
   /* duration might be specified from parent */
-  if (mult_seg_base_type->duration)
+  if (mult_seg_base_node->duration)
     has_duration = TRUE;
 
   if (gst_xml_helper_get_prop_unsigned_integer (a_node, "startNumber", 1,
           &intval)) {
-    mult_seg_base_type->startNumber = intval;
+    mult_seg_base_node->startNumber = intval;
   }
 
   GST_LOG ("extension of MultipleSegmentBaseType extension:");
-  gst_mpdparser_parse_seg_base_type_ext (&mult_seg_base_type->SegBaseType,
-      a_node, (parent ? parent->SegBaseType : NULL));
+  gst_mpdparser_parse_seg_base_type_ext (&mult_seg_base_node->SegmentBase,
+      a_node, (parent ? parent->SegmentBase : NULL));
 
   /* explore children nodes */
   for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {
@@ -434,31 +402,25 @@ gst_mpdparser_parse_mult_seg_base_type_ext (GstMPDMultSegmentBaseType **
       if (xmlStrcmp (cur_node->name, (xmlChar *) "SegmentTimeline") == 0) {
         /* parse frees the segmenttimeline if any */
         gst_mpdparser_parse_segment_timeline_node
-            (&mult_seg_base_type->SegmentTimeline, cur_node);
+            (&mult_seg_base_node->SegmentTimeline, cur_node);
       } else if (xmlStrcmp (cur_node->name,
               (xmlChar *) "BitstreamSwitching") == 0) {
         /* parse frees the old url before setting the new one */
         gst_mpdparser_parse_url_type_node
-            (&mult_seg_base_type->BitstreamSwitching, cur_node);
+            (&mult_seg_base_node->BitstreamSwitching, cur_node);
       }
     }
   }
 
-  has_timeline = mult_seg_base_type->SegmentTimeline != NULL;
+  has_timeline = mult_seg_base_node->SegmentTimeline != NULL;
 
   /* Checking duration and timeline only at Representation's child level */
   if (xmlStrcmp (a_node->parent->name, (xmlChar *) "Representation") == 0
       && !has_duration && !has_timeline) {
     GST_ERROR ("segment has neither duration nor timeline");
-    goto error;
   }
 
-  *pointer = mult_seg_base_type;
   return TRUE;
-
-error:
-  gst_mpd_helper_mult_seg_base_type_free (mult_seg_base_type);
-  return FALSE;
 }
 
 static gboolean
@@ -492,15 +454,15 @@ gst_mpdparser_parse_segment_list_node (GstMPDSegmentListNode ** pointer,
           "http://www.w3.org/1999/xlink", "href", &new_segment_list->xlink_href)
       && gst_xml_helper_get_ns_prop_string (a_node,
           "http://www.w3.org/1999/xlink", "actuate", &actuate)) {
-    if (strcmp (actuate, "onLoad") == 0)
+    if (strcmp (actuate, GST_MPD_XLINK_ACTUATE_ON_LOAD_STR) == 0)
       new_segment_list->actuate = GST_MPD_XLINK_ACTUATE_ON_LOAD;
     xmlFree (actuate);
   }
 
   GST_LOG ("extension of SegmentList node:");
-  if (!gst_mpdparser_parse_mult_seg_base_type_ext
-      (&new_segment_list->MultSegBaseType, a_node,
-          (parent ? parent->MultSegBaseType : NULL)))
+  if (!gst_mpdparser_parse_mult_seg_base_node
+      (GST_MPD_MULT_SEGMENT_BASE_NODE (new_segment_list), a_node,
+          (parent ? GST_MPD_MULT_SEGMENT_BASE_NODE (parent) : NULL)))
     goto error;
 
   /* explore children nodes */
@@ -548,8 +510,9 @@ gst_mpdparser_parse_content_protection_node (GList ** list, xmlNode * a_node)
       for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {
         if (cur_node->type == XML_ELEMENT_NODE) {
           if (xmlStrcmp (cur_node->name, (xmlChar *) "pro") == 0) {
-            GstMPDDescriptorType *new_descriptor;
-            new_descriptor = g_slice_new0 (GstMPDDescriptorType);
+            GstMPDDescriptorTypeNode *new_descriptor;
+            new_descriptor = gst_mpd_descriptor_type_node_new ((const gchar *)
+                cur_node->name);
             *list = g_list_append (*list, new_descriptor);
 
             gst_xml_helper_get_prop_string_stripped (a_node, "schemeIdUri",
@@ -572,14 +535,10 @@ beach:
 }
 
 static void
-gst_mpdparser_parse_representation_base_type (GstMPDRepresentationBaseType **
-    pointer, xmlNode * a_node)
+gst_mpdparser_parse_representation_base (GstMPDRepresentationBaseNode *
+    representation_base, xmlNode * a_node)
 {
   xmlNode *cur_node;
-  GstMPDRepresentationBaseType *representation_base;
-
-  gst_mpd_helper_representation_base_type_free (*pointer);
-  *pointer = representation_base = g_slice_new0 (GstMPDRepresentationBaseType);
 
   GST_LOG ("attributes of RepresentationBaseType extension:");
   gst_xml_helper_get_prop_string (a_node, "profiles",
@@ -659,10 +618,9 @@ gst_mpdparser_parse_representation_node (GList ** list, xmlNode * a_node,
       &new_representation->dependencyId);
   gst_xml_helper_get_prop_string_vector_type (a_node,
       "mediaStreamStructureId", &new_representation->mediaStreamStructureId);
-
   /* RepresentationBase extension */
-  gst_mpdparser_parse_representation_base_type
-      (&new_representation->RepresentationBase, a_node);
+  gst_mpdparser_parse_representation_base
+      (GST_MPD_REPRESENTATION_BASE_NODE (new_representation), a_node);
 
   /* explore children nodes */
   for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {
@@ -764,8 +722,8 @@ gst_mpdparser_parse_adaptation_set_node (GList ** list, xmlNode * a_node,
       &new_adap_set->subsegmentStartsWithSAP);
 
   /* RepresentationBase extension */
-  gst_mpdparser_parse_representation_base_type
-      (&new_adap_set->RepresentationBase, a_node);
+  gst_mpdparser_parse_representation_base
+      (GST_MPD_REPRESENTATION_BASE_NODE (new_adap_set), a_node);
 
   /* explore children nodes */
   for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {
@@ -833,7 +791,7 @@ gst_mpdparser_parse_subset_node (GList ** list, xmlNode * a_node)
 
   GST_LOG ("attributes of Subset node:");
   gst_xml_helper_get_prop_uint_vector_type (a_node, "contains",
-      &new_subset->contains, &new_subset->size);
+      &new_subset->contains, &new_subset->contains_size);
 }
 
 static gboolean
@@ -847,9 +805,9 @@ gst_mpdparser_parse_segment_template_node (GstMPDSegmentTemplateNode ** pointer,
   new_segment_template = gst_mpd_segment_template_node_new ();
 
   GST_LOG ("extension of SegmentTemplate node:");
-  if (!gst_mpdparser_parse_mult_seg_base_type_ext
-      (&new_segment_template->MultSegBaseType, a_node,
-          (parent ? parent->MultSegBaseType : NULL)))
+  if (!gst_mpdparser_parse_mult_seg_base_node
+      (GST_MPD_MULT_SEGMENT_BASE_NODE (new_segment_template), a_node,
+          (parent ? GST_MPD_MULT_SEGMENT_BASE_NODE (parent) : NULL)))
     goto error;
 
   /* Inherit attribute values from parent when the value isn't found */
@@ -1048,15 +1006,7 @@ gst_mpdparser_parse_utctiming_node (GList ** list, xmlNode * a_node)
 
   GST_LOG ("attributes of UTCTiming node:");
   if (gst_xml_helper_get_prop_string (a_node, "schemeIdUri", &method)) {
-    int i;
-
-    for (i = 0; gst_mpdparser_utc_timing_methods[i].name; ++i) {
-      if (g_ascii_strncasecmp (gst_mpdparser_utc_timing_methods[i].name,
-              method, strlen (gst_mpdparser_utc_timing_methods[i].name)) == 0) {
-        new_timing->method = gst_mpdparser_utc_timing_methods[i].method;
-        break;
-      }
-    }
+    new_timing->method = gst_mpd_utctiming_get_method (method);
     xmlFree (method);
   }
 
@@ -1439,7 +1389,7 @@ gst_mpdparser_free_active_stream (GstActiveStream * active_stream)
 
 const gchar *
 gst_mpdparser_get_initializationURL (GstActiveStream * stream,
-    GstMPDURLType * InitializationURL)
+    GstMPDURLTypeNode * InitializationURL)
 {
   const gchar *url_prefix;
 
@@ -1473,10 +1423,10 @@ gst_mpdparser_representation_get_mimetype (GstMPDAdaptationSetNode * adapt_set,
     GstMPDRepresentationNode * rep)
 {
   gchar *mime = NULL;
-  if (rep->RepresentationBase)
-    mime = rep->RepresentationBase->mimeType;
-  if (mime == NULL && adapt_set->RepresentationBase) {
-    mime = adapt_set->RepresentationBase->mimeType;
+  if (rep)
+    mime = GST_MPD_REPRESENTATION_BASE_NODE (rep)->mimeType;
+  if (mime == NULL) {
+    mime = GST_MPD_REPRESENTATION_BASE_NODE (adapt_set)->mimeType;
   }
 
   if (gst_mpd_helper_strncmp_ext (mime, "audio") == 0)
index 653003f..f51b962 100644 (file)
@@ -42,6 +42,7 @@
 #include "gstmpdsegmenttemplatenode.h"
 #include "gstmpdsegmenturlnode.h"
 #include "gstmpdsegmentlistnode.h"
+#include "gstmpdsegmentbasenode.h"
 #include "gstmpdperiodnode.h"
 #include "gstmpdrepresentationnode.h"
 #include "gstmpdsubrepresentationnode.h"
 #include "gstmpdadaptationsetnode.h"
 #include "gstmpdsubsetnode.h"
 #include "gstmpdprograminformationnode.h"
+#include "gstmpdlocationnode.h"
+#include "gstmpdreportingnode.h"
+#include "gstmpdurltypenode.h"
+#include "gstmpddescriptortypenode.h"
+#include "gstmpdrepresentationbasenode.h"
+#include "gstmpdmultsegmentbasenode.h"
 
 G_BEGIN_DECLS
 
@@ -129,7 +136,7 @@ struct _GstActiveStream
   GstMPDAdaptationSetNode *cur_adapt_set;        /* active adaptation set */
   gint representation_idx;                    /* index of current representation */
   GstMPDRepresentationNode *cur_representation;  /* active representation */
-  GstMPDSegmentBaseType *cur_segment_base;       /* active segment base */
+  GstMPDSegmentBaseNode *cur_segment_base;       /* active segment base */
   GstMPDSegmentListNode *cur_segment_list;       /* active segment list */
   GstMPDSegmentTemplateNode *cur_seg_template;   /* active segment template */
   gint segment_index;                         /* index of next sequence chunk */
@@ -155,7 +162,7 @@ void gst_mpdparser_media_fragment_info_clear (GstMediaFragmentInfo * fragment);
 /* Active stream methods*/
 void gst_mpdparser_init_active_stream_segments (GstActiveStream * stream);
 gchar *gst_mpdparser_get_mediaURL (GstActiveStream * stream, GstMPDSegmentURLNode * segmentURL);
-const gchar *gst_mpdparser_get_initializationURL (GstActiveStream * stream, GstMPDURLType * InitializationURL);
+const gchar *gst_mpdparser_get_initializationURL (GstActiveStream * stream, GstMPDURLTypeNode * InitializationURL);
 gchar *gst_mpdparser_build_URL_from_template (const gchar * url_template, const gchar * id, guint number, guint bandwidth, guint64 time);
 
 G_END_DECLS
index 8dea50c..0b67fc7 100644 (file)
@@ -21,8 +21,7 @@
 #include "gstmpdperiodnode.h"
 #include "gstmpdparser.h"
 
-G_DEFINE_TYPE (GstMPDPeriodNode, gst_mpd_period_node, GST_TYPE_OBJECT);
-
+G_DEFINE_TYPE (GstMPDPeriodNode, gst_mpd_period_node, GST_TYPE_MPD_NODE);
 /* GObject VMethods */
 
 static void
@@ -32,7 +31,7 @@ gst_mpd_period_node_finalize (GObject * object)
 
   if (self->id)
     xmlFree (self->id);
-  gst_mpd_helper_segment_base_type_free (self->SegmentBase);
+  gst_mpd_segment_base_node_free (self->SegmentBase);
   gst_mpd_segment_list_node_free (self->SegmentList);
   gst_mpd_segment_template_node_free (self->SegmentTemplate);
   g_list_free_full (self->AdaptationSets,
@@ -45,11 +44,58 @@ gst_mpd_period_node_finalize (GObject * object)
   G_OBJECT_CLASS (gst_mpd_period_node_parent_class)->finalize (object);
 }
 
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_period_get_xml_node (GstMPDNode * node)
+{
+  xmlNodePtr period_xml_node = NULL;
+  GstMPDPeriodNode *self = GST_MPD_PERIOD_NODE (node);
+
+  period_xml_node = xmlNewNode (NULL, (xmlChar *) "Period");
+
+  if (self->id)
+    gst_xml_helper_set_prop_string (period_xml_node, "id", self->id);
+
+  gst_xml_helper_set_prop_duration (period_xml_node, "start", self->start);
+  gst_xml_helper_set_prop_duration (period_xml_node, "duration",
+      self->duration);
+  gst_xml_helper_set_prop_boolean (period_xml_node, "bitstreamSwitching",
+      self->bitstreamSwitching);
+
+  if (self->SegmentBase)
+    gst_mpd_node_add_child_node (GST_MPD_NODE (self->SegmentBase),
+        period_xml_node);
+
+  if (self->SegmentList)
+    gst_mpd_mult_segment_base_node_add_child_node (GST_MPD_NODE
+        (self->SegmentList), period_xml_node);
+
+  if (self->SegmentTemplate)
+    gst_mpd_mult_segment_base_node_add_child_node (GST_MPD_NODE
+        (self->SegmentTemplate), period_xml_node);
+
+  g_list_foreach (self->AdaptationSets,
+      gst_mpd_representation_base_node_get_list_item, period_xml_node);
+  g_list_foreach (self->Subsets, gst_mpd_node_get_list_item, period_xml_node);
+  g_list_foreach (self->BaseURLs, gst_mpd_node_get_list_item, period_xml_node);
+
+
+  return period_xml_node;
+}
+
 static void
 gst_mpd_period_node_class_init (GstMPDPeriodNodeClass * klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GObjectClass *object_class;
+  GstMPDNodeClass *m_klass;
+
+  object_class = G_OBJECT_CLASS (klass);
+  m_klass = GST_MPD_NODE_CLASS (klass);
+
   object_class->finalize = gst_mpd_period_node_finalize;
+
+  m_klass->get_xml_node = gst_mpd_period_get_xml_node;
 }
 
 static void
index 7e327a9..2c6540f 100644 (file)
@@ -31,19 +31,7 @@ G_BEGIN_DECLS
 struct _GstSegmentTemplateNode;
 
 #define GST_TYPE_MPD_PERIOD_NODE gst_mpd_period_node_get_type ()
-#define GST_MPD_PERIOD_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MPD_PERIOD_NODE, GstMPDPeriodNode))
-#define GST_MPD_PERIOD_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MPD_PERIOD_NODE, GstMPDPeriodNodeClass))
-#define GST_IS_MPD_PERIOD_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MPD_PERIOD_NODE))
-#define GST_IS_MPD_PERIOD_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MPD_PERIOD_NODE))
-#define GST_MPD_PERIOD_NODE_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MPD_PERIOD_NODE, GstMPDPeriodNodeClass))
-
-typedef struct _GstMPDPeriodNode                GstMPDPeriodNode;
-typedef struct _GstMPDPeriodNodeClass           GstMPDPeriodNodeClass;
+G_DECLARE_FINAL_TYPE (GstMPDPeriodNode, gst_mpd_period_node, GST, MPD_PERIOD_NODE, GstMPDNode)
 
 struct _GstMPDPeriodNode
 {
@@ -53,7 +41,7 @@ struct _GstMPDPeriodNode
   guint64 duration;                  /* [ms] */
   gboolean bitstreamSwitching;
   /* SegmentBase node */
-  GstMPDSegmentBaseType *SegmentBase;
+  GstMPDSegmentBaseNode *SegmentBase;
   /* SegmentList node */
   GstMPDSegmentListNode *SegmentList;
   /* SegmentTemplate node */
@@ -69,13 +57,6 @@ struct _GstMPDPeriodNode
   int actuate;
 };
 
-struct _GstMPDPeriodNodeClass {
-  GstObjectClass parent_class;
-};
-
-
-G_GNUC_INTERNAL GType gst_mpd_period_node_get_type (void);
-
 GstMPDPeriodNode * gst_mpd_period_node_new (void);
 void gst_mpd_period_node_free (GstMPDPeriodNode* self);
 
index 14daa5d..69550fa 100644 (file)
@@ -22,7 +22,7 @@
 #include "gstmpdparser.h"
 
 G_DEFINE_TYPE (GstMPDProgramInformationNode, gst_mpd_program_information_node,
-    GST_TYPE_OBJECT);
+    GST_TYPE_MPD_NODE);
 
 /* GObject VMethods */
 
@@ -47,12 +47,58 @@ gst_mpd_program_information_node_finalize (GObject * object)
       (object);
 }
 
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_program_information_get_xml_node (GstMPDNode * node)
+{
+  xmlNodePtr program_info_xml_node = NULL;
+  xmlNodePtr child_node = NULL;
+  GstMPDProgramInformationNode *self = GST_MPD_PROGRAM_INFORMATION_NODE (node);
+
+  program_info_xml_node = xmlNewNode (NULL, (xmlChar *) "ProgramInformation");
+
+  if (self->lang)
+    gst_xml_helper_set_prop_string (program_info_xml_node, "lang", self->lang);
+
+  if (self->moreInformationURL)
+    gst_xml_helper_set_prop_string (program_info_xml_node, "moreInformationURL",
+        self->moreInformationURL);
+
+  if (self->Title) {
+    child_node = xmlNewNode (NULL, (xmlChar *) "Title");
+    gst_xml_helper_set_content (child_node, self->Title);
+    xmlAddChild (program_info_xml_node, child_node);
+  }
+
+  if (self->Source) {
+    child_node = xmlNewNode (NULL, (xmlChar *) "Source");
+    gst_xml_helper_set_content (child_node, self->Source);
+    xmlAddChild (program_info_xml_node, child_node);
+  }
+
+  if (self->Copyright) {
+    child_node = xmlNewNode (NULL, (xmlChar *) "Copyright");
+    gst_xml_helper_set_content (child_node, self->Copyright);
+    xmlAddChild (program_info_xml_node, child_node);
+  }
+
+  return program_info_xml_node;
+}
+
 static void
 gst_mpd_program_information_node_class_init (GstMPDProgramInformationNodeClass *
     klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GObjectClass *object_class;
+  GstMPDNodeClass *m_klass;
+
+  object_class = G_OBJECT_CLASS (klass);
+  m_klass = GST_MPD_NODE_CLASS (klass);
+
   object_class->finalize = gst_mpd_program_information_node_finalize;
+
+  m_klass->get_xml_node = gst_mpd_program_information_get_xml_node;
 }
 
 static void
index 9d3a5a8..f1c55a8 100644 (file)
 G_BEGIN_DECLS
 
 #define GST_TYPE_MPD_PROGRAM_INFORMATION_NODE gst_mpd_program_information_node_get_type ()
-#define GST_MPD_PROGRAM_INFORMATION_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MPD_PROGRAM_INFORMATION_NODE, GstMPDProgramInformationNode))
-#define GST_MPD_PROGRAM_INFORMATION_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MPD_PROGRAM_INFORMATION_NODE, GstMPDProgramInformationNodeClass))
-#define GST_IS_MPD_PROGRAM_INFORMATION_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MPD_PROGRAM_INFORMATION_NODE))
-#define GST_IS_MPD_PROGRAM_INFORMATION_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MPD_PROGRAM_INFORMATION_NODE))
-#define GST_MPD_PROGRAM_INFORMATION_NODE_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MPD_PROGRAM_INFORMATION_NODE, GstMPDProgramInformationNodeClass))
-
-typedef struct _GstMPDProgramInformationNode                GstMPDProgramInformationNode;
-typedef struct _GstMPDProgramInformationNodeClass           GstMPDProgramInformationNodeClass;
-
+G_DECLARE_FINAL_TYPE (GstMPDProgramInformationNode, gst_mpd_program_information_node, GST, MPD_PROGRAM_INFORMATION_NODE, GstMPDNode)
 
 struct _GstMPDProgramInformationNode
 {
@@ -53,13 +40,6 @@ struct _GstMPDProgramInformationNode
   gchar *Copyright;
 };
 
-struct _GstMPDProgramInformationNodeClass {
-  GstObjectClass parent_class;
-};
-
-
-G_GNUC_INTERNAL GType gst_mpd_program_information_node_get_type (void);
-
 GstMPDProgramInformationNode * gst_mpd_program_information_node_new (void);
 void gst_mpd_program_information_node_free (GstMPDProgramInformationNode* self);
 
diff --git a/ext/dash/gstmpdreportingnode.c b/ext/dash/gstmpdreportingnode.c
new file mode 100644 (file)
index 0000000..fa81eb5
--- /dev/null
@@ -0,0 +1,64 @@
+/* GStreamer
+ *
+ * Copyright (C) 2019 Collabora Ltd.
+ *   Author: Stéphane Cerveau <scerveau@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+#include "gstmpdreportingnode.h"
+#include "gstmpdparser.h"
+
+G_DEFINE_TYPE (GstMPDReportingNode, gst_mpd_reporting_node, GST_TYPE_MPD_NODE);
+
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_reporting_get_xml_node (GstMPDNode * node)
+{
+  xmlNodePtr reporting_xml_node = NULL;
+
+  reporting_xml_node = xmlNewNode (NULL, (xmlChar *) "Reporting");
+
+  return reporting_xml_node;
+}
+
+static void
+gst_mpd_reporting_node_class_init (GstMPDReportingNodeClass * klass)
+{
+  GstMPDNodeClass *m_klass;
+
+  m_klass = GST_MPD_NODE_CLASS (klass);
+
+  m_klass->get_xml_node = gst_mpd_reporting_get_xml_node;
+}
+
+static void
+gst_mpd_reporting_node_init (GstMPDReportingNode * self)
+{
+}
+
+GstMPDReportingNode *
+gst_mpd_reporting_node_new (void)
+{
+  return g_object_new (GST_TYPE_MPD_REPORTING_NODE, NULL);
+}
+
+void
+gst_mpd_reporting_node_free (GstMPDReportingNode * self)
+{
+  if (self)
+    gst_object_unref (self);
+}
diff --git a/ext/dash/gstmpdreportingnode.h b/ext/dash/gstmpdreportingnode.h
new file mode 100644 (file)
index 0000000..83b0b77
--- /dev/null
@@ -0,0 +1,42 @@
+/* GStreamer
+ *
+ * Copyright (C) 2019 Collabora Ltd.
+ *   Author: Stéphane Cerveau <scerveau@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library (COPYING); if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSTMPDREPORTINGNODE_H__
+#define __GSTMPDREPORTINGNODE_H__
+
+#include <gst/gst.h>
+#include "gstmpdhelper.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_MPD_REPORTING_NODE gst_mpd_reporting_node_get_type ()
+G_DECLARE_FINAL_TYPE (GstMPDReportingNode, gst_mpd_reporting_node, GST, MPD_REPORTING_NODE, GstMPDNode)
+
+struct _GstMPDReportingNode
+{
+  GstObject     parent_instance;
+};
+
+GstMPDReportingNode * gst_mpd_reporting_node_new (void);
+void gst_mpd_reporting_node_free (GstMPDReportingNode* self);
+
+G_END_DECLS
+
+#endif /* __GSTMPDREPORTINGNODE_H__ */
diff --git a/ext/dash/gstmpdrepresentationbasenode.c b/ext/dash/gstmpdrepresentationbasenode.c
new file mode 100644 (file)
index 0000000..29e43d3
--- /dev/null
@@ -0,0 +1,165 @@
+/* GStreamer
+ *
+ * Copyright (C) 2019 Collabora Ltd.
+ *   Author: Stéphane Cerveau <scerveau@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+#include "gstmpdrepresentationbasenode.h"
+#include "gstmpdparser.h"
+
+G_DEFINE_TYPE (GstMPDRepresentationBaseNode, gst_mpd_representation_base_node,
+    GST_TYPE_MPD_NODE);
+
+/* GObject VMethods */
+
+static void
+gst_mpd_representation_base_node_finalize (GObject * object)
+{
+  GstMPDRepresentationBaseNode *self =
+      GST_MPD_REPRESENTATION_BASE_NODE (object);
+
+  if (self->profiles)
+    xmlFree (self->profiles);
+  g_slice_free (GstXMLRatio, self->sar);
+  g_slice_free (GstXMLFrameRate, self->frameRate);
+  g_slice_free (GstXMLFrameRate, self->minFrameRate);
+  g_slice_free (GstXMLFrameRate, self->maxFrameRate);
+  if (self->audioSamplingRate)
+    xmlFree (self->audioSamplingRate);
+  if (self->mimeType)
+    xmlFree (self->mimeType);
+  if (self->segmentProfiles)
+    xmlFree (self->segmentProfiles);
+  if (self->codecs)
+    xmlFree (self->codecs);
+  if (self->scanType)
+    xmlFree (self->scanType);
+  g_list_free_full (self->FramePacking,
+      (GDestroyNotify) gst_mpd_descriptor_type_node_free);
+  g_list_free_full (self->AudioChannelConfiguration,
+      (GDestroyNotify) gst_mpd_descriptor_type_node_free);
+  g_list_free_full (self->ContentProtection,
+      (GDestroyNotify) gst_mpd_descriptor_type_node_free);
+
+  G_OBJECT_CLASS (gst_mpd_representation_base_node_parent_class)->finalize
+      (object);
+}
+
+/* Base class */
+
+static void
+gst_mpd_representation_base_get_xml_node (GstMPDNode * node,
+    xmlNodePtr representation_base_node)
+{
+  GstMPDRepresentationBaseNode *self = GST_MPD_REPRESENTATION_BASE_NODE (node);
+
+  if (self->profiles)
+    gst_xml_helper_set_prop_string (representation_base_node, "profiles",
+        self->profiles);
+  if (self->width)
+    gst_xml_helper_set_prop_uint (representation_base_node, "width",
+        self->width);
+  if (self->height)
+    gst_xml_helper_set_prop_uint (representation_base_node, "height",
+        self->height);
+
+  gst_xml_helper_set_prop_ratio (representation_base_node, "sar", self->sar);
+  gst_xml_helper_set_prop_framerate (representation_base_node, "minFrameRate",
+      self->minFrameRate);
+  gst_xml_helper_set_prop_framerate (representation_base_node, "maxFrameRate",
+      self->maxFrameRate);
+  gst_xml_helper_set_prop_framerate (representation_base_node, "frameRate",
+      self->frameRate);
+
+  gst_xml_helper_set_prop_string (representation_base_node,
+      "audioSamplingRate", self->audioSamplingRate);
+  gst_xml_helper_set_prop_string (representation_base_node, "mimeType",
+      self->mimeType);
+  gst_xml_helper_set_prop_string (representation_base_node, "segmentProfiles",
+      self->segmentProfiles);
+  gst_xml_helper_set_prop_string (representation_base_node, "codecs",
+      self->codecs);
+  if (self->maximumSAPPeriod)
+    gst_xml_helper_set_prop_double (representation_base_node,
+        "maximumSAPPeriod", self->maximumSAPPeriod);
+  if (self->startWithSAP)
+    gst_xml_helper_set_prop_int (representation_base_node, "startWithSAP",
+        self->startWithSAP);
+  if (self->maxPlayoutRate)
+    gst_xml_helper_set_prop_double (representation_base_node, "maxPlayoutRate",
+        self->maxPlayoutRate);
+  if (self->codingDependency)
+    gst_xml_helper_set_prop_boolean (representation_base_node,
+        "codingDependency", self->codingDependency);
+
+  gst_xml_helper_set_prop_string (representation_base_node, "scanType",
+      self->scanType);
+
+  g_list_foreach (self->FramePacking,
+      gst_mpd_node_get_list_item, representation_base_node);
+  g_list_foreach (self->AudioChannelConfiguration,
+      gst_mpd_node_get_list_item, representation_base_node);
+  g_list_foreach (self->ContentProtection,
+      gst_mpd_node_get_list_item, representation_base_node);
+}
+
+static void
+gst_mpd_representation_base_node_class_init (GstMPDRepresentationBaseNodeClass *
+    klass)
+{
+  GObjectClass *object_class;
+
+  object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gst_mpd_representation_base_node_finalize;
+}
+
+static void
+gst_mpd_representation_base_node_init (GstMPDRepresentationBaseNode * self)
+{
+  self->profiles = NULL;
+  self->width = 0;
+  self->height = 0;
+  self->sar = NULL;
+  self->minFrameRate = NULL;
+  self->maxFrameRate = NULL;
+  self->frameRate = NULL;
+  self->audioSamplingRate = NULL;
+  self->mimeType = NULL;
+  self->segmentProfiles = NULL;
+  self->codecs = NULL;
+  self->maximumSAPPeriod = 0;
+  self->startWithSAP = GST_SAP_TYPE_0;
+  self->maxPlayoutRate = 0.0;
+  self->codingDependency = FALSE;
+  self->scanType = NULL;
+  self->FramePacking = NULL;
+  self->AudioChannelConfiguration = NULL;
+  self->ContentProtection = NULL;
+}
+
+void
+gst_mpd_representation_base_node_get_list_item (gpointer data,
+    gpointer user_data)
+{
+  GstMPDNode *node = (GstMPDNode *) data;
+  xmlNodePtr parent_xml_node = (xmlNodePtr) user_data;
+  xmlNodePtr new_xml_node = gst_mpd_node_get_xml_pointer (node);
+
+  gst_mpd_representation_base_get_xml_node (node, new_xml_node);
+  xmlAddChild (parent_xml_node, new_xml_node);
+}
diff --git a/ext/dash/gstmpdrepresentationbasenode.h b/ext/dash/gstmpdrepresentationbasenode.h
new file mode 100644 (file)
index 0000000..767dd9e
--- /dev/null
@@ -0,0 +1,63 @@
+/* GStreamer
+ *
+ * Copyright (C) 2019 Collabora Ltd.
+ *   Author: Stéphane Cerveau <scerveau@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library (COPYING); if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSTMPDREPRESENTATIONBASENODE_H__
+#define __GSTMPDREPRESENTATIONBASENODE_H__
+
+#include <gst/gst.h>
+#include "gstmpdhelper.h"
+G_BEGIN_DECLS
+
+#define GST_TYPE_MPD_REPRESENTATION_BASE_NODE gst_mpd_representation_base_node_get_type ()
+G_DECLARE_FINAL_TYPE (GstMPDRepresentationBaseNode, gst_mpd_representation_base_node, GST, MPD_REPRESENTATION_BASE_NODE, GstMPDNode)
+
+
+struct _GstMPDRepresentationBaseNode
+{
+  GstObject     base;
+  gchar *profiles;
+  guint width;
+  guint height;
+  GstXMLRatio *sar;
+  GstXMLFrameRate *minFrameRate;
+  GstXMLFrameRate *maxFrameRate;
+  GstXMLFrameRate *frameRate;
+  gchar *audioSamplingRate;
+  gchar *mimeType;
+  gchar *segmentProfiles;
+  gchar *codecs;
+  gdouble maximumSAPPeriod;
+  GstMPDSAPType startWithSAP;
+  gdouble maxPlayoutRate;
+  gboolean codingDependency;
+  gchar *scanType;
+  /* list of FramePacking DescriptorType nodes */
+  GList *FramePacking;
+  /* list of AudioChannelConfiguration DescriptorType nodes */
+  GList *AudioChannelConfiguration;
+  /* list of ContentProtection DescriptorType nodes */
+  GList *ContentProtection;
+};
+
+
+void gst_mpd_representation_base_node_get_list_item (gpointer data, gpointer user_data);
+
+G_END_DECLS
+#endif /* __GSTMPDREPRESENTATIONBASENODE_H__ */
index 3179a4a..6b583f0 100644 (file)
@@ -22,7 +22,7 @@
 #include "gstmpdparser.h"
 
 G_DEFINE_TYPE (GstMPDRepresentationNode, gst_mpd_representation_node,
-    GST_TYPE_OBJECT);
+    GST_TYPE_MPD_REPRESENTATION_BASE_NODE);
 
 /* GObject VMethods */
 
@@ -35,10 +35,9 @@ gst_mpd_representation_node_finalize (GObject * object)
     xmlFree (self->id);
   g_strfreev (self->dependencyId);
   g_strfreev (self->mediaStreamStructureId);
-  gst_mpd_helper_representation_base_type_free (self->RepresentationBase);
   g_list_free_full (self->SubRepresentations,
       (GDestroyNotify) gst_mpd_sub_representation_node_free);
-  gst_mpd_helper_segment_base_type_free (self->SegmentBase);
+  gst_mpd_segment_base_node_free (self->SegmentBase);
   gst_mpd_segment_template_node_free (self->SegmentTemplate);
   gst_mpd_segment_list_node_free (self->SegmentList);
   g_list_free_full (self->BaseURLs, (GDestroyNotify) gst_mpd_baseurl_node_free);
@@ -46,11 +45,65 @@ gst_mpd_representation_node_finalize (GObject * object)
   G_OBJECT_CLASS (gst_mpd_representation_node_parent_class)->finalize (object);
 }
 
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_representation_get_xml_node (GstMPDNode * node)
+{
+  gchar *value;
+  xmlNodePtr representation_xml_node = NULL;
+  GstMPDRepresentationNode *self = GST_MPD_REPRESENTATION_NODE (node);
+
+  representation_xml_node = xmlNewNode (NULL, (xmlChar *) "Representation");
+
+  gst_xml_helper_set_prop_string (representation_xml_node, "id", self->id);
+  gst_xml_helper_set_prop_uint (representation_xml_node, "bandwidth",
+      self->bandwidth);
+  if (self->qualityRanking)
+    gst_xml_helper_set_prop_uint (representation_xml_node, "qualityRanking",
+        self->qualityRanking);
+
+
+  if (self->dependencyId) {
+    value = g_strjoinv (" ", self->dependencyId);
+    gst_xml_helper_set_prop_string (representation_xml_node, "dependencyId",
+        value);
+    g_free (value);
+  }
+  if (self->mediaStreamStructureId) {
+    value = g_strjoinv (" ", self->mediaStreamStructureId);
+    gst_xml_helper_set_prop_string (representation_xml_node,
+        "mediaStreamStructureId", value);
+    g_free (value);
+  }
+
+  g_list_foreach (self->BaseURLs, gst_mpd_node_get_list_item,
+      representation_xml_node);
+  g_list_foreach (self->SubRepresentations,
+      gst_mpd_representation_base_node_get_list_item, representation_xml_node);
+
+  gst_mpd_node_add_child_node (GST_MPD_NODE (self->SegmentBase),
+      representation_xml_node);
+  gst_mpd_mult_segment_base_node_add_child_node (GST_MPD_NODE
+      (self->SegmentTemplate), representation_xml_node);
+  gst_mpd_mult_segment_base_node_add_child_node (GST_MPD_NODE
+      (self->SegmentList), representation_xml_node);
+
+  return representation_xml_node;
+}
+
 static void
 gst_mpd_representation_node_class_init (GstMPDRepresentationNodeClass * klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GObjectClass *object_class;
+  GstMPDNodeClass *m_klass;
+
+  object_class = G_OBJECT_CLASS (klass);
+  m_klass = GST_MPD_NODE_CLASS (klass);
+
   object_class->finalize = gst_mpd_representation_node_finalize;
+
+  m_klass->get_xml_node = gst_mpd_representation_get_xml_node;
 }
 
 static void
@@ -61,7 +114,6 @@ gst_mpd_representation_node_init (GstMPDRepresentationNode * self)
   self->qualityRanking = 0;
   self->dependencyId = NULL;
   self->mediaStreamStructureId = NULL;
-  self->RepresentationBase = NULL;
   self->BaseURLs = NULL;
   self->SubRepresentations = NULL;
   self->SegmentBase = NULL;
index 2b0352c..617d978 100644 (file)
 
 #include <gst/gst.h>
 #include "gstmpdhelper.h"
+#include "gstmpdrepresentationbasenode.h"
 #include "gstmpdsegmentlistnode.h"
 #include "gstmpdsegmenttemplatenode.h"
 
 G_BEGIN_DECLS
 
 #define GST_TYPE_MPD_REPRESENTATION_NODE gst_mpd_representation_node_get_type ()
-#define GST_MPD_REPRESENTATION_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MPD_REPRESENTATION_NODE, GstMPDRepresentationNode))
-#define GST_MPD_REPRESENTATION_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MPD_REPRESENTATION_NODE, GstMPDRepresentationNodeClass))
-#define GST_IS_MPD_REPRESENTATION_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MPD_REPRESENTATION_NODE))
-#define GST_IS_MPD_REPRESENTATION_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MPD_REPRESENTATION_NODE))
-#define GST_MPD_REPRESENTATION_NODE_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MPD_REPRESENTATION_NODE, GstMPDRepresentationNodeClass))
-
-typedef struct _GstMPDRepresentationNode                GstMPDRepresentationNode;
-typedef struct _GstMPDRepresentationNodeClass           GstMPDRepresentationNodeClass;
-
+G_DECLARE_FINAL_TYPE (GstMPDRepresentationNode, gst_mpd_representation_node, GST, MPD_REPRESENTATION_NODE, GstMPDRepresentationBaseNode)
 
 struct _GstMPDRepresentationNode
 {
-  GstObject parent_instance;
+  GstMPDRepresentationBaseNode parent_instance;
   gchar *id;
   guint bandwidth;
   guint qualityRanking;
   gchar **dependencyId;              /* StringVectorType */
   gchar **mediaStreamStructureId;    /* StringVectorType */
-  /* RepresentationBase extension */
-  GstMPDRepresentationBaseType *RepresentationBase;
   /* list of BaseURL nodes */
   GList *BaseURLs;
   /* list of SubRepresentation nodes */
   GList *SubRepresentations;
   /* SegmentBase node */
-  GstMPDSegmentBaseType *SegmentBase;
+  GstMPDSegmentBaseNode *SegmentBase;
   /* SegmentTemplate node */
   GstMPDSegmentTemplateNode *SegmentTemplate;
   /* SegmentList node */
   GstMPDSegmentListNode *SegmentList;
 };
 
-struct _GstMPDRepresentationNodeClass {
-  GstObjectClass parent_class;
-};
-
-
-G_GNUC_INTERNAL GType gst_mpd_representation_node_get_type (void);
 
 GstMPDRepresentationNode * gst_mpd_representation_node_new (void);
 void gst_mpd_representation_node_free (GstMPDRepresentationNode* self);
index d2e954f..815c421 100644 (file)
@@ -21,7 +21,8 @@
 #include "gstmpdrootnode.h"
 #include "gstmpdparser.h"
 
-G_DEFINE_TYPE (GstMPDRootNode, gst_mpd_root_node, GST_TYPE_OBJECT);
+G_DEFINE_TYPE (GstMPDRootNode, gst_mpd_root_node, GST_TYPE_MPD_NODE);
+
 /* GObject VMethods */
 
 static void
@@ -44,7 +45,8 @@ gst_mpd_root_node_finalize (GObject * object)
   g_list_free_full (self->ProgramInfos,
       (GDestroyNotify) gst_mpd_program_information_node_free);
   g_list_free_full (self->BaseURLs, (GDestroyNotify) gst_mpd_baseurl_node_free);
-  g_list_free_full (self->Locations, (GDestroyNotify) g_free);
+  g_list_free_full (self->Locations,
+      (GDestroyNotify) gst_mpd_location_node_free);
   g_list_free_full (self->Periods, (GDestroyNotify) gst_mpd_period_node_free);
   g_list_free_full (self->Metrics, (GDestroyNotify) gst_mpd_metrics_node_free);
   g_list_free_full (self->UTCTimings,
@@ -54,11 +56,105 @@ gst_mpd_root_node_finalize (GObject * object)
   G_OBJECT_CLASS (gst_mpd_root_node_parent_class)->finalize (object);
 }
 
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_root_get_xml_node (GstMPDNode * node)
+{
+  xmlNodePtr root_xml_node;
+  GstMPDRootNode *self = GST_MPD_ROOT_NODE (node);
+
+  root_xml_node = xmlNewNode (NULL, (xmlChar *) "MPD");
+
+  gst_xml_helper_set_prop_string (root_xml_node, "xmlns",
+      self->default_namespace);
+  gst_xml_helper_set_prop_string (root_xml_node, "profiles", self->profiles);
+  gst_xml_helper_set_prop_string (root_xml_node, "schemaLocation",
+      self->schemaLocation);
+  gst_xml_helper_set_prop_string (root_xml_node, "xmlns:xsi",
+      self->namespace_xsi);
+  gst_xml_helper_set_prop_string (root_xml_node, "xmlns:ext",
+      self->namespace_ext);
+  gst_xml_helper_set_prop_string (root_xml_node, "id", self->id);
+
+  if (self->type == GST_MPD_FILE_TYPE_STATIC)
+    gst_xml_helper_set_prop_string (root_xml_node, "type", (gchar *) "static");
+  else
+    gst_xml_helper_set_prop_string (root_xml_node, "type", (gchar *) "dynamic");
+
+
+  gst_xml_helper_set_prop_date_time (root_xml_node, "availabilityStartTime",
+      self->availabilityStartTime);
+
+  gst_xml_helper_set_prop_date_time (root_xml_node, "availabilityEndTime",
+      self->availabilityEndTime);
+
+  if (self->mediaPresentationDuration)
+    gst_xml_helper_set_prop_duration (root_xml_node,
+        "mediaPresentationDuration", self->mediaPresentationDuration);
+  if (self->minimumUpdatePeriod)
+    gst_xml_helper_set_prop_duration (root_xml_node, "minimumUpdatePeriod",
+        self->minimumUpdatePeriod);
+  if (self->minimumUpdatePeriod)
+    gst_xml_helper_set_prop_duration (root_xml_node, "minBufferTime",
+        self->minBufferTime);
+  if (self->timeShiftBufferDepth)
+    gst_xml_helper_set_prop_duration (root_xml_node, "timeShiftBufferDepth",
+        self->timeShiftBufferDepth);
+  if (self->suggestedPresentationDelay)
+    gst_xml_helper_set_prop_duration (root_xml_node,
+        "suggestedPresentationDelay", self->suggestedPresentationDelay);
+  if (self->maxSegmentDuration)
+    gst_xml_helper_set_prop_duration (root_xml_node, "maxSegmentDuration",
+        self->maxSegmentDuration);
+  if (self->maxSubsegmentDuration)
+    gst_xml_helper_set_prop_duration (root_xml_node, "maxSubsegmentDuration",
+        self->maxSubsegmentDuration);
+
+  g_list_foreach (self->BaseURLs, gst_mpd_node_get_list_item, root_xml_node);
+  g_list_foreach (self->Locations, gst_mpd_node_get_list_item, root_xml_node);
+  g_list_foreach (self->ProgramInfos, gst_mpd_node_get_list_item,
+      root_xml_node);
+  g_list_foreach (self->Periods, gst_mpd_node_get_list_item, root_xml_node);
+  g_list_foreach (self->Metrics, gst_mpd_node_get_list_item, root_xml_node);
+  g_list_foreach (self->UTCTimings, gst_mpd_node_get_list_item, root_xml_node);
+
+  return root_xml_node;
+}
+
+static gboolean
+gst_mpd_root_get_xml_buffer (GstMPDNode * node, gchar ** doc_content,
+    gint * doc_size)
+{
+  xmlDocPtr doc;
+  xmlNodePtr root_xml_node;
+  xmlChar *xmlbody;
+
+  doc = xmlNewDoc ((xmlChar *) "1.0");
+  root_xml_node = gst_mpd_root_get_xml_node (node);
+  xmlDocSetRootElement (doc, root_xml_node);
+
+  xmlDocDumpMemory (doc, &xmlbody, doc_size);
+  *doc_content = g_strndup ((gchar *) xmlbody, *doc_size);
+  xmlFree (xmlbody);
+
+  xmlFreeDoc (doc);
+  return TRUE;
+}
+
 static void
 gst_mpd_root_node_class_init (GstMPDRootNodeClass * klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GObjectClass *object_class;
+  GstMPDNodeClass *m_klass;
+
+  object_class = G_OBJECT_CLASS (klass);
+  m_klass = GST_MPD_NODE_CLASS (klass);
+
   object_class->finalize = gst_mpd_root_node_finalize;
+
+  m_klass->get_xml_buffer = gst_mpd_root_get_xml_buffer;
+  m_klass->get_xml_node = gst_mpd_root_get_xml_node;
 }
 
 static void
index bf463e0..776e6a6 100644 (file)
 G_BEGIN_DECLS
 
 #define GST_TYPE_MPD_ROOT_NODE gst_mpd_root_node_get_type ()
-#define GST_MPD_ROOT_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MPD_ROOT_NODE, GstMPDRootNode))
-#define GST_MPD_ROOT_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MPD_ROOT_NODE, GstMPDRootNodeClass))
-#define GST_IS_MPD_ROOT_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MPD_ROOT_NODE))
-#define GST_IS_MPD_ROOT_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MPD_ROOT_NODE))
-#define GST_MPD_ROOT_NODE_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MPD_ROOT_NODE, GstMPDRootNodeClass))
-
-typedef struct _GstMPDRootNode                GstMPDRootNode;
-typedef struct _GstMPDRootNodeClass           GstMPDRootNodeClass;
-
+G_DECLARE_FINAL_TYPE (GstMPDRootNode, gst_mpd_root_node, GST, MPD_ROOT_NODE, GstMPDNode)
 
 struct _GstMPDRootNode
 {
@@ -75,13 +62,6 @@ struct _GstMPDRootNode
   GList *UTCTimings;
 };
 
-struct _GstMPDRootNodeClass {
-  GstObjectClass parent_class;
-};
-
-
-G_GNUC_INTERNAL GType gst_mpd_root_node_get_type (void);
-
 GstMPDRootNode * gst_mpd_root_node_new (void);
 void gst_mpd_root_node_free (GstMPDRootNode* self);
 
diff --git a/ext/dash/gstmpdsegmentbasenode.c b/ext/dash/gstmpdsegmentbasenode.c
new file mode 100644 (file)
index 0000000..e492197
--- /dev/null
@@ -0,0 +1,112 @@
+/* GStreamer
+ *
+ * Copyright (C) 2019 Collabora Ltd.
+ *   Author: Stéphane Cerveau <scerveau@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+#include "gstmpdsegmentbasenode.h"
+#include "gstmpdparser.h"
+
+G_DEFINE_TYPE (GstMPDSegmentBaseNode, gst_mpd_segment_base_node,
+    GST_TYPE_MPD_NODE);
+
+/* GObject VMethods */
+
+static void
+gst_mpd_segment_base_node_finalize (GObject * object)
+{
+  GstMPDSegmentBaseNode *self = GST_MPD_SEGMENT_BASE_NODE (object);
+
+  if (self->indexRange)
+    g_slice_free (GstXMLRange, self->indexRange);
+  gst_mpd_url_type_node_free (self->Initialization);
+  gst_mpd_url_type_node_free (self->RepresentationIndex);
+
+  G_OBJECT_CLASS (gst_mpd_segment_base_node_parent_class)->finalize (object);
+}
+
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_segment_base_get_xml_node (GstMPDNode * node)
+{
+  xmlNodePtr segment_base_xml_node = NULL;
+  GstMPDSegmentBaseNode *self = GST_MPD_SEGMENT_BASE_NODE (node);
+
+  segment_base_xml_node = xmlNewNode (NULL, (xmlChar *) "SegmentBase");
+
+  if (self->timescale)
+    gst_xml_helper_set_prop_uint (segment_base_xml_node, "timescale",
+        self->timescale);
+  if (self->presentationTimeOffset)
+    gst_xml_helper_set_prop_uint64 (segment_base_xml_node,
+        "presentationTimeOffset", self->presentationTimeOffset);
+  if (self->indexRange) {
+    gst_xml_helper_set_prop_range (segment_base_xml_node, "indexRange",
+        self->indexRange);
+    gst_xml_helper_set_prop_boolean (segment_base_xml_node, "indexRangeExact",
+        self->indexRangeExact);
+  }
+  if (self->Initialization)
+    gst_mpd_node_add_child_node (GST_MPD_NODE (self->Initialization),
+        segment_base_xml_node);
+  if (self->RepresentationIndex)
+    gst_mpd_node_add_child_node (GST_MPD_NODE (self->RepresentationIndex),
+        segment_base_xml_node);
+
+  return segment_base_xml_node;
+}
+
+static void
+gst_mpd_segment_base_node_class_init (GstMPDSegmentBaseNodeClass * klass)
+{
+  GObjectClass *object_class;
+  GstMPDNodeClass *m_klass;
+
+  object_class = G_OBJECT_CLASS (klass);
+  m_klass = GST_MPD_NODE_CLASS (klass);
+
+  object_class->finalize = gst_mpd_segment_base_node_finalize;
+
+  m_klass->get_xml_node = gst_mpd_segment_base_get_xml_node;
+}
+
+static void
+gst_mpd_segment_base_node_init (GstMPDSegmentBaseNode * self)
+{
+  self->timescale = 0;
+  self->presentationTimeOffset = 0;
+  self->indexRange = NULL;
+  self->indexRangeExact = FALSE;
+  /* Initialization node */
+  self->Initialization = NULL;
+  /* RepresentationIndex node */
+  self->RepresentationIndex = NULL;
+}
+
+GstMPDSegmentBaseNode *
+gst_mpd_segment_base_node_new (void)
+{
+  return g_object_new (GST_TYPE_MPD_SEGMENT_BASE_NODE, NULL);
+}
+
+void
+gst_mpd_segment_base_node_free (GstMPDSegmentBaseNode * self)
+{
+  if (self)
+    gst_object_unref (self);
+}
diff --git a/ext/dash/gstmpdsegmentbasenode.h b/ext/dash/gstmpdsegmentbasenode.h
new file mode 100644 (file)
index 0000000..7693177
--- /dev/null
@@ -0,0 +1,51 @@
+/* GStreamer
+ *
+ * Copyright (C) 2019 Collabora Ltd.
+ *   Author: Stéphane Cerveau <scerveau@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library (COPYING); if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSTMPDSEGMENTBASENODE_H__
+#define __GSTMPDSEGMENTBASENODE_H__
+
+#include <gst/gst.h>
+#include "gstmpdnode.h"
+#include "gstmpdurltypenode.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_MPD_SEGMENT_BASE_NODE gst_mpd_segment_base_node_get_type ()
+G_DECLARE_FINAL_TYPE (GstMPDSegmentBaseNode, gst_mpd_segment_base_node, GST, MPD_SEGMENT_BASE_NODE, GstMPDNode)
+
+struct _GstMPDSegmentBaseNode
+{
+  GstObject     parent_instance;
+  guint timescale;
+  guint64 presentationTimeOffset;
+  GstXMLRange *indexRange;
+  gboolean indexRangeExact;
+  /* Initialization node */
+  GstMPDURLTypeNode *Initialization;
+  /* RepresentationIndex node */
+  GstMPDURLTypeNode *RepresentationIndex;
+};
+
+GstMPDSegmentBaseNode * gst_mpd_segment_base_node_new (void);
+void gst_mpd_segment_base_node_free (GstMPDSegmentBaseNode* self);
+
+G_END_DECLS
+
+#endif /* __GSTMPDSEGMENTBASENODE_H__ */
index 01c6d9a..5d0db76 100644 (file)
  */
 #include "gstmpdsegmentlistnode.h"
 #include "gstmpdparser.h"
-#include "gstmpdhelper.h"
 
 G_DEFINE_TYPE (GstMPDSegmentListNode, gst_mpd_segment_list_node,
-    GST_TYPE_OBJECT);
+    GST_TYPE_MPD_MULT_SEGMENT_BASE_NODE);
 
 /* GObject VMethods */
 
@@ -34,25 +33,49 @@ gst_mpd_segment_list_node_finalize (GObject * object)
 
   g_list_free_full (self->SegmentURL,
       (GDestroyNotify) gst_mpd_segment_url_node_free);
-  /* MultipleSegmentBaseType extension */
-  gst_mpd_helper_mult_seg_base_type_free (self->MultSegBaseType);
   if (self->xlink_href)
     xmlFree (self->xlink_href);
 
   G_OBJECT_CLASS (gst_mpd_segment_list_node_parent_class)->finalize (object);
 }
 
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_segment_list_get_xml_node (GstMPDNode * node)
+{
+  xmlNodePtr segment_list_xml_node = NULL;
+  GstMPDSegmentListNode *self = GST_MPD_SEGMENT_LIST_NODE (node);
+
+  segment_list_xml_node = xmlNewNode (NULL, (xmlChar *) "SegmentList");
+
+  g_list_foreach (self->SegmentURL, gst_mpd_node_get_list_item,
+      segment_list_xml_node);
+
+  if (self->xlink_href)
+    gst_xml_helper_set_prop_string (segment_list_xml_node, "xlink_href",
+        self->xlink_href);
+
+  return segment_list_xml_node;
+}
+
 static void
 gst_mpd_segment_list_node_class_init (GstMPDSegmentListNodeClass * klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GObjectClass *object_class;
+  GstMPDNodeClass *m_klass;
+
+  object_class = G_OBJECT_CLASS (klass);
+  m_klass = GST_MPD_NODE_CLASS (klass);
+
   object_class->finalize = gst_mpd_segment_list_node_finalize;
+
+  m_klass->get_xml_node = gst_mpd_segment_list_get_xml_node;
 }
 
 static void
 gst_mpd_segment_list_node_init (GstMPDSegmentListNode * self)
 {
-  self->MultSegBaseType = NULL;
   self->SegmentURL = NULL;
   self->xlink_href = NULL;
   self->actuate = GST_MPD_XLINK_ACTUATE_ON_REQUEST;
index 715e702..1ed8769 100644 (file)
 
 #include <gst/gst.h>
 #include "gstmpdhelper.h"
+#include "gstmpdmultsegmentbasenode.h"
 #include "gstmpdsegmenturlnode.h"
 
 G_BEGIN_DECLS
 
 #define GST_TYPE_MPD_SEGMENT_LIST_NODE gst_mpd_segment_list_node_get_type ()
-#define GST_MPD_SEGMENT_LIST_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MPD_SEGMENT_LIST_NODE, GstMPDSegmentListNode))
-#define GST_MPD_SEGMENT_LIST_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MPD_SEGMENT_LIST_NODE, GstMPDSegmentListNodeClass))
-#define GST_IS_MPD_SEGMENT_LIST_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MPD_SEGMENT_LIST_NODE))
-#define GST_IS_MPD_SEGMENT_LIST_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MPD_SEGMENT_LIST_NODE))
-#define GST_MPD_SEGMENT_LIST_NODE_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MPD_SEGMENT_LIST_NODE, GstMPDSegmentListNodeClass))
-
-typedef struct _GstMPDSegmentListNode                GstMPDSegmentListNode;
-typedef struct _GstMPDSegmentListNodeClass           GstMPDSegmentListNodeClass;
+G_DECLARE_FINAL_TYPE (GstMPDSegmentListNode, gst_mpd_segment_list_node, GST, MPD_SEGMENT_LIST_NODE, GstMPDMultSegmentBaseNode)
 
 
 struct _GstMPDSegmentListNode
 {
-  GstObject parent_instance;
+  GstMPDMultSegmentBaseNode parent_instance;
   /* extension */
-  GstMPDMultSegmentBaseType *MultSegBaseType;
   /* list of SegmentURL nodes */
   GList *SegmentURL;
 
@@ -55,13 +43,6 @@ struct _GstMPDSegmentListNode
   GstMPDXLinkActuate actuate;
 };
 
-struct _GstMPDSegmentListNodeClass {
-  GstObjectClass parent_class;
-};
-
-
-G_GNUC_INTERNAL GType gst_mpd_segment_list_node_get_type (void);
-
 GstMPDSegmentListNode * gst_mpd_segment_list_node_new (void);
 void gst_mpd_segment_list_node_free (GstMPDSegmentListNode* self);
 
index 3fc898a..ac2af44 100644 (file)
@@ -22,7 +22,7 @@
 #include "gstmpdparser.h"
 
 G_DEFINE_TYPE (GstMPDSegmentTemplateNode, gst_mpd_segment_template_node,
-    GST_TYPE_OBJECT);
+    GST_TYPE_MPD_MULT_SEGMENT_BASE_NODE);
 
 /* GObject VMethods */
 
@@ -39,25 +39,58 @@ gst_mpd_segment_template_node_finalize (GObject * object)
     xmlFree (self->initialization);
   if (self->bitstreamSwitching)
     xmlFree (self->bitstreamSwitching);
-  /* MultipleSegmentBaseType extension */
-  gst_mpd_helper_mult_seg_base_type_free (self->MultSegBaseType);
 
   G_OBJECT_CLASS (gst_mpd_segment_template_node_parent_class)->finalize
       (object);
 }
 
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_segment_template_get_xml_node (GstMPDNode * node)
+{
+  xmlNodePtr segment_template_xml_node = NULL;
+  GstMPDSegmentTemplateNode *self = GST_MPD_SEGMENT_TEMPLATE_NODE (node);
+
+  segment_template_xml_node = xmlNewNode (NULL, (xmlChar *) "SegmentTemplate");
+
+  if (self->media)
+    gst_xml_helper_set_prop_string (segment_template_xml_node, "media",
+        self->media);
+
+  if (self->index)
+    gst_xml_helper_set_prop_string (segment_template_xml_node, "index",
+        self->index);
+
+  if (self->initialization)
+    gst_xml_helper_set_prop_string (segment_template_xml_node, "initialization",
+        self->initialization);
+
+  if (self->bitstreamSwitching)
+    gst_xml_helper_set_prop_string (segment_template_xml_node,
+        "bitstreamSwitching", self->bitstreamSwitching);
+
+  return segment_template_xml_node;
+}
+
 static void
 gst_mpd_segment_template_node_class_init (GstMPDSegmentTemplateNodeClass *
     klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GObjectClass *object_class;
+  GstMPDNodeClass *m_klass;
+
+  object_class = G_OBJECT_CLASS (klass);
+  m_klass = GST_MPD_NODE_CLASS (klass);
+
   object_class->finalize = gst_mpd_segment_template_node_finalize;
+
+  m_klass->get_xml_node = gst_mpd_segment_template_get_xml_node;
 }
 
 static void
 gst_mpd_segment_template_node_init (GstMPDSegmentTemplateNode * self)
 {
-  self->MultSegBaseType = NULL;
   self->media = NULL;
   self->index = NULL;
   self->initialization = NULL;
index b882f55..b9fb469 100644 (file)
 
 #include <gst/gst.h>
 #include "gstmpdhelper.h"
+#include "gstmpdmultsegmentbasenode.h"
 
 G_BEGIN_DECLS
 
 #define GST_TYPE_MPD_SEGMENT_TEMPLATE_NODE gst_mpd_segment_template_node_get_type ()
-#define GST_MPD_SEGMENT_TEMPLATE_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MPD_SEGMENT_TEMPLATE_NODE, GstMPDSegmentTemplateNode))
-#define GST_MPD_SEGMENT_TEMPLATE_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MPD_SEGMENT_TEMPLATE_NODE, GstMPDSegmentTemplateNodeClass))
-#define GST_IS_MPD_SEGMENT_TEMPLATE_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MPD_SEGMENT_TEMPLATE_NODE))
-#define GST_IS_MPD_SEGMENT_TEMPLATE_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MPD_SEGMENT_TEMPLATE_NODE))
-#define GST_MPD_SEGMENT_TEMPLATE_NODE_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MPD_SEGMENT_TEMPLATE_NODE, GstMPDSegmentTemplateNodeClass))
-
-typedef struct _GstMPDSegmentTemplateNode                GstMPDSegmentTemplateNode;
-typedef struct _GstMPDSegmentTemplateNodeClass           GstMPDSegmentTemplateNodeClass;
-
+G_DECLARE_FINAL_TYPE (GstMPDSegmentTemplateNode, gst_mpd_segment_template_node, GST, MPD_SEGMENT_TEMPLATE_NODE, GstMPDMultSegmentBaseNode)
 
 struct _GstMPDSegmentTemplateNode
 {
-  GstObject     parent_instance;
-  /* extension */
-  GstMPDMultSegmentBaseType *MultSegBaseType;
+  GstMPDMultSegmentBaseNode     parent_instance;
+
   gchar *media;
   gchar *index;
   gchar *initialization;
   gchar *bitstreamSwitching;
 };
 
-struct _GstMPDSegmentTemplateNodeClass {
-    GstObjectClass parent_class;
-};
-
-
-G_GNUC_INTERNAL GType gst_mpd_segment_template_node_get_type (void);
-
 GstMPDSegmentTemplateNode * gst_mpd_segment_template_node_new (void);
 void gst_mpd_segment_template_node_free (GstMPDSegmentTemplateNode* self);
 
index c6e449a..9b574e6 100644 (file)
@@ -22,7 +22,7 @@
 #include "gstmpdparser.h"
 
 G_DEFINE_TYPE (GstMPDSegmentTimelineNode, gst_mpd_segment_timeline_node,
-    GST_TYPE_OBJECT);
+    GST_TYPE_MPD_NODE);
 
 /* GObject VMethods */
 
@@ -38,12 +38,35 @@ gst_mpd_segment_timeline_node_finalize (GObject * object)
       (object);
 }
 
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_segment_timeline_get_xml_node (GstMPDNode * node)
+{
+  xmlNodePtr segment_timeline_xml_node = NULL;
+  GstMPDSegmentTimelineNode *self = GST_MPD_SEGMENT_TIMELINE_NODE (node);
+
+  segment_timeline_xml_node = xmlNewNode (NULL, (xmlChar *) "SegmentTimeline");
+
+  g_queue_foreach (&self->S, (GFunc) gst_mpd_node_get_list_item,
+      segment_timeline_xml_node);
+
+  return segment_timeline_xml_node;
+}
+
 static void
 gst_mpd_segment_timeline_node_class_init (GstMPDSegmentTimelineNodeClass *
     klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GObjectClass *object_class;
+  GstMPDNodeClass *m_klass;
+
+  object_class = G_OBJECT_CLASS (klass);
+  m_klass = GST_MPD_NODE_CLASS (klass);
+
   object_class->finalize = gst_mpd_segment_timeline_node_finalize;
+
+  m_klass->get_xml_node = gst_mpd_segment_timeline_get_xml_node;
 }
 
 static void
index b275696..a91ebfe 100644 (file)
 #define __GSTMPDSEGMENTTIMELINENODE_H__
 
 #include <gst/gst.h>
-#include "gstxmlhelper.h"
+#include "gstmpdnode.h"
 
 G_BEGIN_DECLS
 
 #define GST_TYPE_MPD_SEGMENT_TIMELINE_NODE gst_mpd_segment_timeline_node_get_type ()
-#define GST_MPD_SEGMENT_TIMELINE_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MPD_SEGMENT_TIMELINE_NODE, GstMPDSegmentTimelineNode))
-#define GST_MPD_SEGMENT_TIMELINE_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MPD_SEGMENT_TIMELINE_NODE, GstMPDSegmentTimelineNodeClass))
-#define GST_IS_MPD_SEGMENT_TIMELINE_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MPD_SEGMENT_TIMELINE_NODE))
-#define GST_IS_MPD_SEGMENT_TIMELINE_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MPD_SEGMENT_TIMELINE_NODE))
-#define GST_MPD_SEGMENT_TIMELINE_NODE_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MPD_SEGMENT_TIMELINE_NODE, GstMPDSegmentTimelineNodeClass))
-
-typedef struct _GstMPDSegmentTimelineNode                GstMPDSegmentTimelineNode;
-typedef struct _GstMPDSegmentTimelineNodeClass           GstMPDSegmentTimelineNodeClass;
-
+G_DECLARE_FINAL_TYPE (GstMPDSegmentTimelineNode, gst_mpd_segment_timeline_node, GST, MPD_SEGMENT_TIMELINE_NODE, GstMPDNode)
 
 struct _GstMPDSegmentTimelineNode
 {
@@ -49,13 +36,6 @@ struct _GstMPDSegmentTimelineNode
   GQueue S;
 };
 
-struct _GstMPDSegmentTimelineNodeClass {
-  GstObjectClass parent_class;
-};
-
-
-G_GNUC_INTERNAL GType gst_mpd_segment_timeline_node_get_type (void);
-
 GstMPDSegmentTimelineNode * gst_mpd_segment_timeline_node_new (void);
 void gst_mpd_segment_timeline_node_free (GstMPDSegmentTimelineNode* self);
 
index b8f23bf..2a39091 100644 (file)
@@ -22,7 +22,8 @@
 #include "gstmpdparser.h"
 #include "gstmpdhelper.h"
 
-G_DEFINE_TYPE (GstMPDSegmentURLNode, gst_mpd_segment_url_node, GST_TYPE_OBJECT);
+G_DEFINE_TYPE (GstMPDSegmentURLNode, gst_mpd_segment_url_node,
+    GST_TYPE_MPD_NODE);
 
 /* GObject VMethods */
 
@@ -41,11 +42,45 @@ gst_mpd_segment_url_node_finalize (GObject * object)
   G_OBJECT_CLASS (gst_mpd_segment_url_node_parent_class)->finalize (object);
 }
 
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_segment_url_get_xml_node (GstMPDNode * node)
+{
+  xmlNodePtr segment_url_xml_node = NULL;
+  GstMPDSegmentURLNode *self = GST_MPD_SEGMENT_URL_NODE (node);
+
+  segment_url_xml_node = xmlNewNode (NULL, (xmlChar *) "SegmentURL");
+
+  if (self->media)
+    gst_xml_helper_set_prop_string (segment_url_xml_node, "media", self->media);
+
+  if (self->mediaRange)
+    gst_xml_helper_set_prop_range (segment_url_xml_node, "mediaRange",
+        self->mediaRange);
+
+  if (self->index)
+    gst_xml_helper_set_prop_string (segment_url_xml_node, "index", self->index);
+
+  if (self->indexRange)
+    gst_xml_helper_set_prop_range (segment_url_xml_node, "indexRange",
+        self->indexRange);
+
+  return segment_url_xml_node;
+}
+
 static void
 gst_mpd_segment_url_node_class_init (GstMPDSegmentURLNodeClass * klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GObjectClass *object_class;
+  GstMPDNodeClass *m_klass;
+
+  object_class = G_OBJECT_CLASS (klass);
+  m_klass = GST_MPD_NODE_CLASS (klass);
+
   object_class->finalize = gst_mpd_segment_url_node_finalize;
+
+  m_klass->get_xml_node = gst_mpd_segment_url_get_xml_node;
 }
 
 static void
index 5523ec5..851632c 100644 (file)
 #define __GSTMPDSEGMENTURLNODE_H__
 
 #include <gst/gst.h>
-#include "gstmpdhelper.h"
+#include "gstmpdnode.h"
 
 G_BEGIN_DECLS
 
 #define GST_TYPE_MPD_SEGMENT_URL_NODE gst_mpd_segment_url_node_get_type ()
-#define GST_MPD_SEGMENT_URL_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MPD_SEGMENT_URL_NODE, GstMPDSegmentURLNode))
-#define GST_MPD_SEGMENT_URL_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MPD_SEGMENT_URL_NODE, GstMPDSegmentURLNodeClass))
-#define GST_IS_MPD_SEGMENT_URL_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MPD_SEGMENT_URL_NODE))
-#define GST_IS_MPD_SEGMENT_URL_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MPD_SEGMENT_URL_NODE))
-#define GST_MPD_SEGMENT_URL_NODE_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MPD_SEGMENT_URL_NODE, GstMPDSegmentURLNodeClass))
-
-typedef struct _GstMPDSegmentURLNode                GstMPDSegmentURLNode;
-typedef struct _GstMPDSegmentURLNodeClass           GstMPDSegmentURLNodeClass;
-
+G_DECLARE_FINAL_TYPE (GstMPDSegmentURLNode, gst_mpd_segment_url_node, GST, MPD_SEGMENT_URL_NODE, GstMPDNode)
 
 struct _GstMPDSegmentURLNode
 {
@@ -51,13 +38,6 @@ struct _GstMPDSegmentURLNode
   GstXMLRange *indexRange;
 };
 
-struct _GstMPDSegmentURLNodeClass {
-  GstObjectClass parent_class;
-};
-
-
-G_GNUC_INTERNAL GType gst_mpd_segment_url_node_get_type (void);
-
 GstMPDSegmentURLNode * gst_mpd_segment_url_node_new (void);
 void gst_mpd_segment_url_node_free (GstMPDSegmentURLNode* self);
 
index 63fd06e..d823d8a 100644 (file)
 #include "gstmpdsnode.h"
 #include "gstmpdparser.h"
 
-G_DEFINE_TYPE (GstMPDSNode, gst_mpd_s_node, GST_TYPE_OBJECT);
+G_DEFINE_TYPE (GstMPDSNode, gst_mpd_s_node, GST_TYPE_MPD_NODE);
 
-/* GObject VMethods */
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_s_get_xml_node (GstMPDNode * node)
+{
+  xmlNodePtr s_xml_node = NULL;
+  GstMPDSNode *self = GST_MPD_S_NODE (node);
+
+  s_xml_node = xmlNewNode (NULL, (xmlChar *) "S");
+
+  if (self->t)
+    gst_xml_helper_set_prop_uint64 (s_xml_node, "t", self->t);
+
+  if (self->d)
+    gst_xml_helper_set_prop_uint64 (s_xml_node, "d", self->d);
+
+  if (self->r)
+    gst_xml_helper_set_prop_int (s_xml_node, "r", self->r);
+
+  return s_xml_node;
+}
 
 static void
 gst_mpd_s_node_class_init (GstMPDSNodeClass * klass)
 {
+  GstMPDNodeClass *m_klass;
+
+  m_klass = GST_MPD_NODE_CLASS (klass);
+
+  m_klass->get_xml_node = gst_mpd_s_get_xml_node;
 }
 
 static void
index ded0235..c33b898 100644 (file)
 #define __GSTMPDSNODE_H__
 
 #include <gst/gst.h>
-#include "gstmpdhelper.h"
+#include "gstmpdnode.h"
 
 G_BEGIN_DECLS
 
 #define GST_TYPE_MPD_S_NODE gst_mpd_s_node_get_type ()
-#define GST_MPD_S_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MPD_S_NODE, GstMPDSNode))
-#define GST_MPD_S_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MPD_S_NODE, GstMPDSNodeClass))
-#define GST_IS_MPD_S_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MPD_S_NODE))
-#define GST_IS_MPD_S_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MPD_S_NODE))
-#define GST_MPD_S_NODE_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MPD_S_NODE, GstMPDSNodeClass))
-
-typedef struct _GstMPDSNode                GstMPDSNode;
-typedef struct _GstMPDSNodeClass           GstMPDSNodeClass;
-
+G_DECLARE_FINAL_TYPE (GstMPDSNode, gst_mpd_s_node, GST, MPD_S_NODE, GstMPDNode)
 
 struct _GstMPDSNode
 {
@@ -50,13 +37,6 @@ struct _GstMPDSNode
   gint r;
 };
 
-struct _GstMPDSNodeClass {
-  GstObjectClass parent_class;
-};
-
-
-G_GNUC_INTERNAL GType gst_mpd_s_node_get_type (void);
-
 GstMPDSNode * gst_mpd_s_node_new (void);
 void gst_mpd_s_node_free (GstMPDSNode* self);
 
index 55b9a47..66cde3d 100644 (file)
@@ -22,7 +22,7 @@
 #include "gstmpdparser.h"
 
 G_DEFINE_TYPE (GstMPDSubRepresentationNode, gst_mpd_sub_representation_node,
-    GST_TYPE_OBJECT);
+    GST_TYPE_MPD_REPRESENTATION_BASE_NODE);
 
 /* GObject VMethods */
 
@@ -31,7 +31,6 @@ gst_mpd_sub_representation_node_finalize (GObject * object)
 {
   GstMPDSubRepresentationNode *self = GST_MPD_SUB_REPRESENTATION_NODE (object);
 
-  gst_mpd_helper_representation_base_type_free (self->RepresentationBase);
   if (self->dependencyLevel)
     xmlFree (self->dependencyLevel);
   g_strfreev (self->contentComponent);
@@ -40,21 +39,58 @@ gst_mpd_sub_representation_node_finalize (GObject * object)
       (object);
 }
 
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_sub_representation_get_xml_node (GstMPDNode * node)
+{
+  gchar *value = NULL;
+  xmlNodePtr sub_representation_xml_node = NULL;
+  GstMPDSubRepresentationNode *self = GST_MPD_SUB_REPRESENTATION_NODE (node);
+
+  sub_representation_xml_node =
+      xmlNewNode (NULL, (xmlChar *) "SubRepresentation");
+
+  gst_xml_helper_set_prop_uint (sub_representation_xml_node, "level",
+      self->level);
+
+  gst_xml_helper_set_prop_uint_vector_type (sub_representation_xml_node,
+      "dependencyLevel", self->dependencyLevel, self->dependencyLevel_size);
+
+  gst_xml_helper_set_prop_uint (sub_representation_xml_node, "bandwidth",
+      self->level);
+
+  if (self->contentComponent) {
+    value = g_strjoinv (" ", self->contentComponent);
+    gst_xml_helper_set_prop_string (sub_representation_xml_node,
+        "contentComponent", value);
+    g_free (value);
+  }
+
+  return sub_representation_xml_node;
+}
+
 static void
 gst_mpd_sub_representation_node_class_init (GstMPDSubRepresentationNodeClass *
     klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GObjectClass *object_class;
+  GstMPDNodeClass *m_klass;
+
+  object_class = G_OBJECT_CLASS (klass);
+  m_klass = GST_MPD_NODE_CLASS (klass);
+
   object_class->finalize = gst_mpd_sub_representation_node_finalize;
+
+  m_klass->get_xml_node = gst_mpd_sub_representation_get_xml_node;
 }
 
 static void
 gst_mpd_sub_representation_node_init (GstMPDSubRepresentationNode * self)
 {
-  self->RepresentationBase = NULL;
   self->level = 0;
   self->dependencyLevel = NULL;
-  self->size = 0;
+  self->dependencyLevel_size = 0;
   self->bandwidth = 0;
   self->contentComponent = NULL;
 }
index 40c4db3..79ead66 100644 (file)
 
 #include <gst/gst.h>
 #include "gstmpdhelper.h"
+#include "gstmpdrepresentationbasenode.h"
 
 G_BEGIN_DECLS
 
 #define GST_TYPE_MPD_SUB_REPRESENTATION_NODE gst_mpd_sub_representation_node_get_type ()
-#define GST_MPD_SUB_REPRESENTATION_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MPD_SUB_REPRESENTATION_NODE, GstMPDSubRepresentationNode))
-#define GST_MPD_SUB_REPRESENTATION_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MPD_SUB_REPRESENTATION_NODE, GstMPDSubRepresentationNodeClass))
-#define GST_IS_MPD_SUB_REPRESENTATION_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MPD_SUB_REPRESENTATION_NODE))
-#define GST_IS_MPD_SUB_REPRESENTATION_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MPD_SUB_REPRESENTATION_NODE))
-#define GST_MPD_SUB_REPRESENTATION_NODE_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MPD_SUB_REPRESENTATION_NODE, GstMPDSubRepresentationNodeClass))
-
-typedef struct _GstMPDSubRepresentationNode                GstMPDSubRepresentationNode;
-typedef struct _GstMPDSubRepresentationNodeClass           GstMPDSubRepresentationNodeClass;
-
+G_DECLARE_FINAL_TYPE (GstMPDSubRepresentationNode, gst_mpd_sub_representation_node, GST, MPD_SUB_REPRESENTATION_NODE, GstMPDRepresentationBaseNode)
 
 struct _GstMPDSubRepresentationNode
 {
-  GstObject parent_instance;
+  GstMPDRepresentationBaseNode parent_instance;
   /* RepresentationBase extension */
-  GstMPDRepresentationBaseType *RepresentationBase;
   guint level;
   guint *dependencyLevel;            /* UIntVectorType */
-  guint size;                        /* size of "dependencyLevel" array */
+  guint dependencyLevel_size;        /* size of "dependencyLevel" array */
   guint bandwidth;
   gchar **contentComponent;          /* StringVectorType */
 };
 
-struct _GstMPDSubRepresentationNodeClass {
-  GstObjectClass parent_class;
-};
-
-
-G_GNUC_INTERNAL GType gst_mpd_sub_representation_node_get_type (void);
-
 GstMPDSubRepresentationNode * gst_mpd_sub_representation_node_new (void);
 void gst_mpd_sub_representation_node_free (GstMPDSubRepresentationNode* self);
 
index 8a8cd6a..d537ed9 100644 (file)
@@ -21,7 +21,7 @@
 #include "gstmpdsubsetnode.h"
 #include "gstmpdparser.h"
 
-G_DEFINE_TYPE (GstMPDSubsetNode, gst_mpd_subset_node, GST_TYPE_OBJECT);
+G_DEFINE_TYPE (GstMPDSubsetNode, gst_mpd_subset_node, GST_TYPE_MPD_NODE);
 
 /* GObject VMethods */
 
@@ -36,17 +36,41 @@ gst_mpd_subset_node_finalize (GObject * object)
   G_OBJECT_CLASS (gst_mpd_subset_node_parent_class)->finalize (object);
 }
 
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_subset_get_xml_node (GstMPDNode * node)
+{
+  xmlNodePtr subset_xml_node = NULL;
+  GstMPDSubsetNode *self = GST_MPD_SUBSET_NODE (node);
+
+  subset_xml_node = xmlNewNode (NULL, (xmlChar *) "Subset");
+
+  if (self->contains)
+    gst_xml_helper_set_prop_uint_vector_type (subset_xml_node, "contains",
+        self->contains, self->contains_size);
+
+  return subset_xml_node;
+}
+
 static void
 gst_mpd_subset_node_class_init (GstMPDSubsetNodeClass * klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GObjectClass *object_class;
+  GstMPDNodeClass *m_klass;
+
+  object_class = G_OBJECT_CLASS (klass);
+  m_klass = GST_MPD_NODE_CLASS (klass);
+
   object_class->finalize = gst_mpd_subset_node_finalize;
+
+  m_klass->get_xml_node = gst_mpd_subset_get_xml_node;
 }
 
 static void
 gst_mpd_subset_node_init (GstMPDSubsetNode * self)
 {
-  self->size = 0;
+  self->contains_size = 0;
   self->contains = NULL;
 }
 
index d307245..756f4d9 100644 (file)
 #define __GSTMPDSUBSETNODE_H__
 
 #include <gst/gst.h>
-#include "gstmpdhelper.h"
+#include "gstmpdnode.h"
 
 G_BEGIN_DECLS
 
 #define GST_TYPE_MPD_SUBSET_NODE gst_mpd_subset_node_get_type ()
-#define GST_MPD_SUBSET_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MPD_SUBSET_NODE, GstMPDSubsetNode))
-#define GST_MPD_SUBSET_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MPD_SUBSET_NODE, GstMPDSubsetNodeClass))
-#define GST_IS_MPD_SUBSET_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MPD_SUBSET_NODE))
-#define GST_IS_MPD_SUBSET_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MPD_SUBSET_NODE))
-#define GST_MPD_SUBSET_NODE_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MPD_SUBSET_NODE, GstMPDSubsetNodeClass))
-
-typedef struct _GstMPDSubsetNode                GstMPDSubsetNode;
-typedef struct _GstMPDSubsetNodeClass           GstMPDSubsetNodeClass;
-
+G_DECLARE_FINAL_TYPE (GstMPDSubsetNode, gst_mpd_subset_node, GST, MPD_SUBSET_NODE, GstMPDNode)
 
 struct _GstMPDSubsetNode
 {
   GstObject parent_instance;
   guint *contains;                   /* UIntVectorType */
-  guint size;                        /* size of the "contains" array */
+  guint contains_size;               /* size of the "contains" array */
 };
 
 struct _GstMPDSubsetNodeClass {
-  GstObjectClass parent_class;
+  GstMPDNodeClass parent_class;
 };
 
 
-G_GNUC_INTERNAL GType gst_mpd_subset_node_get_type (void);
-
 GstMPDSubsetNode * gst_mpd_subset_node_new (void);
 void gst_mpd_subset_node_free (GstMPDSubsetNode* self);
 
diff --git a/ext/dash/gstmpdurltypenode.c b/ext/dash/gstmpdurltypenode.c
new file mode 100644 (file)
index 0000000..5a1ad50
--- /dev/null
@@ -0,0 +1,110 @@
+/* GStreamer
+ *
+ * Copyright (C) 2019 Collabora Ltd.
+ *   Author: Stéphane Cerveau <scerveau@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+#include "gstmpdurltypenode.h"
+#include "gstmpdparser.h"
+
+G_DEFINE_TYPE (GstMPDURLTypeNode, gst_mpd_url_type_node, GST_TYPE_MPD_NODE);
+
+/* GObject VMethods */
+
+static void
+gst_mpd_url_type_node_finalize (GObject * object)
+{
+  GstMPDURLTypeNode *self = GST_MPD_URL_TYPE_NODE (object);
+
+  if (self->sourceURL)
+    xmlFree (self->sourceURL);
+  g_slice_free (GstXMLRange, self->range);
+  g_free (self->node_name);
+
+  G_OBJECT_CLASS (gst_mpd_url_type_node_parent_class)->finalize (object);
+}
+
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_url_type_get_xml_node (GstMPDNode * node)
+{
+  xmlNodePtr url_type_xml_node = NULL;
+  GstMPDURLTypeNode *self = GST_MPD_URL_TYPE_NODE (node);
+
+  url_type_xml_node = xmlNewNode (NULL, (xmlChar *) self->node_name);
+
+  gst_xml_helper_set_prop_string (url_type_xml_node, "sourceURL",
+      self->sourceURL);
+  gst_xml_helper_set_prop_range (url_type_xml_node, "range", self->range);
+
+  return url_type_xml_node;
+}
+
+static void
+gst_mpd_url_type_node_class_init (GstMPDURLTypeNodeClass * klass)
+{
+  GObjectClass *object_class;
+  GstMPDNodeClass *m_klass;
+
+  object_class = G_OBJECT_CLASS (klass);
+  m_klass = GST_MPD_NODE_CLASS (klass);
+
+  object_class->finalize = gst_mpd_url_type_node_finalize;
+
+  m_klass->get_xml_node = gst_mpd_url_type_get_xml_node;
+}
+
+static void
+gst_mpd_url_type_node_init (GstMPDURLTypeNode * self)
+{
+  self->node_name = NULL;
+  self->sourceURL = NULL;
+  self->range = NULL;
+}
+
+GstMPDURLTypeNode *
+gst_mpd_url_type_node_new (const gchar * name)
+{
+  GstMPDURLTypeNode *self = g_object_new (GST_TYPE_MPD_URL_TYPE_NODE, NULL);
+  self->node_name = g_strdup (name);
+  return self;
+}
+
+void
+gst_mpd_url_type_node_free (GstMPDURLTypeNode * self)
+{
+  if (self)
+    gst_object_unref (self);
+}
+
+GstMPDURLTypeNode *
+gst_mpd_url_type_node_clone (GstMPDURLTypeNode * url)
+{
+
+  GstMPDURLTypeNode *clone = NULL;
+
+  if (url) {
+    clone = gst_mpd_url_type_node_new (url->node_name);
+    if (url->sourceURL) {
+      clone->sourceURL = xmlMemStrdup (url->sourceURL);
+    }
+    clone->range = gst_xml_helper_clone_range (url->range);
+  }
+
+  return clone;
+}
diff --git a/ext/dash/gstmpdurltypenode.h b/ext/dash/gstmpdurltypenode.h
new file mode 100644 (file)
index 0000000..fcb0e1e
--- /dev/null
@@ -0,0 +1,47 @@
+/* GStreamer
+ *
+ * Copyright (C) 2019 Collabora Ltd.
+ *   Author: Stéphane Cerveau <scerveau@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library (COPYING); if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSTMPDURLTYPENODE_H__
+#define __GSTMPDURLTYPENODE_H__
+
+#include <gst/gst.h>
+#include "gstmpdnode.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_MPD_URL_TYPE_NODE gst_mpd_url_type_node_get_type ()
+G_DECLARE_FINAL_TYPE (GstMPDURLTypeNode, gst_mpd_url_type_node, GST, MPD_URL_TYPE_NODE, GstMPDNode)
+
+struct _GstMPDURLTypeNode
+{
+  GstObject     parent_instance;
+  gchar* node_name;
+  gchar *sourceURL;
+  GstXMLRange *range;
+};
+
+GstMPDURLTypeNode * gst_mpd_url_type_node_new (const gchar* name);
+void gst_mpd_url_type_node_free (GstMPDURLTypeNode* self);
+
+GstMPDURLTypeNode *gst_mpd_url_type_node_clone (GstMPDURLTypeNode * url);
+
+G_END_DECLS
+
+#endif /* __GSTMPDURLTYPENODE_H__ */
index ca9c7bb..a02c89c 100644 (file)
@@ -26,10 +26,33 @@ enum
   PROP_MPD_UTCTIMING_0,
 };
 
-G_DEFINE_TYPE (GstMPDUTCTimingNode, gst_mpd_utctiming_node, GST_TYPE_OBJECT);
+G_DEFINE_TYPE (GstMPDUTCTimingNode, gst_mpd_utctiming_node, GST_TYPE_MPD_NODE);
 
 /* GObject VMethods */
 
+static const struct GstMPDUTCTimingMethod gst_mpd_utctiming_methods[] = {
+  {"urn:mpeg:dash:utc:ntp:2014", GST_MPD_UTCTIMING_TYPE_NTP},
+  {"urn:mpeg:dash:utc:sntp:2014", GST_MPD_UTCTIMING_TYPE_SNTP},
+  {"urn:mpeg:dash:utc:http-head:2014", GST_MPD_UTCTIMING_TYPE_HTTP_HEAD},
+  {"urn:mpeg:dash:utc:http-xsdate:2014", GST_MPD_UTCTIMING_TYPE_HTTP_XSDATE},
+  {"urn:mpeg:dash:utc:http-iso:2014", GST_MPD_UTCTIMING_TYPE_HTTP_ISO},
+  {"urn:mpeg:dash:utc:http-ntp:2014", GST_MPD_UTCTIMING_TYPE_HTTP_NTP},
+  {"urn:mpeg:dash:utc:direct:2014", GST_MPD_UTCTIMING_TYPE_DIRECT},
+  /*
+   * Early working drafts used the :2012 namespace and this namespace is
+   * used by some DASH packagers. To work-around these packagers, we also
+   * accept the early draft scheme names.
+   */
+  {"urn:mpeg:dash:utc:ntp:2012", GST_MPD_UTCTIMING_TYPE_NTP},
+  {"urn:mpeg:dash:utc:sntp:2012", GST_MPD_UTCTIMING_TYPE_SNTP},
+  {"urn:mpeg:dash:utc:http-head:2012", GST_MPD_UTCTIMING_TYPE_HTTP_HEAD},
+  {"urn:mpeg:dash:utc:http-xsdate:2012", GST_MPD_UTCTIMING_TYPE_HTTP_XSDATE},
+  {"urn:mpeg:dash:utc:http-iso:2012", GST_MPD_UTCTIMING_TYPE_HTTP_ISO},
+  {"urn:mpeg:dash:utc:http-ntp:2012", GST_MPD_UTCTIMING_TYPE_HTTP_NTP},
+  {"urn:mpeg:dash:utc:direct:2012", GST_MPD_UTCTIMING_TYPE_DIRECT},
+  {NULL, 0}
+};
+
 static void
 gst_mpd_utctiming_node_finalize (GObject * object)
 {
@@ -40,11 +63,42 @@ gst_mpd_utctiming_node_finalize (GObject * object)
   G_OBJECT_CLASS (gst_mpd_utctiming_node_parent_class)->finalize (object);
 }
 
+/* Base class */
+
+static xmlNodePtr
+gst_mpd_utc_timing_get_xml_node (GstMPDNode * node)
+{
+  xmlNodePtr utc_timing_xml_node = NULL;
+  gchar *value = NULL;
+  GstMPDUTCTimingNode *self = GST_MPD_UTCTIMING_NODE (node);
+
+  utc_timing_xml_node = xmlNewNode (NULL, (xmlChar *) "UTCTiming");
+
+  if (self->method) {
+    gst_xml_helper_set_prop_string (utc_timing_xml_node, "schemeiduri",
+        (gchar *) gst_mpd_utctiming_get_scheme_id_uri (self->method));
+  }
+  if (self->urls) {
+    value = g_strjoinv (" ", self->urls);
+    gst_xml_helper_set_prop_string (utc_timing_xml_node, "value", value);
+    g_free (value);
+  }
+
+  return utc_timing_xml_node;
+}
+
 static void
 gst_mpd_utctiming_node_class_init (GstMPDUTCTimingNodeClass * klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GObjectClass *object_class;
+  GstMPDNodeClass *m_klass;
+
+  object_class = G_OBJECT_CLASS (klass);
+  m_klass = GST_MPD_NODE_CLASS (klass);
+
   object_class->finalize = gst_mpd_utctiming_node_finalize;
+
+  m_klass->get_xml_node = gst_mpd_utc_timing_get_xml_node;
 }
 
 static void
@@ -66,3 +120,26 @@ gst_mpd_utctiming_node_free (GstMPDUTCTimingNode * self)
   if (self)
     gst_object_unref (self);
 }
+
+const gchar *
+gst_mpd_utctiming_get_scheme_id_uri (GstMPDUTCTimingType type)
+{
+  int i;
+  for (i = 0; gst_mpd_utctiming_methods[i].name; ++i) {
+    if (type == gst_mpd_utctiming_methods[i].method)
+      return gst_mpd_utctiming_methods[i].name;
+  }
+  return NULL;
+}
+
+GstMPDUTCTimingType
+gst_mpd_utctiming_get_method (gchar * schemeIDURI)
+{
+  int i;
+  for (i = 0; gst_mpd_utctiming_methods[i].name; ++i) {
+    if (g_ascii_strncasecmp (gst_mpd_utctiming_methods[i].name,
+            schemeIDURI, strlen (gst_mpd_utctiming_methods[i].name)) == 0)
+      return gst_mpd_utctiming_methods[i].method;
+  }
+  return GST_MPD_UTCTIMING_TYPE_UNKNOWN;
+}
index 42b5fec..32cd98d 100644 (file)
 #define __GSTMPDUTCTIMINGNODE_H__
 
 #include <gst/gst.h>
-#include "gstxmlhelper.h"
+#include "gstmpdnode.h"
 
 G_BEGIN_DECLS
 
 #define GST_TYPE_MPD_UTCTIMING_NODE gst_mpd_utctiming_node_get_type ()
-#define GST_MPD_UTCTIMING_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MPD_UTCTIMING_NODE, GstMPDUTCTimingNode))
-#define GST_MPD_UTCTIMING_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MPD_UTCTIMING_NODE, GstMPDUTCTimingNodeClass))
-#define GST_IS_MPD_UTCTIMING_NODE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MPD_UTCTIMING_NODE))
-#define GST_IS_MPD_UTCTIMING_NODE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MPD_UTCTIMING_NODE))
-#define GST_MPD_UTCTIMING_NODE_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MPD_UTCTIMING_NODE, GstMPDUTCTimingNodeClass))
-
-typedef struct _GstMPDUTCTimingNode                GstMPDUTCTimingNode;
-typedef struct _GstMPDUTCTimingNodeClass           GstMPDUTCTimingNodeClass;
-
+G_DECLARE_FINAL_TYPE (GstMPDUTCTimingNode, gst_mpd_utctiming_node, GST, MPD_UTCTIMING_NODE, GstMPDNode)
 
 typedef enum
 {
@@ -54,6 +41,12 @@ typedef enum
   GST_MPD_UTCTIMING_TYPE_DIRECT      = 0x40
 } GstMPDUTCTimingType;
 
+struct GstMPDUTCTimingMethod
+{
+  const gchar *name;
+  GstMPDUTCTimingType method;
+};
+
 struct _GstMPDUTCTimingNode
 {
   GstObject parent_instance;
@@ -63,16 +56,13 @@ struct _GstMPDUTCTimingNode
   /* TODO add missing fields such as weight etc.*/
 };
 
-struct _GstMPDUTCTimingNodeClass {
-  GstObjectClass parent_class;
-};
-
-
-G_GNUC_INTERNAL GType gst_mpd_utctiming_node_get_type (void);
 
 GstMPDUTCTimingNode * gst_mpd_utctiming_node_new (void);
 void gst_mpd_utctiming_node_free (GstMPDUTCTimingNode* self);
 
+const gchar* gst_mpd_utctiming_get_scheme_id_uri (GstMPDUTCTimingType type);
+GstMPDUTCTimingType gst_mpd_utctiming_get_method (gchar* schemeIDURI);
+
 G_END_DECLS
 
 #endif /* __GSTMPDUTCTIMINGNODE_H__ */
index ff97981..c59c57d 100644 (file)
 
 #include "gstxmlhelper.h"
 
+#define XML_HELPER_MINUTE_TO_SEC       60
+#define XML_HELPER_HOUR_TO_SEC         (60 * XML_HELPER_MINUTE_TO_SEC)
+#define XML_HELPER_DAY_TO_SEC          (24 * XML_HELPER_HOUR_TO_SEC)
+#define XML_HELPER_MONTH_TO_SEC        (30 * XML_HELPER_DAY_TO_SEC)
+#define XML_HELPER_YEAR_TO_SEC         (365 * XML_HELPER_DAY_TO_SEC)
+#define XML_HELPER_MS_TO_SEC(time)     ((time) / 1000)
 /* static methods */
 /* this function computes decimals * 10 ^ (3 - pos) */
 static guint
@@ -295,6 +301,34 @@ gst_xml_helper_clone_range (GstXMLRange * range)
   return clone;
 }
 
+GstXMLRatio *
+gst_xml_helper_clone_ratio (GstXMLRatio * ratio)
+{
+  GstXMLRatio *clone = NULL;
+
+  if (ratio) {
+    clone = g_slice_new0 (GstXMLRatio);
+    clone->num = ratio->num;
+    clone->den = ratio->den;
+  }
+
+  return clone;
+}
+
+GstXMLFrameRate *
+gst_xml_helper_clone_frame_rate (GstXMLFrameRate * frameRate)
+{
+  GstXMLFrameRate *clone = NULL;
+
+  if (frameRate) {
+    clone = g_slice_new0 (GstXMLFrameRate);
+    clone->num = frameRate->num;
+    clone->den = frameRate->den;
+  }
+
+  return clone;
+}
+
 /* XML property get method */
 gboolean
 gst_xml_helper_get_prop_validated_string (xmlNode * a_node,
@@ -1022,3 +1056,204 @@ gst_xml_helper_get_prop_string_no_whitespace (xmlNode * a_node,
   return gst_xml_helper_get_prop_validated_string (a_node, property_name,
       property_value, _mpd_helper_validate_no_whitespace);
 }
+
+
+/* XML property set method */
+
+void
+gst_xml_helper_set_prop_string (xmlNodePtr node, const gchar * name,
+    gchar * value)
+{
+  if (value)
+    xmlSetProp (node, (xmlChar *) name, (xmlChar *) value);
+}
+
+void
+gst_xml_helper_set_prop_boolean (xmlNodePtr node, const gchar * name,
+    gboolean value)
+{
+  if (value)
+    xmlSetProp (node, (xmlChar *) name, (xmlChar *) "true");
+  else
+    xmlSetProp (node, (xmlChar *) name, (xmlChar *) "false");
+}
+
+void
+gst_xml_helper_set_prop_int (xmlNodePtr node, const gchar * name, gint value)
+{
+  gchar *text;
+  text = g_strdup_printf ("%d", value);
+  xmlSetProp (node, (xmlChar *) name, (xmlChar *) text);
+  g_free (text);
+}
+
+void
+gst_xml_helper_set_prop_uint (xmlNodePtr node, const gchar * name, guint value)
+{
+  gchar *text;
+  text = g_strdup_printf ("%d", value);
+  xmlSetProp (node, (xmlChar *) name, (xmlChar *) text);
+  g_free (text);
+}
+
+void
+gst_xml_helper_set_prop_int64 (xmlNodePtr node, const gchar * name,
+    gint64 value)
+{
+  gchar *text;
+  text = g_strdup_printf ("%" G_GINT64_FORMAT, value);
+  xmlSetProp (node, (xmlChar *) name, (xmlChar *) text);
+  g_free (text);
+}
+
+void
+gst_xml_helper_set_prop_uint64 (xmlNodePtr node, const gchar * name,
+    guint64 value)
+{
+  gchar *text;
+  text = g_strdup_printf ("%" G_GUINT64_FORMAT, value);
+  xmlSetProp (node, (xmlChar *) name, (xmlChar *) text);
+  g_free (text);
+}
+
+void
+gst_xml_helper_set_prop_double (xmlNodePtr node, const gchar * name,
+    gdouble value)
+{
+  gchar *text;
+  text = g_strdup_printf ("%lf", value);
+  xmlSetProp (node, (xmlChar *) name, (xmlChar *) text);
+  g_free (text);
+}
+
+void
+gst_xml_helper_set_prop_uint_vector_type (xmlNode * node, const gchar * name,
+    guint * value, guint value_size)
+{
+  int i;
+  gchar *text = NULL;
+  gchar *prev;
+  gchar *temp;
+
+  for (i = 0; i < value_size; i++) {
+    temp = g_strdup_printf ("%d", value[i]);
+    prev = text;
+    text = g_strjoin (" ", text, prev, NULL);
+    g_free (prev);
+    g_free (temp);
+  }
+
+  if (text) {
+    xmlSetProp (node, (xmlChar *) name, (xmlChar *) text);
+    g_free (text);
+  }
+}
+
+void
+gst_xml_helper_set_prop_date_time (xmlNodePtr node, const gchar * name,
+    GstDateTime * value)
+{
+  gchar *text;
+  if (value) {
+    text = gst_date_time_to_iso8601_string (value);
+    xmlSetProp (node, (xmlChar *) name, (xmlChar *) text);
+    g_free (text);
+  }
+}
+
+void
+gst_xml_helper_set_prop_duration (xmlNode * node, const gchar * name,
+    guint64 value)
+{
+  gchar *text;
+  gint years, months, days, hours, minutes, seconds, milliseconds;
+  if (value) {
+    years = (gint) (XML_HELPER_MS_TO_SEC (value) / (XML_HELPER_YEAR_TO_SEC));
+    months =
+        (gint) ((XML_HELPER_MS_TO_SEC (value) % XML_HELPER_YEAR_TO_SEC) /
+        XML_HELPER_MONTH_TO_SEC);
+    days =
+        (gint) ((XML_HELPER_MS_TO_SEC (value) % XML_HELPER_MONTH_TO_SEC) /
+        XML_HELPER_DAY_TO_SEC);
+    hours =
+        (gint) ((XML_HELPER_MS_TO_SEC (value) % XML_HELPER_DAY_TO_SEC) /
+        XML_HELPER_HOUR_TO_SEC);
+    minutes =
+        (gint) ((XML_HELPER_MS_TO_SEC (value) % XML_HELPER_HOUR_TO_SEC) /
+        XML_HELPER_MINUTE_TO_SEC);
+    seconds = (gint) (XML_HELPER_MS_TO_SEC (value) % XML_HELPER_MINUTE_TO_SEC);
+    milliseconds = value % 1000;
+
+    text =
+        g_strdup_printf ("P%dY%dM%dDT%dH%dM%d.%dS", years, months, days, hours,
+        minutes, seconds, milliseconds);
+    GST_LOG ("duration %" G_GUINT64_FORMAT " -> %s", value, text);
+    xmlSetProp (node, (xmlChar *) name, (xmlChar *) text);
+    g_free (text);
+  }
+}
+
+void
+gst_xml_helper_set_prop_ratio (xmlNodePtr node, const gchar * name,
+    GstXMLRatio * value)
+{
+  gchar *text;
+  if (value) {
+    text = g_strdup_printf ("%d:%d", value->num, value->den);
+    xmlSetProp (node, (xmlChar *) name, (xmlChar *) text);
+    g_free (text);
+  }
+}
+
+
+void
+gst_xml_helper_set_prop_framerate (xmlNodePtr node, const gchar * name,
+    GstXMLFrameRate * value)
+{
+  gchar *text;
+  if (value) {
+    text = g_strdup_printf ("%d/%d", value->num, value->den);
+    xmlSetProp (node, (xmlChar *) name, (xmlChar *) text);
+    g_free (text);
+  }
+}
+
+void
+gst_xml_helper_set_prop_range (xmlNodePtr node, const gchar * name,
+    GstXMLRange * value)
+{
+  gchar *text;
+  if (value) {
+    text =
+        g_strdup_printf ("%" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT,
+        value->first_byte_pos, value->last_byte_pos);
+    xmlSetProp (node, (xmlChar *) name, (xmlChar *) text);
+    g_free (text);
+  }
+}
+
+void
+gst_xml_helper_set_prop_cond_uint (xmlNodePtr node, const gchar * name,
+    GstXMLConditionalUintType * cond)
+{
+  gchar *text;
+  if (cond) {
+    if (cond->flag)
+      if (cond->value)
+        text = g_strdup_printf ("%d", cond->value);
+      else
+        text = g_strdup_printf ("%s", "true");
+    else
+      text = g_strdup_printf ("%s", "false");
+
+    xmlSetProp (node, (xmlChar *) name, (xmlChar *) text);
+    g_free (text);
+  }
+}
+
+void
+gst_xml_helper_set_content (xmlNodePtr node, gchar * content)
+{
+  if (content)
+    xmlNodeSetContent (node, (xmlChar *) content);
+}
index ce9de9a..af3e8ff 100644 (file)
@@ -57,6 +57,8 @@ struct _GstXMLConditionalUintType
 };
 
 GstXMLRange *gst_xml_helper_clone_range (GstXMLRange * range);
+GstXMLRatio *gst_xml_helper_clone_ratio (GstXMLRatio * ratio);
+GstXMLFrameRate *gst_xml_helper_clone_frame_rate (GstXMLFrameRate * frameRate);
 
 /* XML property get method */
 gboolean gst_xml_helper_get_prop_validated_string (xmlNode * a_node,
@@ -109,5 +111,22 @@ gchar *gst_xml_helper_get_node_namespace (xmlNode * a_node,
 gboolean gst_xml_helper_get_node_as_string (xmlNode * a_node,
     gchar ** content);
 
+/* XML property set method */
+void gst_xml_helper_set_prop_string (xmlNodePtr node, const gchar * name, gchar* value);
+void gst_xml_helper_set_prop_boolean (xmlNodePtr node, const gchar * name, gboolean value);
+void gst_xml_helper_set_prop_int (xmlNodePtr root, const gchar * name, gint value);
+void gst_xml_helper_set_prop_uint (xmlNodePtr root, const gchar * name, guint value);
+void gst_xml_helper_set_prop_int64 (xmlNodePtr node, const gchar * name, gint64 value);
+void gst_xml_helper_set_prop_uint64 (xmlNodePtr node, const gchar * name, guint64 value);
+void gst_xml_helper_set_prop_uint_vector_type (xmlNode * a_node,  const gchar * name, guint * value, guint value_size);
+void gst_xml_helper_set_prop_double (xmlNodePtr node, const gchar * name, gdouble value);
+void gst_xml_helper_set_prop_date_time (xmlNodePtr node, const gchar * name, GstDateTime* value);
+void gst_xml_helper_set_prop_duration (xmlNode * node, const gchar * name, guint64 value);
+void gst_xml_helper_set_prop_ratio (xmlNodePtr node, const gchar * name, GstXMLRatio* value);
+void gst_xml_helper_set_prop_framerate (xmlNodePtr node, const gchar * name, GstXMLFrameRate* value);
+void gst_xml_helper_set_prop_range (xmlNodePtr node, const gchar * name, GstXMLRange* value);
+void gst_xml_helper_set_prop_cond_uint (xmlNode * a_node, const gchar * property_name, GstXMLConditionalUintType * cond);
+void gst_xml_helper_set_content (xmlNodePtr node, gchar * content);
+
 G_END_DECLS
 #endif /* __GST_XMLHELPER_H__ */
index 67779b2..56be535 100644 (file)
@@ -1,5 +1,6 @@
 dash_sources = [
   'gstdashdemux.c',
+  'gstmpdnode.c',
   'gstmpdrootnode.c',
   'gstmpdbaseurlnode.c',
   'gstmpdutctimingnode.c',
@@ -10,13 +11,20 @@ dash_sources = [
   'gstmpdsegmenttemplatenode.c',
   'gstmpdsegmenturlnode.c',
   'gstmpdsegmentlistnode.c',
+  'gstmpdsegmentbasenode.c',
   'gstmpdperiodnode.c',
+  'gstmpdrepresentationbasenode.c',
+  'gstmpdmultsegmentbasenode.c',
   'gstmpdrepresentationnode.c',
   'gstmpdsubrepresentationnode.c',
   'gstmpdcontentcomponentnode.c',
   'gstmpdadaptationsetnode.c',
   'gstmpdsubsetnode.c',
   'gstmpdprograminformationnode.c',
+  'gstmpdlocationnode.c',
+  'gstmpdreportingnode.c',
+  'gstmpdurltypenode.c',
+  'gstmpddescriptortypenode.c',
   'gstxmlhelper.c',
   'gstmpdhelper.c',
   'gstmpdparser.c',
index 8098013..e651054 100644 (file)
@@ -21,6 +21,9 @@
 #include "../../ext/dash/gstmpdparser.c"
 #include "../../ext/dash/gstxmlhelper.c"
 #include "../../ext/dash/gstmpdhelper.c"
+#include "../../ext/dash/gstmpdnode.c"
+#include "../../ext/dash/gstmpdrepresentationbasenode.c"
+#include "../../ext/dash/gstmpdmultsegmentbasenode.c"
 #include "../../ext/dash/gstmpdrootnode.c"
 #include "../../ext/dash/gstmpdbaseurlnode.c"
 #include "../../ext/dash/gstmpdutctimingnode.c"
@@ -31,6 +34,7 @@
 #include "../../ext/dash/gstmpdsegmenttemplatenode.c"
 #include "../../ext/dash/gstmpdsegmenturlnode.c"
 #include "../../ext/dash/gstmpdsegmentlistnode.c"
+#include "../../ext/dash/gstmpdsegmentbasenode.c"
 #include "../../ext/dash/gstmpdperiodnode.c"
 #include "../../ext/dash/gstmpdsubrepresentationnode.c"
 #include "../../ext/dash/gstmpdrepresentationnode.c"
 #include "../../ext/dash/gstmpdadaptationsetnode.c"
 #include "../../ext/dash/gstmpdsubsetnode.c"
 #include "../../ext/dash/gstmpdprograminformationnode.c"
+#include "../../ext/dash/gstmpdlocationnode.c"
+#include "../../ext/dash/gstmpdreportingnode.c"
+#include "../../ext/dash/gstmpdurltypenode.c"
+#include "../../ext/dash/gstmpddescriptortypenode.c"
 #include "../../ext/dash/gstmpdclient.c"
 #undef GST_CAT_DEFAULT
 
@@ -212,8 +220,8 @@ GST_START_TEST (dash_mpdparser_programInformation)
   assert_equals_int (ret, TRUE);
 
   program =
-      (GstMPDProgramInformationNode *) mpdclient->mpd_root_node->
-      ProgramInfos->data;
+      (GstMPDProgramInformationNode *) mpdclient->mpd_root_node->ProgramInfos->
+      data;
   assert_equals_string (program->lang, "en");
   assert_equals_string (program->moreInformationURL, "TestMoreInformationUrl");
   assert_equals_string (program->Title, "TestTitle");
@@ -261,7 +269,7 @@ GST_END_TEST;
  */
 GST_START_TEST (dash_mpdparser_location)
 {
-  const gchar *location;
+  GstMPDLocationNode *location;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -274,8 +282,8 @@ GST_START_TEST (dash_mpdparser_location)
   ret = gst_mpd_client_parse (mpdclient, xml, (gint) strlen (xml));
   assert_equals_int (ret, TRUE);
 
-  location = (gchar *) mpdclient->mpd_root_node->Locations->data;
-  assert_equals_string (location, "TestLocation");
+  location = (GstMPDLocationNode *) mpdclient->mpd_root_node->Locations->data;
+  assert_equals_string (location->location, "TestLocation");
 
   gst_mpd_client_free (mpdclient);
 }
@@ -449,7 +457,7 @@ GST_END_TEST;
 GST_START_TEST (dash_mpdparser_period_segmentBase)
 {
   GstMPDPeriodNode *periodNode;
-  GstMPDSegmentBaseType *segmentBase;
+  GstMPDSegmentBaseNode *segmentBase;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -487,8 +495,8 @@ GST_END_TEST;
 GST_START_TEST (dash_mpdparser_period_segmentBase_initialization)
 {
   GstMPDPeriodNode *periodNode;
-  GstMPDSegmentBaseType *segmentBase;
-  GstMPDURLType *initialization;
+  GstMPDSegmentBaseNode *segmentBase;
+  GstMPDURLTypeNode *initialization;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -524,8 +532,8 @@ GST_END_TEST;
 GST_START_TEST (dash_mpdparser_period_segmentBase_representationIndex)
 {
   GstMPDPeriodNode *periodNode;
-  GstMPDSegmentBaseType *segmentBase;
-  GstMPDURLType *representationIndex;
+  GstMPDSegmentBaseNode *segmentBase;
+  GstMPDURLTypeNode *representationIndex;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -591,7 +599,7 @@ GST_START_TEST (dash_mpdparser_period_segmentList_multipleSegmentBaseType)
 {
   GstMPDPeriodNode *periodNode;
   GstMPDSegmentListNode *segmentList;
-  GstMPDMultSegmentBaseType *multSegBaseType;
+
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -609,9 +617,11 @@ GST_START_TEST (dash_mpdparser_period_segmentList_multipleSegmentBaseType)
 
   periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
   segmentList = periodNode->SegmentList;
-  multSegBaseType = segmentList->MultSegBaseType;
-  assert_equals_uint64 (multSegBaseType->duration, 10);
-  assert_equals_uint64 (multSegBaseType->startNumber, 11);
+
+  assert_equals_uint64 (GST_MPD_MULT_SEGMENT_BASE_NODE (segmentList)->duration,
+      10);
+  assert_equals_uint64 (GST_MPD_MULT_SEGMENT_BASE_NODE
+      (segmentList)->startNumber, 11);
 
   gst_mpd_client_free (mpdclient);
 }
@@ -627,8 +637,7 @@ GST_START_TEST
 {
   GstMPDPeriodNode *periodNode;
   GstMPDSegmentListNode *segmentList;
-  GstMPDMultSegmentBaseType *multSegBaseType;
-  GstMPDSegmentBaseType *segBaseType;
+  GstMPDSegmentBaseNode *segmentBase;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -649,13 +658,12 @@ GST_START_TEST
 
   periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
   segmentList = periodNode->SegmentList;
-  multSegBaseType = segmentList->MultSegBaseType;
-  segBaseType = multSegBaseType->SegBaseType;
-  assert_equals_uint64 (segBaseType->timescale, 10);
-  assert_equals_uint64 (segBaseType->presentationTimeOffset, 11);
-  assert_equals_uint64 (segBaseType->indexRange->first_byte_pos, 20);
-  assert_equals_uint64 (segBaseType->indexRange->last_byte_pos, 21);
-  assert_equals_int (segBaseType->indexRangeExact, FALSE);
+  segmentBase = GST_MPD_MULT_SEGMENT_BASE_NODE (segmentList)->SegmentBase;
+  assert_equals_uint64 (segmentBase->timescale, 10);
+  assert_equals_uint64 (segmentBase->presentationTimeOffset, 11);
+  assert_equals_uint64 (segmentBase->indexRange->first_byte_pos, 20);
+  assert_equals_uint64 (segmentBase->indexRange->last_byte_pos, 21);
+  assert_equals_int (segmentBase->indexRangeExact, FALSE);
 
   gst_mpd_client_free (mpdclient);
 }
@@ -671,7 +679,6 @@ GST_START_TEST
 {
   GstMPDPeriodNode *periodNode;
   GstMPDSegmentListNode *segmentList;
-  GstMPDMultSegmentBaseType *multSegBaseType;
   GstMPDSegmentTimelineNode *segmentTimeline;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
@@ -690,8 +697,8 @@ GST_START_TEST
 
   periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
   segmentList = periodNode->SegmentList;
-  multSegBaseType = segmentList->MultSegBaseType;
-  segmentTimeline = multSegBaseType->SegmentTimeline;
+  segmentTimeline =
+      GST_MPD_MULT_SEGMENT_BASE_NODE (segmentList)->SegmentTimeline;
   fail_if (segmentTimeline == NULL);
 
   gst_mpd_client_free (mpdclient);
@@ -708,7 +715,6 @@ GST_START_TEST
 {
   GstMPDPeriodNode *periodNode;
   GstMPDSegmentListNode *segmentList;
-  GstMPDMultSegmentBaseType *multSegBaseType;
   GstMPDSegmentTimelineNode *segmentTimeline;
   GstMPDSNode *sNode;
   const gchar *xml =
@@ -729,8 +735,8 @@ GST_START_TEST
 
   periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
   segmentList = periodNode->SegmentList;
-  multSegBaseType = segmentList->MultSegBaseType;
-  segmentTimeline = multSegBaseType->SegmentTimeline;
+  segmentTimeline =
+      GST_MPD_MULT_SEGMENT_BASE_NODE (segmentList)->SegmentTimeline;
   sNode = (GstMPDSNode *) g_queue_peek_head (&segmentTimeline->S);
   assert_equals_uint64 (sNode->t, 1);
   assert_equals_uint64 (sNode->d, 2);
@@ -750,8 +756,7 @@ GST_START_TEST
 {
   GstMPDPeriodNode *periodNode;
   GstMPDSegmentListNode *segmentList;
-  GstMPDMultSegmentBaseType *multSegBaseType;
-  GstMPDURLType *bitstreamSwitching;
+  GstMPDURLTypeNode *bitstreamSwitching;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -770,8 +775,9 @@ GST_START_TEST
 
   periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
   segmentList = periodNode->SegmentList;
-  multSegBaseType = segmentList->MultSegBaseType;
-  bitstreamSwitching = multSegBaseType->BitstreamSwitching;
+
+  bitstreamSwitching =
+      GST_MPD_MULT_SEGMENT_BASE_NODE (segmentList)->BitstreamSwitching;
   assert_equals_string (bitstreamSwitching->sourceURL, "TestSourceURL");
   assert_equals_uint64 (bitstreamSwitching->range->first_byte_pos, 100);
   assert_equals_uint64 (bitstreamSwitching->range->last_byte_pos, 200);
@@ -962,7 +968,6 @@ GST_START_TEST (dash_mpdparser_period_segmentTemplate_multipleSegmentBaseType)
 {
   GstMPDPeriodNode *periodNode;
   GstMPDSegmentTemplateNode *segmentTemplate;
-  GstMPDMultSegmentBaseType *multSegBaseType;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -980,9 +985,11 @@ GST_START_TEST (dash_mpdparser_period_segmentTemplate_multipleSegmentBaseType)
 
   periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
   segmentTemplate = periodNode->SegmentTemplate;
-  multSegBaseType = segmentTemplate->MultSegBaseType;
-  assert_equals_uint64 (multSegBaseType->duration, 10);
-  assert_equals_uint64 (multSegBaseType->startNumber, 11);
+
+  assert_equals_uint64 (GST_MPD_MULT_SEGMENT_BASE_NODE
+      (segmentTemplate)->duration, 10);
+  assert_equals_uint64 (GST_MPD_MULT_SEGMENT_BASE_NODE
+      (segmentTemplate)->startNumber, 11);
 
   gst_mpd_client_free (mpdclient);
 }
@@ -998,8 +1005,7 @@ GST_START_TEST
 {
   GstMPDPeriodNode *periodNode;
   GstMPDSegmentTemplateNode *segmentTemplate;
-  GstMPDMultSegmentBaseType *multSegBaseType;
-  GstMPDSegmentBaseType *segBaseType;
+  GstMPDSegmentBaseNode *segmentBase;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -1020,13 +1026,12 @@ GST_START_TEST
 
   periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
   segmentTemplate = periodNode->SegmentTemplate;
-  multSegBaseType = segmentTemplate->MultSegBaseType;
-  segBaseType = multSegBaseType->SegBaseType;
-  assert_equals_uint64 (segBaseType->timescale, 123456);
-  assert_equals_uint64 (segBaseType->presentationTimeOffset, 123456789);
-  assert_equals_uint64 (segBaseType->indexRange->first_byte_pos, 100);
-  assert_equals_uint64 (segBaseType->indexRange->last_byte_pos, 200);
-  assert_equals_int (segBaseType->indexRangeExact, TRUE);
+  segmentBase = GST_MPD_MULT_SEGMENT_BASE_NODE (segmentTemplate)->SegmentBase;
+  assert_equals_uint64 (segmentBase->timescale, 123456);
+  assert_equals_uint64 (segmentBase->presentationTimeOffset, 123456789);
+  assert_equals_uint64 (segmentBase->indexRange->first_byte_pos, 100);
+  assert_equals_uint64 (segmentBase->indexRange->last_byte_pos, 200);
+  assert_equals_int (segmentBase->indexRangeExact, TRUE);
 
   gst_mpd_client_free (mpdclient);
 }
@@ -1042,7 +1047,6 @@ GST_START_TEST
 {
   GstMPDPeriodNode *periodNode;
   GstMPDSegmentTemplateNode *segmentTemplate;
-  GstMPDMultSegmentBaseType *multSegBaseType;
   GstMPDSegmentTimelineNode *segmentTimeline;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
@@ -1061,9 +1065,9 @@ GST_START_TEST
 
   periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
   segmentTemplate = periodNode->SegmentTemplate;
-  multSegBaseType = segmentTemplate->MultSegBaseType;
-  segmentTimeline =
-      (GstMPDSegmentTimelineNode *) multSegBaseType->SegmentTimeline;
+
+  segmentTimeline = (GstMPDSegmentTimelineNode *)
+      GST_MPD_MULT_SEGMENT_BASE_NODE (segmentTemplate)->SegmentTimeline;
   fail_if (segmentTimeline == NULL);
 
   gst_mpd_client_free (mpdclient);
@@ -1080,7 +1084,6 @@ GST_START_TEST
 {
   GstMPDPeriodNode *periodNode;
   GstMPDSegmentTemplateNode *segmentTemplate;
-  GstMPDMultSegmentBaseType *multSegBaseType;
   GstMPDSegmentTimelineNode *segmentTimeline;
   GstMPDSNode *sNode;
   const gchar *xml =
@@ -1101,9 +1104,8 @@ GST_START_TEST
 
   periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
   segmentTemplate = periodNode->SegmentTemplate;
-  multSegBaseType = segmentTemplate->MultSegBaseType;
-  segmentTimeline =
-      (GstMPDSegmentTimelineNode *) multSegBaseType->SegmentTimeline;
+  segmentTimeline = (GstMPDSegmentTimelineNode *)
+      GST_MPD_MULT_SEGMENT_BASE_NODE (segmentTemplate)->SegmentTimeline;
   sNode = (GstMPDSNode *) g_queue_peek_head (&segmentTimeline->S);
   assert_equals_uint64 (sNode->t, 1);
   assert_equals_uint64 (sNode->d, 2);
@@ -1123,8 +1125,7 @@ GST_START_TEST
 {
   GstMPDPeriodNode *periodNode;
   GstMPDSegmentTemplateNode *segmentTemplate;
-  GstMPDMultSegmentBaseType *multSegBaseType;
-  GstMPDURLType *bitstreamSwitching;
+  GstMPDURLTypeNode *bitstreamSwitching;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -1143,8 +1144,8 @@ GST_START_TEST
 
   periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
   segmentTemplate = periodNode->SegmentTemplate;
-  multSegBaseType = segmentTemplate->MultSegBaseType;
-  bitstreamSwitching = multSegBaseType->BitstreamSwitching;
+  bitstreamSwitching =
+      GST_MPD_MULT_SEGMENT_BASE_NODE (segmentTemplate)->BitstreamSwitching;
   assert_equals_string (bitstreamSwitching->sourceURL, "TestSourceURL");
   assert_equals_uint64 (bitstreamSwitching->range->first_byte_pos, 100);
   assert_equals_uint64 (bitstreamSwitching->range->last_byte_pos, 200);
@@ -1206,14 +1207,14 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet)
   assert_equals_uint64 (adaptationSet->maxWidth, 2000);
   assert_equals_uint64 (adaptationSet->minHeight, 1100);
   assert_equals_uint64 (adaptationSet->maxHeight, 2100);
-  assert_equals_uint64 (adaptationSet->RepresentationBase->minFrameRate->num,
-      25);
-  assert_equals_uint64 (adaptationSet->RepresentationBase->minFrameRate->den,
-      123);
-  assert_equals_uint64 (adaptationSet->RepresentationBase->maxFrameRate->num,
-      26);
-  assert_equals_uint64 (adaptationSet->RepresentationBase->maxFrameRate->den,
-      1);
+  assert_equals_uint64 (GST_MPD_REPRESENTATION_BASE_NODE
+      (adaptationSet)->minFrameRate->num, 25);
+  assert_equals_uint64 (GST_MPD_REPRESENTATION_BASE_NODE
+      (adaptationSet)->minFrameRate->den, 123);
+  assert_equals_uint64 (GST_MPD_REPRESENTATION_BASE_NODE
+      (adaptationSet)->maxFrameRate->num, 26);
+  assert_equals_uint64 (GST_MPD_REPRESENTATION_BASE_NODE
+      (adaptationSet)->maxFrameRate->den, 1);
   assert_equals_int (adaptationSet->segmentAlignment->flag, 1);
   assert_equals_uint64 (adaptationSet->segmentAlignment->value, 2);
   assert_equals_int (adaptationSet->subsegmentAlignment->flag, 0);
@@ -1234,7 +1235,7 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet_representationBase)
 {
   GstMPDPeriodNode *periodNode;
   GstMPDAdaptationSetNode *adaptationSet;
-  GstMPDRepresentationBaseType *representationBase;
+  GstMPDRepresentationBaseNode *representationBase;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -1264,7 +1265,7 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet_representationBase)
 
   periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
   adaptationSet = (GstMPDAdaptationSetNode *) periodNode->AdaptationSets->data;
-  representationBase = adaptationSet->RepresentationBase;
+  representationBase = GST_MPD_REPRESENTATION_BASE_NODE (adaptationSet);
   assert_equals_string (representationBase->profiles, "TestProfiles");
   assert_equals_uint64 (representationBase->width, 100);
   assert_equals_uint64 (representationBase->height, 200);
@@ -1297,8 +1298,8 @@ GST_START_TEST
     (dash_mpdparser_period_adaptationSet_representationBase_framePacking) {
   GstMPDPeriodNode *periodNode;
   GstMPDAdaptationSetNode *adaptationSet;
-  GstMPDRepresentationBaseType *representationBase;
-  GstMPDDescriptorType *framePacking;
+  GstMPDRepresentationBaseNode *representationBase;
+  GstMPDDescriptorTypeNode *framePacking;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -1317,9 +1318,9 @@ GST_START_TEST
 
   periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
   adaptationSet = (GstMPDAdaptationSetNode *) periodNode->AdaptationSets->data;
-  representationBase = adaptationSet->RepresentationBase;
+  representationBase = GST_MPD_REPRESENTATION_BASE_NODE (adaptationSet);
   framePacking =
-      (GstMPDDescriptorType *) representationBase->FramePacking->data;
+      (GstMPDDescriptorTypeNode *) representationBase->FramePacking->data;
   assert_equals_string (framePacking->schemeIdUri, "TestSchemeIdUri");
   assert_equals_string (framePacking->value, "TestValue");
 
@@ -1337,8 +1338,8 @@ GST_START_TEST
 {
   GstMPDPeriodNode *periodNode;
   GstMPDAdaptationSetNode *adaptationSet;
-  GstMPDRepresentationBaseType *representationBase;
-  GstMPDDescriptorType *audioChannelConfiguration;
+  GstMPDRepresentationBaseNode *representationBase;
+  GstMPDDescriptorTypeNode *audioChannelConfiguration;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -1357,10 +1358,9 @@ GST_START_TEST
 
   periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
   adaptationSet = (GstMPDAdaptationSetNode *) periodNode->AdaptationSets->data;
-  representationBase = adaptationSet->RepresentationBase;
-  audioChannelConfiguration =
-      (GstMPDDescriptorType *) representationBase->
-      AudioChannelConfiguration->data;
+  representationBase = GST_MPD_REPRESENTATION_BASE_NODE (adaptationSet);
+  audioChannelConfiguration = (GstMPDDescriptorTypeNode *)
+      representationBase->AudioChannelConfiguration->data;
   assert_equals_string (audioChannelConfiguration->schemeIdUri,
       "TestSchemeIdUri");
   assert_equals_string (audioChannelConfiguration->value, "TestValue");
@@ -1378,8 +1378,8 @@ GST_START_TEST
     (dash_mpdparser_period_adaptationSet_representationBase_contentProtection) {
   GstMPDPeriodNode *periodNode;
   GstMPDAdaptationSetNode *adaptationSet;
-  GstMPDRepresentationBaseType *representationBase;
-  GstMPDDescriptorType *contentProtection;
+  GstMPDRepresentationBaseNode *representationBase;
+  GstMPDDescriptorTypeNode *contentProtection;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -1398,9 +1398,9 @@ GST_START_TEST
 
   periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
   adaptationSet = (GstMPDAdaptationSetNode *) periodNode->AdaptationSets->data;
-  representationBase = adaptationSet->RepresentationBase;
+  representationBase = GST_MPD_REPRESENTATION_BASE_NODE (adaptationSet);
   contentProtection =
-      (GstMPDDescriptorType *) representationBase->ContentProtection->data;
+      (GstMPDDescriptorTypeNode *) representationBase->ContentProtection->data;
   assert_equals_string (contentProtection->schemeIdUri, "TestSchemeIdUri");
   assert_equals_string (contentProtection->value, "TestValue");
 
@@ -1416,8 +1416,8 @@ GST_START_TEST (dash_mpdparser_contentProtection_no_value)
 {
   GstMPDPeriodNode *periodNode;
   GstMPDAdaptationSetNode *adaptationSet;
-  GstMPDRepresentationBaseType *representationBase;
-  GstMPDDescriptorType *contentProtection;
+  GstMPDRepresentationBaseNode *representationBase;
+  GstMPDDescriptorTypeNode *contentProtection;
   const gchar *xml =
       "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -1444,9 +1444,9 @@ GST_START_TEST (dash_mpdparser_contentProtection_no_value)
 
   periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
   adaptationSet = (GstMPDAdaptationSetNode *) periodNode->AdaptationSets->data;
-  representationBase = adaptationSet->RepresentationBase;
+  representationBase = GST_MPD_REPRESENTATION_BASE_NODE (adaptationSet);
   assert_equals_int (g_list_length (representationBase->ContentProtection), 3);
-  contentProtection = (GstMPDDescriptorType *)
+  contentProtection = (GstMPDDescriptorTypeNode *)
       g_list_nth (representationBase->ContentProtection, 1)->data;
   assert_equals_string (contentProtection->schemeIdUri,
       "urn:uuid:5e629af5-38da-4063-8977-97ffbd9902d4");
@@ -1479,8 +1479,8 @@ GST_START_TEST (dash_mpdparser_contentProtection_no_value_no_encoding)
 {
   GstMPDPeriodNode *periodNode;
   GstMPDAdaptationSetNode *adaptationSet;
-  GstMPDRepresentationBaseType *representationBase;
-  GstMPDDescriptorType *contentProtection;
+  GstMPDRepresentationBaseNode *representationBase;
+  GstMPDDescriptorTypeNode *contentProtection;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -1502,9 +1502,9 @@ GST_START_TEST (dash_mpdparser_contentProtection_no_value_no_encoding)
 
   periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
   adaptationSet = (GstMPDAdaptationSetNode *) periodNode->AdaptationSets->data;
-  representationBase = adaptationSet->RepresentationBase;
+  representationBase = GST_MPD_REPRESENTATION_BASE_NODE (adaptationSet);
   assert_equals_int (g_list_length (representationBase->ContentProtection), 2);
-  contentProtection = (GstMPDDescriptorType *)
+  contentProtection = (GstMPDDescriptorTypeNode *)
       g_list_nth (representationBase->ContentProtection, 1)->data;
   assert_equals_string (contentProtection->schemeIdUri,
       "urn:uuid:5e629af5-38da-4063-8977-97ffbd9902d4");
@@ -1522,7 +1522,7 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet_accessibility)
 {
   GstMPDPeriodNode *periodNode;
   GstMPDAdaptationSetNode *adaptationSet;
-  GstMPDDescriptorType *accessibility;
+  GstMPDDescriptorTypeNode *accessibility;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -1541,7 +1541,8 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet_accessibility)
 
   periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
   adaptationSet = (GstMPDAdaptationSetNode *) periodNode->AdaptationSets->data;
-  accessibility = (GstMPDDescriptorType *) adaptationSet->Accessibility->data;
+  accessibility =
+      (GstMPDDescriptorTypeNode *) adaptationSet->Accessibility->data;
   assert_equals_string (accessibility->schemeIdUri, "TestSchemeIdUri");
   assert_equals_string (accessibility->value, "TestValue");
 
@@ -1558,7 +1559,7 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet_role)
 {
   GstMPDPeriodNode *periodNode;
   GstMPDAdaptationSetNode *adaptationSet;
-  GstMPDDescriptorType *role;
+  GstMPDDescriptorTypeNode *role;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -1577,7 +1578,7 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet_role)
 
   periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
   adaptationSet = (GstMPDAdaptationSetNode *) periodNode->AdaptationSets->data;
-  role = (GstMPDDescriptorType *) adaptationSet->Role->data;
+  role = (GstMPDDescriptorTypeNode *) adaptationSet->Role->data;
   assert_equals_string (role->schemeIdUri, "TestSchemeIdUri");
   assert_equals_string (role->value, "TestValue");
 
@@ -1594,7 +1595,7 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet_rating)
 {
   GstMPDPeriodNode *periodNode;
   GstMPDAdaptationSetNode *adaptationSet;
-  GstMPDDescriptorType *rating;
+  GstMPDDescriptorTypeNode *rating;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -1613,7 +1614,7 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet_rating)
 
   periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
   adaptationSet = (GstMPDAdaptationSetNode *) periodNode->AdaptationSets->data;
-  rating = (GstMPDDescriptorType *) adaptationSet->Rating->data;
+  rating = (GstMPDDescriptorTypeNode *) adaptationSet->Rating->data;
   assert_equals_string (rating->schemeIdUri, "TestSchemeIdUri");
   assert_equals_string (rating->value, "TestValue");
 
@@ -1630,7 +1631,7 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet_viewpoint)
 {
   GstMPDPeriodNode *periodNode;
   GstMPDAdaptationSetNode *adaptationSet;
-  GstMPDDescriptorType *viewpoint;
+  GstMPDDescriptorTypeNode *viewpoint;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -1649,7 +1650,7 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet_viewpoint)
 
   periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
   adaptationSet = (GstMPDAdaptationSetNode *) periodNode->AdaptationSets->data;
-  viewpoint = (GstMPDDescriptorType *) adaptationSet->Viewpoint->data;
+  viewpoint = (GstMPDDescriptorTypeNode *) adaptationSet->Viewpoint->data;
   assert_equals_string (viewpoint->schemeIdUri, "TestSchemeIdUri");
   assert_equals_string (viewpoint->value, "TestValue");
 
@@ -1709,7 +1710,7 @@ GST_START_TEST
   GstMPDPeriodNode *periodNode;
   GstMPDAdaptationSetNode *adaptationSet;
   GstMPDContentComponentNode *contentComponent;
-  GstMPDDescriptorType *accessibility;
+  GstMPDDescriptorTypeNode *accessibility;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -1733,7 +1734,7 @@ GST_START_TEST
   contentComponent = (GstMPDContentComponentNode *)
       adaptationSet->ContentComponents->data;
   accessibility =
-      (GstMPDDescriptorType *) contentComponent->Accessibility->data;
+      (GstMPDDescriptorTypeNode *) contentComponent->Accessibility->data;
   assert_equals_string (accessibility->schemeIdUri, "TestSchemeIdUri");
   assert_equals_string (accessibility->value, "TestValue");
 
@@ -1751,7 +1752,7 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet_contentComponent_role)
   GstMPDPeriodNode *periodNode;
   GstMPDAdaptationSetNode *adaptationSet;
   GstMPDContentComponentNode *contentComponent;
-  GstMPDDescriptorType *role;
+  GstMPDDescriptorTypeNode *role;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -1773,7 +1774,7 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet_contentComponent_role)
   adaptationSet = (GstMPDAdaptationSetNode *) periodNode->AdaptationSets->data;
   contentComponent = (GstMPDContentComponentNode *)
       adaptationSet->ContentComponents->data;
-  role = (GstMPDDescriptorType *) contentComponent->Role->data;
+  role = (GstMPDDescriptorTypeNode *) contentComponent->Role->data;
   assert_equals_string (role->schemeIdUri, "TestSchemeIdUri");
   assert_equals_string (role->value, "TestValue");
 
@@ -1791,7 +1792,7 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet_contentComponent_rating)
   GstMPDPeriodNode *periodNode;
   GstMPDAdaptationSetNode *adaptationSet;
   GstMPDContentComponentNode *contentComponent;
-  GstMPDDescriptorType *rating;
+  GstMPDDescriptorTypeNode *rating;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -1814,7 +1815,7 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet_contentComponent_rating)
   adaptationSet = (GstMPDAdaptationSetNode *) periodNode->AdaptationSets->data;
   contentComponent = (GstMPDContentComponentNode *)
       adaptationSet->ContentComponents->data;
-  rating = (GstMPDDescriptorType *) contentComponent->Rating->data;
+  rating = (GstMPDDescriptorTypeNode *) contentComponent->Rating->data;
   assert_equals_string (rating->schemeIdUri, "TestSchemeIdUri");
   assert_equals_string (rating->value, "TestValue");
 
@@ -1832,7 +1833,7 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet_contentComponent_viewpoint)
   GstMPDPeriodNode *periodNode;
   GstMPDAdaptationSetNode *adaptationSet;
   GstMPDContentComponentNode *contentComponent;
-  GstMPDDescriptorType *viewpoint;
+  GstMPDDescriptorTypeNode *viewpoint;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -1855,7 +1856,7 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet_contentComponent_viewpoint)
   adaptationSet = (GstMPDAdaptationSetNode *) periodNode->AdaptationSets->data;
   contentComponent = (GstMPDContentComponentNode *)
       adaptationSet->ContentComponents->data;
-  viewpoint = (GstMPDDescriptorType *) contentComponent->Viewpoint->data;
+  viewpoint = (GstMPDDescriptorTypeNode *) contentComponent->Viewpoint->data;
   assert_equals_string (viewpoint->schemeIdUri, "TestSchemeIdUri");
   assert_equals_string (viewpoint->value, "TestValue");
 
@@ -1909,7 +1910,7 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet_segmentBase)
 {
   GstMPDPeriodNode *periodNode;
   GstMPDAdaptationSetNode *adaptationSet;
-  GstMPDSegmentBaseType *segmentBase;
+  GstMPDSegmentBaseNode *segmentBase;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -1950,8 +1951,8 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet_segmentBase_initialization)
 {
   GstMPDPeriodNode *periodNode;
   GstMPDAdaptationSetNode *adaptationSet;
-  GstMPDSegmentBaseType *segmentBase;
-  GstMPDURLType *initialization;
+  GstMPDSegmentBaseNode *segmentBase;
+  GstMPDURLTypeNode *initialization;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -1990,8 +1991,8 @@ GST_START_TEST
     (dash_mpdparser_period_adaptationSet_segmentBase_representationIndex) {
   GstMPDPeriodNode *periodNode;
   GstMPDAdaptationSetNode *adaptationSet;
-  GstMPDSegmentBaseType *segmentBase;
-  GstMPDURLType *representationIndex;
+  GstMPDSegmentBaseNode *segmentBase;
+  GstMPDURLTypeNode *representationIndex;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -2149,7 +2150,7 @@ GST_START_TEST
   GstMPDPeriodNode *periodNode;
   GstMPDAdaptationSetNode *adaptationSet;
   GstMPDRepresentationNode *representation;
-  GstMPDSegmentBaseType *segmentBase;
+  GstMPDSegmentBaseNode *segmentBase;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -2195,8 +2196,7 @@ GST_START_TEST (dash_mpdparser_adapt_repr_segmentTemplate_inherit)
   GstMPDAdaptationSetNode *adaptationSet;
   GstMPDSegmentTemplateNode *segmentTemplate;
   GstMPDRepresentationNode *representation;
-  GstMPDMultSegmentBaseType *multSegBaseType;
-  GstMPDSegmentBaseType *segBaseType;
+  GstMPDSegmentBaseNode *segmentBase;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -2221,12 +2221,13 @@ GST_START_TEST (dash_mpdparser_adapt_repr_segmentTemplate_inherit)
       adaptationSet->Representations->data;
   segmentTemplate = representation->SegmentTemplate;
   fail_if (segmentTemplate == NULL);
-  multSegBaseType = segmentTemplate->MultSegBaseType;
-  segBaseType = multSegBaseType->SegBaseType;
+  segmentBase = GST_MPD_MULT_SEGMENT_BASE_NODE (segmentTemplate)->SegmentBase;
 
-  assert_equals_uint64 (segBaseType->timescale, 12800);
-  assert_equals_uint64 (multSegBaseType->duration, 25600);
-  assert_equals_uint64 (multSegBaseType->startNumber, 1);
+  assert_equals_uint64 (segmentBase->timescale, 12800);
+  assert_equals_uint64 (GST_MPD_MULT_SEGMENT_BASE_NODE
+      (segmentTemplate)->duration, 25600);
+  assert_equals_uint64 (GST_MPD_MULT_SEGMENT_BASE_NODE
+      (segmentTemplate)->startNumber, 1);
   assert_equals_string (segmentTemplate->media, "track1_$Number$.m4s");
   assert_equals_string (segmentTemplate->initialization, "set1_init.mp4");
 
@@ -2334,7 +2335,7 @@ GST_START_TEST
   GstMPDPeriodNode *periodNode;
   GstMPDAdaptationSetNode *adaptationSet;
   GstMPDRepresentationNode *representation;
-  GstMPDRepresentationBaseType *representationBase;
+
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -2354,9 +2355,8 @@ GST_START_TEST
   adaptationSet = (GstMPDAdaptationSetNode *) periodNode->AdaptationSets->data;
   representation = (GstMPDRepresentationNode *)
       adaptationSet->Representations->data;
-  representationBase = (GstMPDRepresentationBaseType *)
-      representation->RepresentationBase;
-  fail_if (representationBase == NULL);
+
+  fail_if (representation == NULL);
 
   gst_mpd_client_free (mpdclient);
 }
@@ -2441,7 +2441,7 @@ GST_START_TEST
   subRepresentation = (GstMPDSubRepresentationNode *)
       representation->SubRepresentations->data;
   assert_equals_uint64 (subRepresentation->level, 100);
-  assert_equals_uint64 (subRepresentation->size, 3);
+  assert_equals_uint64 (subRepresentation->dependencyLevel_size, 3);
   assert_equals_uint64 (subRepresentation->dependencyLevel[0], 1);
   assert_equals_uint64 (subRepresentation->dependencyLevel[1], 2);
   assert_equals_uint64 (subRepresentation->dependencyLevel[2], 3);
@@ -2466,7 +2466,7 @@ GST_START_TEST
   GstMPDAdaptationSetNode *adaptationSet;
   GstMPDRepresentationNode *representation;
   GstMPDSubRepresentationNode *subRepresentation;
-  GstMPDRepresentationBaseType *representationBase;
+
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -2490,9 +2490,8 @@ GST_START_TEST
       adaptationSet->Representations->data;
   subRepresentation = (GstMPDSubRepresentationNode *)
       representation->SubRepresentations->data;
-  representationBase = (GstMPDRepresentationBaseType *)
-      subRepresentation->RepresentationBase;
-  fail_if (representationBase == NULL);
+
+  fail_if (subRepresentation == NULL);
 
   gst_mpd_client_free (mpdclient);
 }
@@ -2508,7 +2507,7 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet_representation_segmentBase)
   GstMPDPeriodNode *periodNode;
   GstMPDAdaptationSetNode *adaptationSet;
   GstMPDRepresentationNode *representation;
-  GstMPDSegmentBaseType *segmentBase;
+  GstMPDSegmentBaseNode *segmentBase;
   const gchar *xml =
       "<?xml version=\"1.0\"?>"
       "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
@@ -2638,7 +2637,7 @@ GST_START_TEST (dash_mpdparser_period_subset)
 
   periodNode = (GstMPDPeriodNode *) mpdclient->mpd_root_node->Periods->data;
   subset = (GstMPDSubsetNode *) periodNode->Subsets->data;
-  assert_equals_uint64 (subset->size, 3);
+  assert_equals_uint64 (subset->contains_size, 3);
   assert_equals_uint64 (subset->contains[0], 1);
   assert_equals_uint64 (subset->contains[1], 2);
   assert_equals_uint64 (subset->contains[2], 3);
@@ -4479,7 +4478,7 @@ GST_END_TEST;
 GST_START_TEST (dash_mpdparser_inherited_segmentBase)
 {
   GstMPDPeriodNode *periodNode;
-  GstMPDSegmentBaseType *segmentBase;
+  GstMPDSegmentBaseNode *segmentBase;
   GstMPDAdaptationSetNode *adaptationSet;
   GstMPDRepresentationNode *representation;
   const gchar *xml =
@@ -5446,7 +5445,7 @@ GST_END_TEST;
 GST_START_TEST (dash_mpdparser_read_unsigned_from_negative_values)
 {
   GstMPDPeriodNode *periodNode;
-  GstMPDSegmentBaseType *segmentBase;
+  GstMPDSegmentBaseNode *segmentBase;
   GstMPDAdaptationSetNode *adaptationSet;
   GstMPDRepresentationNode *representation;
   GstMPDSubRepresentationNode *subRepresentation;
@@ -5501,7 +5500,8 @@ GST_START_TEST (dash_mpdparser_read_unsigned_from_negative_values)
   fail_if (adaptationSet->par != NULL);
 
   /* minFrameRate parsing should fail */
-  fail_if (adaptationSet->RepresentationBase->minFrameRate != NULL);
+  fail_if (GST_MPD_REPRESENTATION_BASE_NODE (adaptationSet)->minFrameRate !=
+      NULL);
 
   /* segmentAlignment parsing should fail */
   fail_if (adaptationSet->segmentAlignment != NULL);
@@ -5960,7 +5960,157 @@ GST_START_TEST (dash_mpdparser_datetime_with_tz_offset)
 
 GST_END_TEST;
 
+/*
+ * Test generate xml content.
+ *
+ */
+GST_START_TEST (dash_mpdparser_check_mpd_xml_generator)
+{
+  const gchar *xml =
+      "<?xml version=\"1.0\"?>"
+      "<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
+      "     profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
+      "     schemaLocation=\"TestSchemaLocation\""
+      "     xmlns:xsi=\"TestNamespaceXSI\""
+      "     xmlns:ext=\"TestNamespaceEXT\""
+      "     id=\"testId\""
+      "     type=\"static\""
+      "     availabilityStartTime=\"2015-03-24T1:10:50+08:00\""
+      "     availabilityEndTime=\"2015-03-24T1:10:50.123456-04:30\""
+      "     mediaPresentationDuration=\"P0Y1M2DT12H10M20.5S\""
+      "     minimumUpdatePeriod=\"P0Y1M2DT12H10M20.5S\""
+      "     minBufferTime=\"P0Y1M2DT12H10M20.5S\""
+      "     timeShiftBufferDepth=\"P0Y1M2DT12H10M20.5S\""
+      "     suggestedPresentationDelay=\"P0Y1M2DT12H10M20.5S\""
+      "     maxSegmentDuration=\"P0Y1M2DT12H10M20.5S\""
+      "     maxSubsegmentDuration=\"P0Y1M2DT12H10M20.5S\">"
+      "     <BaseURL serviceLocation=\"TestServiceLocation\""
+      "     byteRange=\"TestByteRange\">TestBaseURL</BaseURL>"
+      "     <Location>TestLocation</Location>"
+      "     <ProgramInformation lang=\"en\""
+      "     moreInformationURL=\"TestMoreInformationUrl\">"
+      "     <Title>TestTitle</Title>"
+      "     <Source>TestSource</Source>"
+      "     <Copyright>TestCopyright</Copyright>"
+      "     </ProgramInformation>"
+      "     <Metrics metrics=\"TestMetric\"><Range starttime=\"P0Y1M2DT12H10M20.5S\""
+      "           duration=\"P0Y1M2DT12H10M20.1234567S\">"
+      "    </Range></Metrics>"
+      "  <Period>"
+      "    <AdaptationSet>"
+      "      <Representation id=\"1\" bandwidth=\"250000\">"
+      "        <SegmentTemplate duration=\"1\">"
+      "        </SegmentTemplate>"
+      "      </Representation></AdaptationSet></Period>" "     </MPD>";
+
+  gboolean ret;
+  gchar *new_xml;
+  gint new_xml_size;
+  GstMPDClient *first_mpdclient = NULL;
+  GstMPDClient *second_mpdclient = NULL;
+  GstMPDBaseURLNode *first_baseURL, *second_baseURL;
+  GstMPDLocationNode *first_location, *second_location;
+  GstMPDProgramInformationNode *first_prog_info, *second_prog_info;
+  GstMPDMetricsNode *first_metrics, *second_metrics;
+  GstMPDMetricsRangeNode *first_metrics_range, *second_metrics_range;
+
+  first_mpdclient = gst_mpd_client_new ();
+
+  ret = gst_mpd_client_parse (first_mpdclient, xml, (gint) strlen (xml));
+  assert_equals_int (ret, TRUE);
+
+  gst_mpd_client_get_xml_content (first_mpdclient, &new_xml, &new_xml_size);
+
+  second_mpdclient = gst_mpd_client_new ();
+
+  ret = gst_mpd_client_parse (second_mpdclient, new_xml, new_xml_size);
+  assert_equals_int (ret, TRUE);
+  g_free (new_xml);
+
+  /* assert that parameters are equal */
+  assert_equals_string (first_mpdclient->mpd_root_node->default_namespace,
+      second_mpdclient->mpd_root_node->default_namespace);
+  assert_equals_string (first_mpdclient->mpd_root_node->namespace_xsi,
+      second_mpdclient->mpd_root_node->namespace_xsi);
+  assert_equals_string (first_mpdclient->mpd_root_node->namespace_ext,
+      second_mpdclient->mpd_root_node->namespace_ext);
+  assert_equals_string (first_mpdclient->mpd_root_node->schemaLocation,
+      second_mpdclient->mpd_root_node->schemaLocation);
+  assert_equals_string (first_mpdclient->mpd_root_node->id,
+      second_mpdclient->mpd_root_node->id);
+  assert_equals_string (first_mpdclient->mpd_root_node->profiles,
+      second_mpdclient->mpd_root_node->profiles);
+  assert_equals_uint64 (first_mpdclient->
+      mpd_root_node->mediaPresentationDuration,
+      second_mpdclient->mpd_root_node->mediaPresentationDuration);
+  assert_equals_uint64 (first_mpdclient->mpd_root_node->minimumUpdatePeriod,
+      second_mpdclient->mpd_root_node->minimumUpdatePeriod);
+  assert_equals_uint64 (first_mpdclient->mpd_root_node->minBufferTime,
+      second_mpdclient->mpd_root_node->minBufferTime);
+  assert_equals_uint64 (first_mpdclient->mpd_root_node->timeShiftBufferDepth,
+      second_mpdclient->mpd_root_node->timeShiftBufferDepth);
+  assert_equals_uint64 (first_mpdclient->
+      mpd_root_node->suggestedPresentationDelay,
+      second_mpdclient->mpd_root_node->suggestedPresentationDelay);
+  assert_equals_uint64 (first_mpdclient->mpd_root_node->maxSegmentDuration,
+      second_mpdclient->mpd_root_node->maxSegmentDuration);
+  assert_equals_uint64 (first_mpdclient->mpd_root_node->maxSubsegmentDuration,
+      second_mpdclient->mpd_root_node->maxSubsegmentDuration);
+
+  /* baseURLs */
+  first_baseURL =
+      (GstMPDBaseURLNode *) first_mpdclient->mpd_root_node->BaseURLs->data;
+  second_baseURL =
+      (GstMPDBaseURLNode *) second_mpdclient->mpd_root_node->BaseURLs->data;
+  assert_equals_string (first_baseURL->baseURL, second_baseURL->baseURL);
+  assert_equals_string (first_baseURL->serviceLocation,
+      second_baseURL->serviceLocation);
+  assert_equals_string (first_baseURL->byteRange, second_baseURL->byteRange);
+
+  /* locations */
+  first_location =
+      (GstMPDLocationNode *) first_mpdclient->mpd_root_node->Locations->data;
+  second_location =
+      (GstMPDLocationNode *) second_mpdclient->mpd_root_node->Locations->data;
+  assert_equals_string (first_location->location, second_location->location);
+
+  /* ProgramInformation */
+  first_prog_info =
+      (GstMPDProgramInformationNode *) first_mpdclient->mpd_root_node->
+      ProgramInfos->data;
+  second_prog_info =
+      (GstMPDProgramInformationNode *) second_mpdclient->mpd_root_node->
+      ProgramInfos->data;
+  assert_equals_string (first_prog_info->lang, second_prog_info->lang);
+  assert_equals_string (first_prog_info->moreInformationURL,
+      second_prog_info->moreInformationURL);
+  assert_equals_string (first_prog_info->Title, second_prog_info->Title);
+  assert_equals_string (first_prog_info->Source, second_prog_info->Source);
+  assert_equals_string (first_prog_info->Copyright,
+      second_prog_info->Copyright);
+
+  /* Metrics */
+  first_metrics =
+      (GstMPDMetricsNode *) first_mpdclient->mpd_root_node->Metrics->data;
+  second_metrics =
+      (GstMPDMetricsNode *) second_mpdclient->mpd_root_node->Metrics->data;
+  assert_equals_string (first_metrics->metrics, second_metrics->metrics);
+
+  /* Metrics Range */
+  first_metrics_range =
+      (GstMPDMetricsRangeNode *) first_metrics->MetricsRanges->data;
+  second_metrics_range =
+      (GstMPDMetricsRangeNode *) second_metrics->MetricsRanges->data;
+  assert_equals_uint64 (first_metrics_range->starttime,
+      second_metrics_range->starttime);
+  assert_equals_uint64 (first_metrics_range->duration,
+      second_metrics_range->duration);
+
+  gst_mpd_client_free (first_mpdclient);
+  gst_mpd_client_free (second_mpdclient);
+}
 
+GST_END_TEST;
 
 /*
  * create a test suite containing all dash testcases
@@ -5981,6 +6131,9 @@ dash_suite (void)
   /* test parsing the simplest possible mpd */
   tcase_add_test (tc_simpleMPD, dash_mpdparser_validsimplempd);
 
+  /* test parsing the simplest possible mpd */
+  tcase_add_test (tc_simpleMPD, dash_mpdparser_check_mpd_xml_generator);
+
   /* tests parsing attributes from each element type */
   tcase_add_test (tc_simpleMPD, dash_mpdparser_mpd);
   tcase_add_test (tc_simpleMPD, dash_mpdparser_datetime_with_tz_offset);