/* GStreamer * * Copyright (C) 2019 Collabora Ltd. * Author: Stéphane Cerveau * * 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); enum { PROP_MPD_REPRESENTATION_BASE_0 = 100, PROP_MPD_REPRESENTATION_BASE_PROFILES, PROP_MPD_REPRESENTATION_BASE_WIDTH, PROP_MPD_REPRESENTATION_BASE_HEIGHT, PROP_MPD_REPRESENTATION_BASE_SAR, PROP_MPD_REPRESENTATION_BASE_MIN_FRAME_RATE, PROP_MPD_REPRESENTATION_BASE_MAX_FRAME_RATE, PROP_MPD_REPRESENTATION_BASE_FRAME_RATE, PROP_MPD_REPRESENTATION_BASE_AUDIO_SAMPLING_RATE, PROP_MPD_REPRESENTATION_BASE_MIMETYPE, PROP_MPD_REPRESENTATION_BASE_SEGMENT_PROFILES, PROP_MPD_REPRESENTATION_BASE_CODECS, PROP_MPD_REPRESENTATION_BASE_MAX_SAP_PERIOD, PROP_MPD_REPRESENTATION_BASE_START_WITH_SAP, PROP_MPD_REPRESENTATION_BASE_MAX_PLAYOUT_RATE, PROP_MPD_REPRESENTATION_BASE_CODING_DEPENDENCY, PROP_MPD_REPRESENTATION_BASE_SCAN_TYPE, }; /* GObject VMethods */ static void gst_mpd_representation_base_node_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstMPDRepresentationBaseNode *self = GST_MPD_REPRESENTATION_BASE_NODE (object); switch (prop_id) { case PROP_MPD_REPRESENTATION_BASE_PROFILES: g_free (self->profiles); self->profiles = g_value_dup_string (value); break; case PROP_MPD_REPRESENTATION_BASE_WIDTH: self->width = g_value_get_uint (value); break; case PROP_MPD_REPRESENTATION_BASE_HEIGHT: self->height = g_value_get_uint (value); break; case PROP_MPD_REPRESENTATION_BASE_SAR: g_slice_free (GstXMLRatio, self->sar); self->sar = gst_xml_helper_clone_ratio (g_value_get_pointer (value)); break; case PROP_MPD_REPRESENTATION_BASE_MIN_FRAME_RATE: g_slice_free (GstXMLFrameRate, self->minFrameRate); self->minFrameRate = gst_xml_helper_clone_frame_rate (g_value_get_pointer (value)); break; case PROP_MPD_REPRESENTATION_BASE_MAX_FRAME_RATE: g_slice_free (GstXMLFrameRate, self->maxFrameRate); self->maxFrameRate = gst_xml_helper_clone_frame_rate (g_value_get_pointer (value)); break; case PROP_MPD_REPRESENTATION_BASE_FRAME_RATE: g_slice_free (GstXMLFrameRate, self->frameRate); self->frameRate = gst_xml_helper_clone_frame_rate (g_value_get_pointer (value)); break; case PROP_MPD_REPRESENTATION_BASE_AUDIO_SAMPLING_RATE: g_free (self->audioSamplingRate); self->audioSamplingRate = g_strdup_printf ("%u", g_value_get_uint (value)); break; case PROP_MPD_REPRESENTATION_BASE_MIMETYPE: g_free (self->mimeType); self->mimeType = g_value_dup_string (value); break; case PROP_MPD_REPRESENTATION_BASE_SEGMENT_PROFILES: g_free (self->segmentProfiles); self->segmentProfiles = g_value_dup_string (value); break; case PROP_MPD_REPRESENTATION_BASE_CODECS: g_free (self->codecs); self->codecs = g_value_dup_string (value); break; case PROP_MPD_REPRESENTATION_BASE_MAX_SAP_PERIOD: self->maximumSAPPeriod = g_value_get_double (value); break; case PROP_MPD_REPRESENTATION_BASE_START_WITH_SAP: self->startWithSAP = g_value_get_int (value); break; case PROP_MPD_REPRESENTATION_BASE_MAX_PLAYOUT_RATE: self->maxPlayoutRate = g_value_get_double (value); break; case PROP_MPD_REPRESENTATION_BASE_CODING_DEPENDENCY: self->codingDependency = g_value_get_boolean (value); break; case PROP_MPD_REPRESENTATION_BASE_SCAN_TYPE: g_free (self->scanType); self->scanType = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gst_mpd_representation_base_node_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstMPDRepresentationBaseNode *self = GST_MPD_REPRESENTATION_BASE_NODE (object); switch (prop_id) { case PROP_MPD_REPRESENTATION_BASE_PROFILES: g_value_set_string (value, self->profiles); break; case PROP_MPD_REPRESENTATION_BASE_WIDTH: g_value_set_uint (value, self->width); break; case PROP_MPD_REPRESENTATION_BASE_HEIGHT: g_value_set_uint (value, self->height); break; case PROP_MPD_REPRESENTATION_BASE_SAR: g_value_set_pointer (value, self->sar); break; case PROP_MPD_REPRESENTATION_BASE_MIN_FRAME_RATE: g_value_set_pointer (value, self->minFrameRate); break; case PROP_MPD_REPRESENTATION_BASE_MAX_FRAME_RATE: g_value_set_pointer (value, self->maxFrameRate); break; case PROP_MPD_REPRESENTATION_BASE_FRAME_RATE: g_value_set_pointer (value, self->frameRate); break; case PROP_MPD_REPRESENTATION_BASE_AUDIO_SAMPLING_RATE: g_value_set_uint (value, atoi (self->audioSamplingRate)); break; case PROP_MPD_REPRESENTATION_BASE_MIMETYPE: g_value_set_string (value, self->mimeType); break; case PROP_MPD_REPRESENTATION_BASE_SEGMENT_PROFILES: g_value_set_string (value, self->segmentProfiles); break; case PROP_MPD_REPRESENTATION_BASE_CODECS: g_value_set_string (value, self->codecs); break; case PROP_MPD_REPRESENTATION_BASE_MAX_SAP_PERIOD: g_value_set_double (value, self->maximumSAPPeriod); break; case PROP_MPD_REPRESENTATION_BASE_START_WITH_SAP: g_value_set_int (value, self->startWithSAP); break; case PROP_MPD_REPRESENTATION_BASE_MAX_PLAYOUT_RATE: g_value_set_double (value, self->maxPlayoutRate); break; case PROP_MPD_REPRESENTATION_BASE_CODING_DEPENDENCY: g_value_set_boolean (value, self->codingDependency); self->codingDependency = g_value_get_boolean (value); break; case PROP_MPD_REPRESENTATION_BASE_SCAN_TYPE: g_value_set_string (value, self->scanType); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } 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; object_class->set_property = gst_mpd_representation_base_node_set_property; object_class->get_property = gst_mpd_representation_base_node_get_property; g_object_class_install_property (object_class, PROP_MPD_REPRESENTATION_BASE_WIDTH, g_param_spec_uint ("width", "width", "representation width", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_MPD_REPRESENTATION_BASE_HEIGHT, g_param_spec_uint ("height", "height", "representation height", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_MPD_REPRESENTATION_BASE_MIMETYPE, g_param_spec_string ("mime-type", "mimetype", "representation mimetype", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_MPD_REPRESENTATION_BASE_CODECS, g_param_spec_string ("codecs", "codecs", "representation codec", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_MPD_REPRESENTATION_BASE_AUDIO_SAMPLING_RATE, g_param_spec_uint ("audio-sampling-rate", "audio sampling rate", "representation audio sampling rate", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } 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); }