1 /* GStreamer
2 *
3 * Copyright (C) 2019 Collabora Ltd.
4 * Author: Stéphane Cerveau <scerveau@collabora.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 */
21 #include "gstmpdrepresentationbasenode.h"
22 #include "gstmpdparser.h"
23
24 G_DEFINE_TYPE (GstMPDRepresentationBaseNode, gst_mpd_representation_base_node,
25 GST_TYPE_MPD_NODE);
26
27 enum
28 {
29 PROP_MPD_REPRESENTATION_BASE_0 = 100,
30 PROP_MPD_REPRESENTATION_BASE_PROFILES,
31 PROP_MPD_REPRESENTATION_BASE_WIDTH,
32 PROP_MPD_REPRESENTATION_BASE_HEIGHT,
33 PROP_MPD_REPRESENTATION_BASE_SAR,
34 PROP_MPD_REPRESENTATION_BASE_MIN_FRAME_RATE,
35 PROP_MPD_REPRESENTATION_BASE_MAX_FRAME_RATE,
36 PROP_MPD_REPRESENTATION_BASE_FRAME_RATE,
37 PROP_MPD_REPRESENTATION_BASE_AUDIO_SAMPLING_RATE,
38 PROP_MPD_REPRESENTATION_BASE_MIMETYPE,
39 PROP_MPD_REPRESENTATION_BASE_SEGMENT_PROFILES,
40 PROP_MPD_REPRESENTATION_BASE_CODECS,
41 PROP_MPD_REPRESENTATION_BASE_MAX_SAP_PERIOD,
42 PROP_MPD_REPRESENTATION_BASE_START_WITH_SAP,
43 PROP_MPD_REPRESENTATION_BASE_MAX_PLAYOUT_RATE,
44 PROP_MPD_REPRESENTATION_BASE_CODING_DEPENDENCY,
45 PROP_MPD_REPRESENTATION_BASE_SCAN_TYPE,
46 };
47
48 /* GObject VMethods */
49
50 static void
gst_mpd_representation_base_node_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)51 gst_mpd_representation_base_node_set_property (GObject * object, guint prop_id,
52 const GValue * value, GParamSpec * pspec)
53 {
54 GstMPDRepresentationBaseNode *self =
55 GST_MPD_REPRESENTATION_BASE_NODE (object);
56 switch (prop_id) {
57 case PROP_MPD_REPRESENTATION_BASE_PROFILES:
58 g_free (self->profiles);
59 self->profiles = g_value_dup_string (value);
60 break;
61 case PROP_MPD_REPRESENTATION_BASE_WIDTH:
62 self->width = g_value_get_uint (value);
63 break;
64 case PROP_MPD_REPRESENTATION_BASE_HEIGHT:
65 self->height = g_value_get_uint (value);
66 break;
67 case PROP_MPD_REPRESENTATION_BASE_SAR:
68 g_slice_free (GstXMLRatio, self->sar);
69 self->sar = gst_xml_helper_clone_ratio (g_value_get_pointer (value));
70 break;
71 case PROP_MPD_REPRESENTATION_BASE_MIN_FRAME_RATE:
72 g_slice_free (GstXMLFrameRate, self->minFrameRate);
73 self->minFrameRate =
74 gst_xml_helper_clone_frame_rate (g_value_get_pointer (value));
75 break;
76 case PROP_MPD_REPRESENTATION_BASE_MAX_FRAME_RATE:
77 g_slice_free (GstXMLFrameRate, self->maxFrameRate);
78 self->maxFrameRate =
79 gst_xml_helper_clone_frame_rate (g_value_get_pointer (value));
80 break;
81 case PROP_MPD_REPRESENTATION_BASE_FRAME_RATE:
82 g_slice_free (GstXMLFrameRate, self->frameRate);
83 self->frameRate =
84 gst_xml_helper_clone_frame_rate (g_value_get_pointer (value));
85 break;
86 case PROP_MPD_REPRESENTATION_BASE_AUDIO_SAMPLING_RATE:
87 g_free (self->audioSamplingRate);
88 self->audioSamplingRate =
89 g_strdup_printf ("%u", g_value_get_uint (value));
90 break;
91 case PROP_MPD_REPRESENTATION_BASE_MIMETYPE:
92 g_free (self->mimeType);
93 self->mimeType = g_value_dup_string (value);
94 break;
95 case PROP_MPD_REPRESENTATION_BASE_SEGMENT_PROFILES:
96 g_free (self->segmentProfiles);
97 self->segmentProfiles = g_value_dup_string (value);
98 break;
99 case PROP_MPD_REPRESENTATION_BASE_CODECS:
100 g_free (self->codecs);
101 self->codecs = g_value_dup_string (value);
102 break;
103 case PROP_MPD_REPRESENTATION_BASE_MAX_SAP_PERIOD:
104 self->maximumSAPPeriod = g_value_get_double (value);
105 break;
106 case PROP_MPD_REPRESENTATION_BASE_START_WITH_SAP:
107 self->startWithSAP = g_value_get_int (value);
108 break;
109 case PROP_MPD_REPRESENTATION_BASE_MAX_PLAYOUT_RATE:
110 self->maxPlayoutRate = g_value_get_double (value);
111 break;
112 case PROP_MPD_REPRESENTATION_BASE_CODING_DEPENDENCY:
113 self->codingDependency = g_value_get_boolean (value);
114 break;
115 case PROP_MPD_REPRESENTATION_BASE_SCAN_TYPE:
116 g_free (self->scanType);
117 self->scanType = g_value_dup_string (value);
118 break;
119 default:
120 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
121 break;
122 }
123 }
124
125 static void
gst_mpd_representation_base_node_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)126 gst_mpd_representation_base_node_get_property (GObject * object, guint prop_id,
127 GValue * value, GParamSpec * pspec)
128 {
129 GstMPDRepresentationBaseNode *self =
130 GST_MPD_REPRESENTATION_BASE_NODE (object);
131 switch (prop_id) {
132 case PROP_MPD_REPRESENTATION_BASE_PROFILES:
133 g_value_set_string (value, self->profiles);
134 break;
135 case PROP_MPD_REPRESENTATION_BASE_WIDTH:
136 g_value_set_uint (value, self->width);
137 break;
138 case PROP_MPD_REPRESENTATION_BASE_HEIGHT:
139 g_value_set_uint (value, self->height);
140 break;
141 case PROP_MPD_REPRESENTATION_BASE_SAR:
142 g_value_set_pointer (value, self->sar);
143 break;
144 case PROP_MPD_REPRESENTATION_BASE_MIN_FRAME_RATE:
145 g_value_set_pointer (value, self->minFrameRate);
146 break;
147 case PROP_MPD_REPRESENTATION_BASE_MAX_FRAME_RATE:
148 g_value_set_pointer (value, self->maxFrameRate);
149 break;
150 case PROP_MPD_REPRESENTATION_BASE_FRAME_RATE:
151 g_value_set_pointer (value, self->frameRate);
152 break;
153 case PROP_MPD_REPRESENTATION_BASE_AUDIO_SAMPLING_RATE:
154 g_value_set_uint (value, atoi (self->audioSamplingRate));
155 break;
156 case PROP_MPD_REPRESENTATION_BASE_MIMETYPE:
157 g_value_set_string (value, self->mimeType);
158 break;
159 case PROP_MPD_REPRESENTATION_BASE_SEGMENT_PROFILES:
160 g_value_set_string (value, self->segmentProfiles);
161 break;
162 case PROP_MPD_REPRESENTATION_BASE_CODECS:
163 g_value_set_string (value, self->codecs);
164 break;
165 case PROP_MPD_REPRESENTATION_BASE_MAX_SAP_PERIOD:
166 g_value_set_double (value, self->maximumSAPPeriod);
167 break;
168 case PROP_MPD_REPRESENTATION_BASE_START_WITH_SAP:
169 g_value_set_int (value, self->startWithSAP);
170 break;
171 case PROP_MPD_REPRESENTATION_BASE_MAX_PLAYOUT_RATE:
172 g_value_set_double (value, self->maxPlayoutRate);
173 break;
174 case PROP_MPD_REPRESENTATION_BASE_CODING_DEPENDENCY:
175 g_value_set_boolean (value, self->codingDependency);
176 self->codingDependency = g_value_get_boolean (value);
177 break;
178 case PROP_MPD_REPRESENTATION_BASE_SCAN_TYPE:
179 g_value_set_string (value, self->scanType);
180 break;
181 default:
182 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
183 break;
184 }
185 }
186
187 static void
gst_mpd_representation_base_node_finalize(GObject * object)188 gst_mpd_representation_base_node_finalize (GObject * object)
189 {
190 GstMPDRepresentationBaseNode *self =
191 GST_MPD_REPRESENTATION_BASE_NODE (object);
192
193 if (self->profiles)
194 xmlFree (self->profiles);
195 g_slice_free (GstXMLRatio, self->sar);
196 g_slice_free (GstXMLFrameRate, self->frameRate);
197 g_slice_free (GstXMLFrameRate, self->minFrameRate);
198 g_slice_free (GstXMLFrameRate, self->maxFrameRate);
199 if (self->audioSamplingRate)
200 xmlFree (self->audioSamplingRate);
201 if (self->mimeType)
202 xmlFree (self->mimeType);
203 if (self->segmentProfiles)
204 xmlFree (self->segmentProfiles);
205 if (self->codecs)
206 xmlFree (self->codecs);
207 if (self->scanType)
208 xmlFree (self->scanType);
209 g_list_free_full (self->FramePacking,
210 (GDestroyNotify) gst_mpd_descriptor_type_node_free);
211 g_list_free_full (self->AudioChannelConfiguration,
212 (GDestroyNotify) gst_mpd_descriptor_type_node_free);
213 g_list_free_full (self->ContentProtection,
214 (GDestroyNotify) gst_mpd_descriptor_type_node_free);
215
216 G_OBJECT_CLASS (gst_mpd_representation_base_node_parent_class)->finalize
217 (object);
218 }
219
220 /* Base class */
221
222 static void
gst_mpd_representation_base_get_xml_node(GstMPDNode * node,xmlNodePtr representation_base_node)223 gst_mpd_representation_base_get_xml_node (GstMPDNode * node,
224 xmlNodePtr representation_base_node)
225 {
226 GstMPDRepresentationBaseNode *self = GST_MPD_REPRESENTATION_BASE_NODE (node);
227
228 if (self->profiles)
229 gst_xml_helper_set_prop_string (representation_base_node, "profiles",
230 self->profiles);
231 if (self->width)
232 gst_xml_helper_set_prop_uint (representation_base_node, "width",
233 self->width);
234 if (self->height)
235 gst_xml_helper_set_prop_uint (representation_base_node, "height",
236 self->height);
237
238 gst_xml_helper_set_prop_ratio (representation_base_node, "sar", self->sar);
239 gst_xml_helper_set_prop_framerate (representation_base_node, "minFrameRate",
240 self->minFrameRate);
241 gst_xml_helper_set_prop_framerate (representation_base_node, "maxFrameRate",
242 self->maxFrameRate);
243 gst_xml_helper_set_prop_framerate (representation_base_node, "frameRate",
244 self->frameRate);
245
246 gst_xml_helper_set_prop_string (representation_base_node,
247 "audioSamplingRate", self->audioSamplingRate);
248 gst_xml_helper_set_prop_string (representation_base_node, "mimeType",
249 self->mimeType);
250 gst_xml_helper_set_prop_string (representation_base_node, "segmentProfiles",
251 self->segmentProfiles);
252 gst_xml_helper_set_prop_string (representation_base_node, "codecs",
253 self->codecs);
254 if (self->maximumSAPPeriod)
255 gst_xml_helper_set_prop_double (representation_base_node,
256 "maximumSAPPeriod", self->maximumSAPPeriod);
257 if (self->startWithSAP)
258 gst_xml_helper_set_prop_int (representation_base_node, "startWithSAP",
259 self->startWithSAP);
260 if (self->maxPlayoutRate)
261 gst_xml_helper_set_prop_double (representation_base_node, "maxPlayoutRate",
262 self->maxPlayoutRate);
263 if (self->codingDependency)
264 gst_xml_helper_set_prop_boolean (representation_base_node,
265 "codingDependency", self->codingDependency);
266
267 gst_xml_helper_set_prop_string (representation_base_node, "scanType",
268 self->scanType);
269
270 g_list_foreach (self->FramePacking,
271 gst_mpd_node_get_list_item, representation_base_node);
272 g_list_foreach (self->AudioChannelConfiguration,
273 gst_mpd_node_get_list_item, representation_base_node);
274 g_list_foreach (self->ContentProtection,
275 gst_mpd_node_get_list_item, representation_base_node);
276 }
277
278 static void
gst_mpd_representation_base_node_class_init(GstMPDRepresentationBaseNodeClass * klass)279 gst_mpd_representation_base_node_class_init (GstMPDRepresentationBaseNodeClass *
280 klass)
281 {
282 GObjectClass *object_class;
283
284 object_class = G_OBJECT_CLASS (klass);
285
286 object_class->finalize = gst_mpd_representation_base_node_finalize;
287 object_class->set_property = gst_mpd_representation_base_node_set_property;
288 object_class->get_property = gst_mpd_representation_base_node_get_property;
289
290
291 g_object_class_install_property (object_class,
292 PROP_MPD_REPRESENTATION_BASE_WIDTH, g_param_spec_uint ("width",
293 "width", "representation width", 0, G_MAXUINT, 0,
294 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
295 g_object_class_install_property (object_class,
296 PROP_MPD_REPRESENTATION_BASE_HEIGHT, g_param_spec_uint ("height",
297 "height", "representation height", 0, G_MAXUINT, 0,
298 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
299 g_object_class_install_property (object_class,
300 PROP_MPD_REPRESENTATION_BASE_MIMETYPE, g_param_spec_string ("mime-type",
301 "mimetype", "representation mimetype", NULL,
302 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
303 g_object_class_install_property (object_class,
304 PROP_MPD_REPRESENTATION_BASE_CODECS, g_param_spec_string ("codecs",
305 "codecs", "representation codec", NULL,
306 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
307 g_object_class_install_property (object_class,
308 PROP_MPD_REPRESENTATION_BASE_AUDIO_SAMPLING_RATE,
309 g_param_spec_uint ("audio-sampling-rate", "audio sampling rate",
310 "representation audio sampling rate", 0, G_MAXUINT, 0,
311 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
312 }
313
314 static void
gst_mpd_representation_base_node_init(GstMPDRepresentationBaseNode * self)315 gst_mpd_representation_base_node_init (GstMPDRepresentationBaseNode * self)
316 {
317 self->profiles = NULL;
318 self->width = 0;
319 self->height = 0;
320 self->sar = NULL;
321 self->minFrameRate = NULL;
322 self->maxFrameRate = NULL;
323 self->frameRate = NULL;
324 self->audioSamplingRate = NULL;
325 self->mimeType = NULL;
326 self->segmentProfiles = NULL;
327 self->codecs = NULL;
328 self->maximumSAPPeriod = 0;
329 self->startWithSAP = GST_SAP_TYPE_0;
330 self->maxPlayoutRate = 0.0;
331 self->codingDependency = FALSE;
332 self->scanType = NULL;
333 self->FramePacking = NULL;
334 self->AudioChannelConfiguration = NULL;
335 self->ContentProtection = NULL;
336 }
337
338 void
gst_mpd_representation_base_node_get_list_item(gpointer data,gpointer user_data)339 gst_mpd_representation_base_node_get_list_item (gpointer data,
340 gpointer user_data)
341 {
342 GstMPDNode *node = (GstMPDNode *) data;
343 xmlNodePtr parent_xml_node = (xmlNodePtr) user_data;
344 xmlNodePtr new_xml_node = gst_mpd_node_get_xml_pointer (node);
345
346 gst_mpd_representation_base_get_xml_node (node, new_xml_node);
347 xmlAddChild (parent_xml_node, new_xml_node);
348 }
349