diff options
61 files changed, 2830 insertions, 955 deletions
diff --git a/ext/dash/gstdashdemux.c b/ext/dash/gstdashdemux.c index 05bb85bde..8aecfafa4 100644 --- a/ext/dash/gstdashdemux.c +++ b/ext/dash/gstdashdemux.c @@ -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; diff --git a/ext/dash/gstmpdadaptationsetnode.c b/ext/dash/gstmpdadaptationsetnode.c index a47bd910d..5d2ed9d12 100644 --- a/ext/dash/gstmpdadaptationsetnode.c +++ b/ext/dash/gstmpdadaptationsetnode.c @@ -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 */ diff --git a/ext/dash/gstmpdadaptationsetnode.h b/ext/dash/gstmpdadaptationsetnode.h index 1a0977f68..ce91a4b88 100644 --- a/ext/dash/gstmpdadaptationsetnode.h +++ b/ext/dash/gstmpdadaptationsetnode.h @@ -23,30 +23,18 @@ #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); diff --git a/ext/dash/gstmpdbaseurlnode.c b/ext/dash/gstmpdbaseurlnode.c index 4e5f89e37..53043edfb 100644 --- a/ext/dash/gstmpdbaseurlnode.c +++ b/ext/dash/gstmpdbaseurlnode.c @@ -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 diff --git a/ext/dash/gstmpdbaseurlnode.h b/ext/dash/gstmpdbaseurlnode.h index be28dc8d6..078d7545f 100644 --- a/ext/dash/gstmpdbaseurlnode.h +++ b/ext/dash/gstmpdbaseurlnode.h @@ -27,20 +27,7 @@ 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); diff --git a/ext/dash/gstmpdclient.c b/ext/dash/gstmpdclient.c index b2fdea915..99878d3dc 100644 --- a/ext/dash/gstmpdclient.c +++ b/ext/dash/gstmpdclient.c @@ -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) { diff --git a/ext/dash/gstmpdclient.h b/ext/dash/gstmpdclient.h index 8d165a919..ccf9923d5 100644 --- a/ext/dash/gstmpdclient.h +++ b/ext/dash/gstmpdclient.h @@ -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); diff --git a/ext/dash/gstmpdcontentcomponentnode.c b/ext/dash/gstmpdcontentcomponentnode.c index e8983f752..9498aa493 100644 --- a/ext/dash/gstmpdcontentcomponentnode.c +++ b/ext/dash/gstmpdcontentcomponentnode.c @@ -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 diff --git a/ext/dash/gstmpdcontentcomponentnode.h b/ext/dash/gstmpdcontentcomponentnode.h index 952110050..51a3b24a2 100644 --- a/ext/dash/gstmpdcontentcomponentnode.h +++ b/ext/dash/gstmpdcontentcomponentnode.h @@ -27,20 +27,7 @@ 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 index 000000000..a91d4b00a --- /dev/null +++ b/ext/dash/gstmpddescriptortypenode.c @@ -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 index 000000000..d4cbbd53c --- /dev/null +++ b/ext/dash/gstmpddescriptortypenode.h @@ -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__ */ diff --git a/ext/dash/gstmpdhelper.c b/ext/dash/gstmpdhelper.c index 7c10225e4..a66de89b9 100644 --- a/ext/dash/gstmpdhelper.c +++ b/ext/dash/gstmpdhelper.c @@ -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) { diff --git a/ext/dash/gstmpdhelper.h b/ext/dash/gstmpdhelper.h index 5bf35b648..95eaec9c8 100644 --- a/ext/dash/gstmpdhelper.h +++ b/ext/dash/gstmpdhelper.h @@ -22,15 +22,14 @@ #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 index 000000000..69459be4b --- /dev/null +++ b/ext/dash/gstmpdlocationnode.c @@ -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 index 000000000..2c2f33887 --- /dev/null +++ b/ext/dash/gstmpdlocationnode.h @@ -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__ */ diff --git a/ext/dash/gstmpdmetricsnode.c b/ext/dash/gstmpdmetricsnode.c index 1c1d5e408..79d6c5c62 100644 --- a/ext/dash/gstmpdmetricsnode.c +++ b/ext/dash/gstmpdmetricsnode.c @@ -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 diff --git a/ext/dash/gstmpdmetricsnode.h b/ext/dash/gstmpdmetricsnode.h index ef3ec2bff..87ad39d53 100644 --- a/ext/dash/gstmpdmetricsnode.h +++ b/ext/dash/gstmpdmetricsnode.h @@ -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 @@ -31,19 +27,7 @@ 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); diff --git a/ext/dash/gstmpdmetricsrangenode.c b/ext/dash/gstmpdmetricsrangenode.c index 1b8a9bd75..5ceb49839 100644 --- a/ext/dash/gstmpdmetricsrangenode.c +++ b/ext/dash/gstmpdmetricsrangenode.c @@ -22,13 +22,36 @@ #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 diff --git a/ext/dash/gstmpdmetricsrangenode.h b/ext/dash/gstmpdmetricsrangenode.h index 90709f93a..ef3dae0de 100644 --- a/ext/dash/gstmpdmetricsrangenode.h +++ b/ext/dash/gstmpdmetricsrangenode.h @@ -27,20 +27,7 @@ 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 index 000000000..349bfa1db --- /dev/null +++ b/ext/dash/gstmpdmultsegmentbasenode.c @@ -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 index 000000000..7f1654989 --- /dev/null +++ b/ext/dash/gstmpdmultsegmentbasenode.h @@ -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 index 000000000..f19dd0bc9 --- /dev/null +++ b/ext/dash/gstmpdnode.c @@ -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 index 000000000..d0f48e15c --- /dev/null +++ b/ext/dash/gstmpdnode.h @@ -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__ */ diff --git a/ext/dash/gstmpdparser.c b/ext/dash/gstmpdparser.c index 9dcc3bb59..8cd285871 100644 --- a/ext/dash/gstmpdparser.c +++ b/ext/dash/gstmpdparser.c @@ -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) diff --git a/ext/dash/gstmpdparser.h b/ext/dash/gstmpdparser.h index 653003fd7..f51b962bf 100644 --- a/ext/dash/gstmpdparser.h +++ b/ext/dash/gstmpdparser.h @@ -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" @@ -49,6 +50,12 @@ #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 diff --git a/ext/dash/gstmpdperiodnode.c b/ext/dash/gstmpdperiodnode.c index 8dea50c26..0b67fc74b 100644 --- a/ext/dash/gstmpdperiodnode.c +++ b/ext/dash/gstmpdperiodnode.c @@ -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 diff --git a/ext/dash/gstmpdperiodnode.h b/ext/dash/gstmpdperiodnode.h index 7e327a9ad..2c6540fe3 100644 --- a/ext/dash/gstmpdperiodnode.h +++ b/ext/dash/gstmpdperiodnode.h @@ -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); diff --git a/ext/dash/gstmpdprograminformationnode.c b/ext/dash/gstmpdprograminformationnode.c index 14daa5d64..69550fa8c 100644 --- a/ext/dash/gstmpdprograminformationnode.c +++ b/ext/dash/gstmpdprograminformationnode.c @@ -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 diff --git a/ext/dash/gstmpdprograminformationnode.h b/ext/dash/gstmpdprograminformationnode.h index 9d3a5a83f..f1c55a8fe 100644 --- a/ext/dash/gstmpdprograminformationnode.h +++ b/ext/dash/gstmpdprograminformationnode.h @@ -27,20 +27,7 @@ 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 index 000000000..fa81eb5de --- /dev/null +++ b/ext/dash/gstmpdreportingnode.c @@ -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 index 000000000..83b0b7763 --- /dev/null +++ b/ext/dash/gstmpdreportingnode.h @@ -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 index 000000000..29e43d311 --- /dev/null +++ b/ext/dash/gstmpdrepresentationbasenode.c @@ -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 index 000000000..767dd9ee6 --- /dev/null +++ b/ext/dash/gstmpdrepresentationbasenode.h @@ -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__ */ diff --git a/ext/dash/gstmpdrepresentationnode.c b/ext/dash/gstmpdrepresentationnode.c index 3179a4a77..6b583f04a 100644 --- a/ext/dash/gstmpdrepresentationnode.c +++ b/ext/dash/gstmpdrepresentationnode.c @@ -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; diff --git a/ext/dash/gstmpdrepresentationnode.h b/ext/dash/gstmpdrepresentationnode.h index 2b0352c0f..617d978f1 100644 --- a/ext/dash/gstmpdrepresentationnode.h +++ b/ext/dash/gstmpdrepresentationnode.h @@ -23,55 +23,35 @@ #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); diff --git a/ext/dash/gstmpdrootnode.c b/ext/dash/gstmpdrootnode.c index d2e954f6a..815c421ec 100644 --- a/ext/dash/gstmpdrootnode.c +++ b/ext/dash/gstmpdrootnode.c @@ -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 diff --git a/ext/dash/gstmpdrootnode.h b/ext/dash/gstmpdrootnode.h index bf463e014..776e6a6ac 100644 --- a/ext/dash/gstmpdrootnode.h +++ b/ext/dash/gstmpdrootnode.h @@ -27,20 +27,7 @@ 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 index 000000000..e492197d2 --- /dev/null +++ b/ext/dash/gstmpdsegmentbasenode.c @@ -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 index 000000000..7693177bc --- /dev/null +++ b/ext/dash/gstmpdsegmentbasenode.h @@ -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__ */ diff --git a/ext/dash/gstmpdsegmentlistnode.c b/ext/dash/gstmpdsegmentlistnode.c index 01c6d9aa6..5d0db76cd 100644 --- a/ext/dash/gstmpdsegmentlistnode.c +++ b/ext/dash/gstmpdsegmentlistnode.c @@ -20,10 +20,9 @@ */ #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; diff --git a/ext/dash/gstmpdsegmentlistnode.h b/ext/dash/gstmpdsegmentlistnode.h index 715e702e3..1ed8769c9 100644 --- a/ext/dash/gstmpdsegmentlistnode.h +++ b/ext/dash/gstmpdsegmentlistnode.h @@ -23,31 +23,19 @@ #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); diff --git a/ext/dash/gstmpdsegmenttemplatenode.c b/ext/dash/gstmpdsegmenttemplatenode.c index 3fc898a99..ac2af44b7 100644 --- a/ext/dash/gstmpdsegmenttemplatenode.c +++ b/ext/dash/gstmpdsegmenttemplatenode.c @@ -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; diff --git a/ext/dash/gstmpdsegmenttemplatenode.h b/ext/dash/gstmpdsegmenttemplatenode.h index b882f5505..b9fb469c9 100644 --- a/ext/dash/gstmpdsegmenttemplatenode.h +++ b/ext/dash/gstmpdsegmenttemplatenode.h @@ -23,43 +23,23 @@ #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); diff --git a/ext/dash/gstmpdsegmenttimelinenode.c b/ext/dash/gstmpdsegmenttimelinenode.c index c6e449ac9..9b574e615 100644 --- a/ext/dash/gstmpdsegmenttimelinenode.c +++ b/ext/dash/gstmpdsegmenttimelinenode.c @@ -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 diff --git a/ext/dash/gstmpdsegmenttimelinenode.h b/ext/dash/gstmpdsegmenttimelinenode.h index b27569612..a91ebfe3b 100644 --- a/ext/dash/gstmpdsegmenttimelinenode.h +++ b/ext/dash/gstmpdsegmenttimelinenode.h @@ -22,25 +22,12 @@ #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); diff --git a/ext/dash/gstmpdsegmenturlnode.c b/ext/dash/gstmpdsegmenturlnode.c index b8f23bfb7..2a3909159 100644 --- a/ext/dash/gstmpdsegmenturlnode.c +++ b/ext/dash/gstmpdsegmenturlnode.c @@ -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 diff --git a/ext/dash/gstmpdsegmenturlnode.h b/ext/dash/gstmpdsegmenturlnode.h index 5523ec50e..851632c58 100644 --- a/ext/dash/gstmpdsegmenturlnode.h +++ b/ext/dash/gstmpdsegmenturlnode.h @@ -22,25 +22,12 @@ #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); diff --git a/ext/dash/gstmpdsnode.c b/ext/dash/gstmpdsnode.c index 63fd06e5b..d823d8a02 100644 --- a/ext/dash/gstmpdsnode.c +++ b/ext/dash/gstmpdsnode.c @@ -21,13 +21,38 @@ #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 diff --git a/ext/dash/gstmpdsnode.h b/ext/dash/gstmpdsnode.h index ded0235bf..c33b898a9 100644 --- a/ext/dash/gstmpdsnode.h +++ b/ext/dash/gstmpdsnode.h @@ -22,25 +22,12 @@ #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); diff --git a/ext/dash/gstmpdsubrepresentationnode.c b/ext/dash/gstmpdsubrepresentationnode.c index 55b9a4768..66cde3d29 100644 --- a/ext/dash/gstmpdsubrepresentationnode.c +++ b/ext/dash/gstmpdsubrepresentationnode.c @@ -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; } diff --git a/ext/dash/gstmpdsubrepresentationnode.h b/ext/dash/gstmpdsubrepresentationnode.h index 40c4db3b3..79ead6668 100644 --- a/ext/dash/gstmpdsubrepresentationnode.h +++ b/ext/dash/gstmpdsubrepresentationnode.h @@ -23,44 +23,24 @@ #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); diff --git a/ext/dash/gstmpdsubsetnode.c b/ext/dash/gstmpdsubsetnode.c index 8a8cd6a80..d537ed917 100644 --- a/ext/dash/gstmpdsubsetnode.c +++ b/ext/dash/gstmpdsubsetnode.c @@ -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; } diff --git a/ext/dash/gstmpdsubsetnode.h b/ext/dash/gstmpdsubsetnode.h index d307245c3..756f4d955 100644 --- a/ext/dash/gstmpdsubsetnode.h +++ b/ext/dash/gstmpdsubsetnode.h @@ -22,40 +22,25 @@ #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 index 000000000..5a1ad503f --- /dev/null +++ b/ext/dash/gstmpdurltypenode.c @@ -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 index 000000000..fcb0e1e3c --- /dev/null +++ b/ext/dash/gstmpdurltypenode.h @@ -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__ */ diff --git a/ext/dash/gstmpdutctimingnode.c b/ext/dash/gstmpdutctimingnode.c index ca9c7bb50..a02c89c69 100644 --- a/ext/dash/gstmpdutctimingnode.c +++ b/ext/dash/gstmpdutctimingnode.c @@ -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; +} diff --git a/ext/dash/gstmpdutctimingnode.h b/ext/dash/gstmpdutctimingnode.h index 42b5fecbd..32cd98dee 100644 --- a/ext/dash/gstmpdutctimingnode.h +++ b/ext/dash/gstmpdutctimingnode.h @@ -22,25 +22,12 @@ #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__ */ diff --git a/ext/dash/gstxmlhelper.c b/ext/dash/gstxmlhelper.c index ff9798119..c59c57d9a 100644 --- a/ext/dash/gstxmlhelper.c +++ b/ext/dash/gstxmlhelper.c @@ -21,6 +21,12 @@ #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); +} diff --git a/ext/dash/gstxmlhelper.h b/ext/dash/gstxmlhelper.h index ce9de9ab6..af3e8ff9e 100644 --- a/ext/dash/gstxmlhelper.h +++ b/ext/dash/gstxmlhelper.h @@ -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__ */ diff --git a/ext/dash/meson.build b/ext/dash/meson.build index 67779b275..56be53564 100644 --- a/ext/dash/meson.build +++ b/ext/dash/meson.build @@ -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', diff --git a/tests/check/elements/dash_mpd.c b/tests/check/elements/dash_mpd.c index 8098013c6..e65105455 100644 --- a/tests/check/elements/dash_mpd.c +++ b/tests/check/elements/dash_mpd.c @@ -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" @@ -38,6 +42,10 @@ #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); |