1 /*
2  * gstmpegtsdescriptor.c -
3  * Copyright (C) 2013 Edward Hervey
4  *
5  * Authors:
6  *   Edward Hervey <edward@collabora.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #include "mpegts.h"
31 #include "gstmpegts-private.h"
32 
33 
34 /**
35  * SECTION:gst-dvb-descriptor
36  * @title: DVB variants of MPEG-TS descriptors
37  * @short_description: Descriptors for the various DVB specifications
38  * @include: gst/mpegts/mpegts.h
39  *
40  */
41 
42 /*
43  * TODO
44  *
45  * * Add common validation code for data presence and minimum/maximum expected
46  *   size.
47  * * Add parsing methods for the following descriptors that were previously
48  *   handled in mpegtsbase:
49  *   * GST_MTS_DESC_DVB_DATA_BROADCAST_ID
50  *   * GST_MTS_DESC_DVB_CAROUSEL_IDENTIFIER
51  */
52 
53 #define BCD_UN(a) ((a) & 0x0f)
54 #define BCD_DEC(a) (((a) >> 4) & 0x0f)
55 #define BCD(a) (BCD_UN(a) + 10 * BCD_DEC(a))
56 #define BCD_16(a) (BCD(a[1]) + 100 * BCD(a[0]))
57 #define BCD_28(a) (BCD_DEC(a[3]) + 10 * BCD(a[2]) + 1000 * BCD(a[1]) + 100000 * BCD(a[0]))
58 #define BCD_32(a) (BCD(a[3]) + 100 * BCD(a[2]) + 10000 * BCD(a[1]) + 1000000 * BCD(a[0]))
59 
60 #define DEFINE_STATIC_COPY_FUNCTION(type, name) \
61 static type * _##name##_copy (type * source) \
62 { \
63   return g_slice_dup (type, source); \
64 }
65 
66 #define DEFINE_STATIC_FREE_FUNCTION(type, name) \
67 static void _##name##_free (type * source) \
68 { \
69   g_slice_free (type, source); \
70 }
71 
72 /* GST_MTS_DESC_DVB_NETWORK_NAME (0x40) */
73 /**
74  * gst_mpegts_descriptor_parse_dvb_network_name:
75  * @descriptor: a %GST_MTS_DESC_DVB_NETWORK_NAME #GstMpegtsDescriptor
76  * @name: (out) (transfer full): the extracted name
77  *
78  * Parses out the dvb network name from the @descriptor:
79  *
80  * Returns: %TRUE if the parsing happened correctly, else %FALSE.
81  */
82 gboolean
gst_mpegts_descriptor_parse_dvb_network_name(const GstMpegtsDescriptor * descriptor,gchar ** name)83 gst_mpegts_descriptor_parse_dvb_network_name (const GstMpegtsDescriptor *
84     descriptor, gchar ** name)
85 {
86   g_return_val_if_fail (descriptor != NULL && name != NULL, FALSE);
87   /* We need at least one byte of data for the string */
88   __common_desc_checks (descriptor, GST_MTS_DESC_DVB_NETWORK_NAME, 1, FALSE);
89 
90   *name = get_encoding_and_convert ((gchar *) descriptor->data + 2,
91       descriptor->data[1]);
92   return TRUE;
93 }
94 
95 /**
96  * gst_mpegts_descriptor_from_dvb_network_name:
97  * @name: the network name to set
98  *
99  * Creates a #GstMpegtsDescriptor to be a %GST_MTS_DESC_DVB_NETWORK_NAME,
100  * with the network name @name. The data field of the #GstMpegtsDescriptor
101  * will be allocated, and transferred to the caller.
102  *
103  * Returns: (transfer full): the #GstMpegtsDescriptor or %NULL on fail
104  */
105 GstMpegtsDescriptor *
gst_mpegts_descriptor_from_dvb_network_name(const gchar * name)106 gst_mpegts_descriptor_from_dvb_network_name (const gchar * name)
107 {
108   GstMpegtsDescriptor *descriptor;
109   guint8 *converted_name;
110   gsize size;
111 
112   g_return_val_if_fail (name != NULL, NULL);
113 
114   converted_name = dvb_text_from_utf8 (name, &size);
115 
116   if (size >= 256) {
117     g_free (converted_name);
118     return NULL;
119   }
120 
121   if (!converted_name) {
122     GST_WARNING ("Could not find proper encoding for string `%s`", name);
123     return NULL;
124   }
125 
126   descriptor = _new_descriptor (GST_MTS_DESC_DVB_NETWORK_NAME, size);
127   memcpy (descriptor->data + 2, converted_name, size);
128   g_free (converted_name);
129 
130   return descriptor;
131 }
132 
133 /* GST_MTS_DESC_DVB_SERVICE_LIST (0x41) */
134 
135 DEFINE_STATIC_COPY_FUNCTION (GstMpegtsDVBServiceListItem,
136     gst_mpegts_dvb_service_list_item);
137 
138 DEFINE_STATIC_FREE_FUNCTION (GstMpegtsDVBServiceListItem,
139     gst_mpegts_dvb_service_list_item);
140 
141 G_DEFINE_BOXED_TYPE (GstMpegtsDVBServiceListItem,
142     gst_mpegts_dvb_service_list_item,
143     (GBoxedCopyFunc) _gst_mpegts_dvb_service_list_item_copy,
144     (GFreeFunc) _gst_mpegts_dvb_service_list_item_free);
145 
146 /**
147  * gst_mpegts_descriptor_parse_dvb_service_list:
148  * @descriptor: a %GST_MTS_DESC_DVB_SERVICE_LIST #GstMpegtsDescriptor
149  * @list: (out) (transfer full) (element-type GstMpegtsDVBServiceListItem):
150  * the list of services
151  *
152  * Parses out a list of services from the @descriptor:
153  *
154  * Returns: %TRUE if the parsing happened correctly, else %FALSE.
155  */
156 gboolean
gst_mpegts_descriptor_parse_dvb_service_list(const GstMpegtsDescriptor * descriptor,GPtrArray ** list)157 gst_mpegts_descriptor_parse_dvb_service_list (const GstMpegtsDescriptor *
158     descriptor, GPtrArray ** list)
159 {
160   guint8 *data, i;
161 
162   g_return_val_if_fail (descriptor != NULL && list != NULL, FALSE);
163   /* a entry has 3 bytes, 2 for service id, 1 for service type */
164   __common_desc_checks (descriptor, GST_MTS_DESC_DVB_SERVICE_LIST, 3, FALSE);
165 
166   data = (guint8 *) descriptor->data + 2;
167 
168   *list = g_ptr_array_new_with_free_func ((GDestroyNotify)
169       _gst_mpegts_dvb_service_list_item_free);
170 
171   for (i = 0; i < descriptor->length - 2; i += 3) {
172     GstMpegtsDVBServiceListItem *item =
173         g_slice_new0 (GstMpegtsDVBServiceListItem);
174 
175     g_ptr_array_add (*list, item);
176     item->service_id = GST_READ_UINT16_BE (data);
177     data += 2;
178 
179     item->type = *data;
180     data += 1;
181   }
182 
183   return TRUE;
184 }
185 
186 /* GST_MTS_DESC_DVB_STUFFING (0x42) */
187 /**
188  * gst_mpegts_descriptor_parse_dvb_stuffing:
189  * @descriptor: a %GST_MTS_DESC_DVB_STUFFING #GstMpegtsDescriptor
190  * @stuffing_bytes: (out) (transfer full): the stuffing bytes
191  *
192  * Parses out the stuffing bytes from the @descriptor.
193  *
194  * Returns: %TRUE if the parsing happened correctly, else %FALSE.
195  */
196 gboolean
gst_mpegts_descriptor_parse_dvb_stuffing(const GstMpegtsDescriptor * descriptor,guint8 ** stuffing_bytes)197 gst_mpegts_descriptor_parse_dvb_stuffing (const GstMpegtsDescriptor *
198     descriptor, guint8 ** stuffing_bytes)
199 {
200   guint8 *data;
201 
202   g_return_val_if_fail (descriptor != NULL && stuffing_bytes != NULL, FALSE);
203   __common_desc_check_base (descriptor, GST_MTS_DESC_DVB_STUFFING, FALSE);
204 
205   data = (guint8 *) descriptor->data + 2;
206 
207   *stuffing_bytes = g_memdup (data, descriptor->length);
208 
209   return TRUE;
210 }
211 
212 /* GST_MTS_DESC_DVB_SATELLITE_DELIVERY_SYSTEM (0x43) */
213 
214 DEFINE_STATIC_COPY_FUNCTION (GstMpegtsSatelliteDeliverySystemDescriptor,
215     gst_mpegts_satellite_delivery_system_descriptor);
216 
217 DEFINE_STATIC_FREE_FUNCTION (GstMpegtsSatelliteDeliverySystemDescriptor,
218     gst_mpegts_satellite_delivery_system_descriptor);
219 
220 G_DEFINE_BOXED_TYPE (GstMpegtsSatelliteDeliverySystemDescriptor,
221     gst_mpegts_satellite_delivery_system_descriptor,
222     (GBoxedCopyFunc) _gst_mpegts_satellite_delivery_system_descriptor_copy,
223     (GFreeFunc) _gst_mpegts_satellite_delivery_system_descriptor_free);
224 
225 /**
226  * gst_mpegts_descriptor_parse_satellite_delivery_system:
227  * @descriptor: a %GST_MTS_DESC_DVB_SATELLITE_DELIVERY_SYSTEM #GstMpegtsDescriptor
228  * @res: (out) (transfer none): the #GstMpegtsSatelliteDeliverySystemDescriptor to fill
229  *
230  * Extracts the satellite delivery system information from @descriptor.
231  *
232  * Returns: %TRUE if parsing succeeded, else %FALSE.
233  */
234 gboolean
gst_mpegts_descriptor_parse_satellite_delivery_system(const GstMpegtsDescriptor * descriptor,GstMpegtsSatelliteDeliverySystemDescriptor * res)235 gst_mpegts_descriptor_parse_satellite_delivery_system (const GstMpegtsDescriptor
236     * descriptor, GstMpegtsSatelliteDeliverySystemDescriptor * res)
237 {
238   guint8 *data;
239   guint8 tmp;
240 
241   g_return_val_if_fail (descriptor != NULL && res != NULL, FALSE);
242   /* This descriptor is always 11 bytes long */
243   __common_desc_checks_exact (descriptor,
244       GST_MTS_DESC_DVB_SATELLITE_DELIVERY_SYSTEM, 11, FALSE);
245 
246   data = (guint8 *) descriptor->data + 2;
247 
248   /* BCD coded frequency in GHz (decimal point occurs after the 3rd character)
249    * So direct BCD gives us units of (GHz / 100 000) = 10 kHz*/
250   res->frequency = BCD_32 (data) * 10;
251   data += 4;
252   /* BCD codec position in degrees (float pointer after the 3rd character) */
253   res->orbital_position = (BCD_16 (data)) / 10.0;
254   data += 2;
255 
256   tmp = *data;
257   res->west_east = (tmp & 0x80) == 0x80;
258   res->polarization = (tmp >> 7) & 0x03;
259   res->modulation_system = (tmp & 0x04) == 0x04;
260   if (res->modulation_system)
261     res->roll_off = (tmp >> 3 & 0x03);
262   else
263     res->roll_off = GST_MPEGTS_ROLLOFF_AUTO;
264   switch (tmp & 0x03) {
265     case 0x00:
266       res->modulation_type = GST_MPEGTS_MODULATION_QAM_AUTO;
267       break;
268     case 0x01:
269       res->modulation_type = GST_MPEGTS_MODULATION_QPSK;
270       break;
271     case 0x02:
272       res->modulation_type = GST_MPEGTS_MODULATION_PSK_8;
273       break;
274     case 0x03:
275       res->modulation_type = GST_MPEGTS_MODULATION_QAM_16;
276       break;
277     default:
278       res->modulation_type = GST_MPEGTS_MODULATION_QAM_AUTO;
279       break;
280   }
281   data += 1;
282   /* symbol_rate is in Msymbols/ (decimal point occurs after 3rd character) */
283   /* So direct BCD gives us units of (Msymbol / 10 000) = 100 sym/s */
284   res->symbol_rate = BCD_28 (data) * 100;
285   data += 3;
286   /* fec_inner */
287   switch (*data >> 4) {
288     case 0x01:
289       res->fec_inner = GST_MPEGTS_FEC_1_2;
290       break;
291     case 0x02:
292       res->fec_inner = GST_MPEGTS_FEC_2_3;
293       break;
294     case 0x03:
295       res->fec_inner = GST_MPEGTS_FEC_3_4;
296       break;
297     case 0x04:
298       res->fec_inner = GST_MPEGTS_FEC_5_6;
299       break;
300     case 0x05:
301       res->fec_inner = GST_MPEGTS_FEC_7_8;
302       break;
303     case 0x06:
304       res->fec_inner = GST_MPEGTS_FEC_8_9;
305       break;
306     case 0x07:
307       res->fec_inner = GST_MPEGTS_FEC_3_5;
308       break;
309     case 0x08:
310       res->fec_inner = GST_MPEGTS_FEC_4_5;
311       break;
312     case 0x09:
313       res->fec_inner = GST_MPEGTS_FEC_9_10;
314       break;
315     case 0x0f:
316       res->fec_inner = GST_MPEGTS_FEC_NONE;
317       break;
318     default:
319       res->fec_inner = GST_MPEGTS_FEC_AUTO;
320       break;
321   }
322 
323   return TRUE;
324 }
325 
326 /* GST_MTS_DESC_DVB_CABLE_DELIVERY_SYSTEM (0x44) */
327 
328 DEFINE_STATIC_COPY_FUNCTION (GstMpegtsCableDeliverySystemDescriptor,
329     gst_mpegts_dvb_cable_delivery_system_descriptor);
330 
gst_mpegts_dvb_cable_delivery_system_descriptor_free(GstMpegtsCableDeliverySystemDescriptor * source)331 void gst_mpegts_dvb_cable_delivery_system_descriptor_free
332     (GstMpegtsCableDeliverySystemDescriptor * source)
333 {
334   g_slice_free (GstMpegtsCableDeliverySystemDescriptor, source);
335 }
336 
337 G_DEFINE_BOXED_TYPE (GstMpegtsCableDeliverySystemDescriptor,
338     gst_mpegts_dvb_cable_delivery_system_descriptor,
339     (GBoxedCopyFunc) _gst_mpegts_dvb_cable_delivery_system_descriptor_copy,
340     (GFreeFunc) gst_mpegts_dvb_cable_delivery_system_descriptor_free);
341 
342 /**
343  * gst_mpegts_descriptor_parse_cable_delivery_system:
344  * @descriptor: a %GST_MTS_DESC_DVB_CABLE_DELIVERY_SYSTEM #GstMpegtsDescriptor
345  * @res: (out) (transfer none): the #GstMpegtsCableDeliverySystemDescriptor to fill
346  *
347  * Extracts the cable delivery system information from @descriptor.
348  *
349  * Returns: %TRUE if parsing succeeded, else %FALSE.
350  */
351 gboolean
gst_mpegts_descriptor_parse_cable_delivery_system(const GstMpegtsDescriptor * descriptor,GstMpegtsCableDeliverySystemDescriptor * res)352 gst_mpegts_descriptor_parse_cable_delivery_system (const GstMpegtsDescriptor *
353     descriptor, GstMpegtsCableDeliverySystemDescriptor * res)
354 {
355   guint8 *data;
356 
357   g_return_val_if_fail (descriptor != NULL && res != NULL, FALSE);
358   /* This descriptor is always 11 bytes long */
359   __common_desc_checks_exact (descriptor,
360       GST_MTS_DESC_DVB_CABLE_DELIVERY_SYSTEM, 11, FALSE);
361 
362   data = (guint8 *) descriptor->data + 2;
363   /* BCD in MHz, decimal place after the fourth character */
364   res->frequency = BCD_32 (data) * 100;
365   data += 5;
366   /* fec_out (4bits) */
367   res->outer_fec = *data++ & 0x0f;
368   switch (*data) {
369     case 0x00:
370       res->modulation = GST_MPEGTS_MODULATION_NONE;
371       break;
372     case 0x01:
373       res->modulation = GST_MPEGTS_MODULATION_QAM_16;
374       break;
375     case 0x02:
376       res->modulation = GST_MPEGTS_MODULATION_QAM_32;
377       break;
378     case 0x03:
379       res->modulation = GST_MPEGTS_MODULATION_QAM_64;
380       break;
381     case 0x04:
382       res->modulation = GST_MPEGTS_MODULATION_QAM_128;
383       break;
384     case 0x05:
385       res->modulation = GST_MPEGTS_MODULATION_QAM_256;
386       break;
387     default:
388       GST_WARNING ("Unsupported cable modulation type: 0x%02x", *data);
389       res->modulation = GST_MPEGTS_MODULATION_NONE;
390       break;
391   }
392 
393   data += 1;
394   /* symbol_rate is in Msymbols/ (decimal point occurs after 3rd character) */
395   /* So direct BCD gives us units of (Msymbol / 10 000) = 100 sym/s */
396   res->symbol_rate = BCD_28 (data) * 100;
397   data += 3;
398   /* fec_inner */
399   switch (*data & 0xf) {
400     case 0x00:
401       res->fec_inner = GST_MPEGTS_FEC_AUTO;
402       break;
403     case 0x01:
404       res->fec_inner = GST_MPEGTS_FEC_1_2;
405       break;
406     case 0x02:
407       res->fec_inner = GST_MPEGTS_FEC_2_3;
408       break;
409     case 0x03:
410       res->fec_inner = GST_MPEGTS_FEC_3_4;
411       break;
412     case 0x04:
413       res->fec_inner = GST_MPEGTS_FEC_5_6;
414       break;
415     case 0x05:
416       res->fec_inner = GST_MPEGTS_FEC_7_8;
417       break;
418     case 0x06:
419       res->fec_inner = GST_MPEGTS_FEC_8_9;
420       break;
421     case 0x07:
422       res->fec_inner = GST_MPEGTS_FEC_3_5;
423       break;
424     case 0x08:
425       res->fec_inner = GST_MPEGTS_FEC_4_5;
426       break;
427     case 0x09:
428       res->fec_inner = GST_MPEGTS_FEC_9_10;
429       break;
430     case 0x0f:
431       res->fec_inner = GST_MPEGTS_FEC_NONE;
432       break;
433     default:
434       res->fec_inner = GST_MPEGTS_FEC_AUTO;
435       break;
436   }
437 
438   return TRUE;
439 }
440 
441 /* GST_MTS_DESC_DVB_BOUQUET_NAME (0x47) */
442 /**
443  * gst_mpegts_descriptor_parse_dvb_bouquet_name:
444  * @bouquet_name: (out) (transfer full) (allow-none): the bouquet name
445  *
446  * Extracts the bouquet name from @descriptor.
447  *
448  * Returns: %TRUE if parsing succeeded, else %FALSE.
449  */
450 gboolean
gst_mpegts_descriptor_parse_dvb_bouquet_name(const GstMpegtsDescriptor * descriptor,gchar ** bouquet_name)451 gst_mpegts_descriptor_parse_dvb_bouquet_name (const GstMpegtsDescriptor *
452     descriptor, gchar ** bouquet_name)
453 {
454   guint8 *data;
455 
456   g_return_val_if_fail (descriptor != NULL && bouquet_name != NULL, FALSE);
457   __common_desc_checks (descriptor, GST_MTS_DESC_DVB_BOUQUET_NAME, 1, FALSE);
458 
459   data = (guint8 *) descriptor->data + 2;
460 
461   *bouquet_name =
462       get_encoding_and_convert ((const gchar *) data, descriptor->length);
463 
464   return TRUE;
465 }
466 
467 /* GST_MTS_DESC_DVB_SERVICE (0x48) */
468 /**
469  * gst_mpegts_descriptor_parse_dvb_service:
470  * @descriptor: a %GST_MTS_DESC_DVB_SERVICE #GstMpegtsDescriptor
471  * @service_type: (out) (allow-none): the service type
472  * @service_name: (out) (transfer full) (allow-none): the service name
473  * @provider_name: (out) (transfer full) (allow-none): the provider name
474  *
475  * Extracts the dvb service information from @descriptor.
476  *
477  * Returns: %TRUE if parsing succeeded, else %FALSE.
478  */
479 gboolean
gst_mpegts_descriptor_parse_dvb_service(const GstMpegtsDescriptor * descriptor,GstMpegtsDVBServiceType * service_type,gchar ** service_name,gchar ** provider_name)480 gst_mpegts_descriptor_parse_dvb_service (const GstMpegtsDescriptor *
481     descriptor, GstMpegtsDVBServiceType * service_type, gchar ** service_name,
482     gchar ** provider_name)
483 {
484   guint8 *data;
485 
486   g_return_val_if_fail (descriptor != NULL, FALSE);
487   /* Need at least 3 bytes (type and 2 bytes for the string length) */
488   __common_desc_checks (descriptor, GST_MTS_DESC_DVB_SERVICE, 3, FALSE);
489 
490   data = (guint8 *) descriptor->data + 2;
491 
492   if (service_type)
493     *service_type = *data;
494   data += 1;
495   if (provider_name)
496     *provider_name = get_encoding_and_convert ((const gchar *) data + 1, *data);
497   data += *data + 1;
498   if (service_name)
499     *service_name = get_encoding_and_convert ((const gchar *) data + 1, *data);
500 
501   return TRUE;
502 }
503 
504 /**
505  * gst_mpegts_descriptor_from_dvb_service:
506  * @service_type: Service type defined as a #GstMpegtsDVBServiceType
507  * @service_name: (allow-none): Name of the service
508  * @service_provider: (allow-none): Name of the service provider
509  *
510  * Fills a #GstMpegtsDescriptor to be a %GST_MTS_DESC_DVB_SERVICE.
511  * The data field of the #GstMpegtsDescriptor will be allocated,
512  * and transferred to the caller.
513  *
514  * Returns: (transfer full): the #GstMpegtsDescriptor or %NULL on fail
515  */
516 GstMpegtsDescriptor *
gst_mpegts_descriptor_from_dvb_service(GstMpegtsDVBServiceType service_type,const gchar * service_name,const gchar * service_provider)517 gst_mpegts_descriptor_from_dvb_service (GstMpegtsDVBServiceType service_type,
518     const gchar * service_name, const gchar * service_provider)
519 {
520   GstMpegtsDescriptor *descriptor = NULL;
521   guint8 *conv_provider_name = NULL, *conv_service_name = NULL;
522   gsize provider_size = 0, service_size = 0;
523   guint8 *data;
524 
525   if (service_provider) {
526     conv_provider_name = dvb_text_from_utf8 (service_provider, &provider_size);
527 
528     if (!conv_provider_name) {
529       GST_WARNING ("Could not find proper encoding for string `%s`",
530           service_provider);
531       goto beach;
532     }
533   }
534 
535   if (provider_size >= 256) {
536     GST_WARNING ("Service provider string too big (%" G_GSIZE_FORMAT " > 256)",
537         provider_size);
538     goto beach;
539   }
540 
541   if (service_name) {
542     conv_service_name = dvb_text_from_utf8 (service_name, &service_size);
543 
544     if (!conv_service_name) {
545       GST_WARNING ("Could not find proper encoding for string `%s`",
546           service_name);
547       goto beach;
548     }
549   }
550 
551   if (service_size >= 256) {
552     GST_WARNING ("Service name string too big (%" G_GSIZE_FORMAT " > 256)",
553         service_size);
554     goto beach;
555   }
556 
557   descriptor =
558       _new_descriptor (GST_MTS_DESC_DVB_SERVICE,
559       3 + provider_size + service_size);
560 
561   data = descriptor->data + 2;
562   *data++ = service_type;
563   *data++ = provider_size;
564   if (conv_provider_name)
565     memcpy (data, conv_provider_name, provider_size);
566 
567   data += provider_size;
568   *data++ = service_size;
569   if (conv_service_name)
570     memcpy (data, conv_service_name, service_size);
571 
572 beach:
573   g_free (conv_service_name);
574   g_free (conv_provider_name);
575 
576   return descriptor;
577 }
578 
579 /* GST_MTS_DESC_DVB_LINKAGE (0x4A) */
580 static GstMpegtsDVBLinkageDescriptor *
_gst_mpegts_dvb_linkage_descriptor_copy(GstMpegtsDVBLinkageDescriptor * source)581 _gst_mpegts_dvb_linkage_descriptor_copy (GstMpegtsDVBLinkageDescriptor * source)
582 {
583   GstMpegtsDVBLinkageDescriptor *copy;
584 
585   copy = g_slice_dup (GstMpegtsDVBLinkageDescriptor, source);
586 
587   switch (source->linkage_type) {
588     case GST_MPEGTS_DVB_LINKAGE_MOBILE_HAND_OVER:
589       copy->linkage_data = g_slice_dup (GstMpegtsDVBLinkageMobileHandOver,
590           source->linkage_data);
591       break;
592     case GST_MPEGTS_DVB_LINKAGE_EVENT:
593       copy->linkage_data = g_slice_dup (GstMpegtsDVBLinkageEvent,
594           source->linkage_data);
595       break;
596     case GST_MPEGTS_DVB_LINKAGE_EXTENDED_EVENT:
597       copy->linkage_data = g_ptr_array_ref (source->linkage_data);
598       break;
599     default:
600       break;
601   }
602 
603   copy->private_data_bytes = g_memdup (source->private_data_bytes,
604       source->private_data_length);
605 
606   return copy;
607 }
608 
609 void
gst_mpegts_dvb_linkage_descriptor_free(GstMpegtsDVBLinkageDescriptor * source)610 gst_mpegts_dvb_linkage_descriptor_free (GstMpegtsDVBLinkageDescriptor * source)
611 {
612   if (source->linkage_data)
613     switch (source->linkage_type) {
614       case GST_MPEGTS_DVB_LINKAGE_MOBILE_HAND_OVER:
615         g_slice_free (GstMpegtsDVBLinkageMobileHandOver, source->linkage_data);
616         break;
617       case GST_MPEGTS_DVB_LINKAGE_EVENT:
618         g_slice_free (GstMpegtsDVBLinkageEvent, source->linkage_data);
619         break;
620       case GST_MPEGTS_DVB_LINKAGE_EXTENDED_EVENT:
621         g_ptr_array_unref (source->linkage_data);
622         break;
623       default:
624         break;
625     }
626 
627   g_free (source->private_data_bytes);
628   g_slice_free (GstMpegtsDVBLinkageDescriptor, source);
629 }
630 
631 G_DEFINE_BOXED_TYPE (GstMpegtsDVBLinkageDescriptor,
632     gst_mpegts_dvb_linkage_descriptor,
633     (GBoxedCopyFunc) _gst_mpegts_dvb_linkage_descriptor_copy,
634     (GFreeFunc) gst_mpegts_dvb_linkage_descriptor_free);
635 
636 DEFINE_STATIC_COPY_FUNCTION (GstMpegtsDVBLinkageMobileHandOver,
637     gst_mpegts_dvb_linkage_mobile_hand_over);
638 
639 DEFINE_STATIC_FREE_FUNCTION (GstMpegtsDVBLinkageMobileHandOver,
640     gst_mpegts_dvb_linkage_mobile_hand_over);
641 
642 G_DEFINE_BOXED_TYPE (GstMpegtsDVBLinkageMobileHandOver,
643     gst_mpegts_dvb_linkage_mobile_hand_over,
644     (GBoxedCopyFunc) _gst_mpegts_dvb_linkage_mobile_hand_over_copy,
645     (GFreeFunc) _gst_mpegts_dvb_linkage_mobile_hand_over_free);
646 
647 DEFINE_STATIC_COPY_FUNCTION (GstMpegtsDVBLinkageEvent,
648     gst_mpegts_dvb_linkage_event);
649 
650 DEFINE_STATIC_FREE_FUNCTION (GstMpegtsDVBLinkageEvent,
651     gst_mpegts_dvb_linkage_event);
652 
653 G_DEFINE_BOXED_TYPE (GstMpegtsDVBLinkageEvent,
654     gst_mpegts_dvb_linkage_event,
655     (GBoxedCopyFunc) _gst_mpegts_dvb_linkage_event_copy,
656     (GFreeFunc) _gst_mpegts_dvb_linkage_event_free);
657 
658 DEFINE_STATIC_COPY_FUNCTION (GstMpegtsDVBLinkageExtendedEvent,
659     gst_mpegts_dvb_linkage_extended_event);
660 
661 DEFINE_STATIC_FREE_FUNCTION (GstMpegtsDVBLinkageExtendedEvent,
662     gst_mpegts_dvb_linkage_extended_event);
663 
664 G_DEFINE_BOXED_TYPE (GstMpegtsDVBLinkageExtendedEvent,
665     gst_mpegts_dvb_linkage_extended_event,
666     (GBoxedCopyFunc) _gst_mpegts_dvb_linkage_extended_event_copy,
667     (GFreeFunc) _gst_mpegts_dvb_linkage_extended_event_free);
668 
669 /**
670  * gst_mpegts_descriptor_parse_dvb_linkage:
671  * @descriptor: a %GST_MTS_DESC_DVB_LINKAGE #GstMpegtsDescriptor
672  * @res: (out) (transfer full): the #GstMpegtsDVBLinkageDescriptor to fill
673  *
674  * Extracts the DVB linkage information from @descriptor.
675  *
676  * Returns: %TRUE if parsing succeeded, else %FALSE.
677  */
678 gboolean
gst_mpegts_descriptor_parse_dvb_linkage(const GstMpegtsDescriptor * descriptor,GstMpegtsDVBLinkageDescriptor ** desc)679 gst_mpegts_descriptor_parse_dvb_linkage (const GstMpegtsDescriptor * descriptor,
680     GstMpegtsDVBLinkageDescriptor ** desc)
681 {
682   guint i;
683   guint8 *data, *end;
684   GstMpegtsDVBLinkageDescriptor *res;
685 
686   g_return_val_if_fail (descriptor != NULL && desc != NULL, FALSE);
687   __common_desc_checks (descriptor, GST_MTS_DESC_DVB_LINKAGE, 7, FALSE);
688 
689   data = (guint8 *) descriptor->data + 2;
690   end = data + descriptor->length;
691 
692   res = g_slice_new0 (GstMpegtsDVBLinkageDescriptor);
693 
694   res->transport_stream_id = GST_READ_UINT16_BE (data);
695   data += 2;
696 
697   res->original_network_id = GST_READ_UINT16_BE (data);
698   data += 2;
699 
700   res->service_id = GST_READ_UINT16_BE (data);
701   data += 2;
702 
703   res->linkage_type = *data;
704   data += 1;
705 
706   switch (res->linkage_type) {
707     case GST_MPEGTS_DVB_LINKAGE_MOBILE_HAND_OVER:{
708       GstMpegtsDVBLinkageMobileHandOver *hand_over;
709 
710       if (end - data < 1)
711         goto fail;
712 
713       hand_over = g_slice_new0 (GstMpegtsDVBLinkageMobileHandOver);
714       res->linkage_data = (gpointer) hand_over;
715 
716       hand_over->origin_type = (*data) & 0x01;
717       hand_over->hand_over_type = (*data >> 4) & 0x0f;
718       data += 1;
719 
720       if (hand_over->hand_over_type ==
721           GST_MPEGTS_DVB_LINKAGE_HAND_OVER_IDENTICAL
722           || hand_over->hand_over_type ==
723           GST_MPEGTS_DVB_LINKAGE_HAND_OVER_LOCAL_VARIATION
724           || hand_over->hand_over_type ==
725           GST_MPEGTS_DVB_LINKAGE_HAND_OVER_ASSOCIATED) {
726         if (end - data < 2)
727           goto fail;
728 
729         hand_over->network_id = GST_READ_UINT16_BE (data);
730         data += 2;
731       }
732 
733       if (hand_over->origin_type == 0) {
734         if (end - data < 2)
735           goto fail;
736 
737         hand_over->initial_service_id = GST_READ_UINT16_BE (data);
738         data += 2;
739       }
740       break;
741     }
742     case GST_MPEGTS_DVB_LINKAGE_EVENT:{
743       GstMpegtsDVBLinkageEvent *event;
744 
745       if (end - data < 3)
746         goto fail;
747 
748       event = g_slice_new0 (GstMpegtsDVBLinkageEvent);
749       res->linkage_data = (gpointer) event;
750 
751       event->target_event_id = GST_READ_UINT16_BE (data);
752       data += 2;
753       event->target_listed = *data & 0x01;
754       event->event_simulcast = (*data >> 1) & 0x01;
755       data += 1;
756       break;
757     }
758     case GST_MPEGTS_DVB_LINKAGE_EXTENDED_EVENT:{
759       GPtrArray *ext_events;
760       ext_events = g_ptr_array_new_with_free_func ((GDestroyNotify)
761           _gst_mpegts_dvb_linkage_extended_event_free);
762 
763       res->linkage_data = (gpointer) ext_events;
764 
765       for (i = 0; i < *data++;) {
766         GstMpegtsDVBLinkageExtendedEvent *ext_event;
767 
768         if (end - data < 3)
769           goto fail;
770 
771         ext_event = g_slice_new0 (GstMpegtsDVBLinkageExtendedEvent);
772         g_ptr_array_add (res->linkage_data, ext_event);
773 
774         ext_event->target_event_id = GST_READ_UINT16_BE (data);
775         data += 2;
776         i += 2;
777 
778         ext_event->target_listed = *data & 0x01;
779         ext_event->event_simulcast = (*data >> 1) & 0x01;
780         ext_event->link_type = (*data >> 3) & 0x03;
781         ext_event->target_id_type = (*data >> 5) & 0x03;
782         ext_event->original_network_id_flag = (*data >> 6) & 0x01;
783         ext_event->service_id_flag = (*data >> 7) & 0x01;
784         data += 1;
785         i += 1;
786 
787         if (ext_event->target_id_type == 3) {
788           if (end - data < 2)
789             goto fail;
790 
791           ext_event->user_defined_id = GST_READ_UINT16_BE (data);
792           data += 2;
793           i += 2;
794         } else {
795           if (ext_event->target_id_type == 1) {
796             if (end - data < 2)
797               goto fail;
798 
799             ext_event->target_transport_stream_id = GST_READ_UINT16_BE (data);
800             data += 2;
801             i += 2;
802           }
803           if (ext_event->original_network_id_flag) {
804             if (end - data < 2)
805               goto fail;
806 
807             ext_event->target_original_network_id = GST_READ_UINT16_BE (data);
808             data += 2;
809             i += 2;
810           }
811           if (ext_event->service_id_flag) {
812             if (end - data < 2)
813               goto fail;
814 
815             ext_event->target_service_id = GST_READ_UINT16_BE (data);
816             data += 2;
817             i += 2;
818           }
819         }
820       }
821       break;
822     }
823     default:
824       break;
825   }
826 
827   res->private_data_length = end - data;
828   res->private_data_bytes = g_memdup (data, res->private_data_length);
829 
830   *desc = res;
831 
832   return TRUE;
833 
834 fail:
835   gst_mpegts_dvb_linkage_descriptor_free (res);
836   return FALSE;
837 }
838 
839 /**
840  * gst_mpegts_dvb_linkage_descriptor_get_mobile_hand_over:
841  * @desc: the #GstMpegtsDVBLinkageDescriptor
842  *
843  * Returns: The #GstMpegtsDVBLinkageMobileHandOver or %NULL if an error happened
844  */
845 const GstMpegtsDVBLinkageMobileHandOver *
gst_mpegts_dvb_linkage_descriptor_get_mobile_hand_over(const GstMpegtsDVBLinkageDescriptor * desc)846 gst_mpegts_dvb_linkage_descriptor_get_mobile_hand_over (const
847     GstMpegtsDVBLinkageDescriptor * desc)
848 {
849   g_return_val_if_fail (desc != NULL, NULL);
850   g_return_val_if_fail (desc->linkage_type ==
851       GST_MPEGTS_DVB_LINKAGE_MOBILE_HAND_OVER, NULL);
852 
853   return (const GstMpegtsDVBLinkageMobileHandOver *) desc->linkage_data;
854 }
855 
856 /**
857  * gst_mpegts_dvb_linkage_descriptor_get_event:
858  * @desc: the #GstMpegtsDVBLinkageDescriptor
859  *
860  * Returns: The #GstMpegtsDVBLinkageEvent or %NULL if an error happened
861  */
862 const GstMpegtsDVBLinkageEvent *
gst_mpegts_dvb_linkage_descriptor_get_event(const GstMpegtsDVBLinkageDescriptor * desc)863 gst_mpegts_dvb_linkage_descriptor_get_event (const GstMpegtsDVBLinkageDescriptor
864     * desc)
865 {
866   g_return_val_if_fail (desc != NULL, NULL);
867   g_return_val_if_fail (desc->linkage_type ==
868       GST_MPEGTS_DVB_LINKAGE_EVENT, NULL);
869 
870   return (const GstMpegtsDVBLinkageEvent *) desc->linkage_data;
871 }
872 
873 /**
874  * gst_mpegts_dvb_linkage_descriptor_get_extended_event:
875  * @desc: the #GstMpegtsDVBLinkageDescriptor
876  *
877  * Returns: (element-type GstMpegtsDVBLinkageExtendedEvent): an #GstMpegtsDVBLinkageExtendedEvent array or %NULL if an error happened
878  */
879 const GPtrArray *
gst_mpegts_dvb_linkage_descriptor_get_extended_event(const GstMpegtsDVBLinkageDescriptor * desc)880 gst_mpegts_dvb_linkage_descriptor_get_extended_event (const
881     GstMpegtsDVBLinkageDescriptor * desc)
882 {
883   g_return_val_if_fail (desc != NULL, NULL);
884   g_return_val_if_fail (desc->linkage_type ==
885       GST_MPEGTS_DVB_LINKAGE_EXTENDED_EVENT, NULL);
886 
887   return (const GPtrArray *) desc->linkage_data;
888 }
889 
890 /* GST_MTS_DESC_DVB_SHORT_EVENT (0x4D) */
891 /**
892  * gst_mpegts_descriptor_parse_dvb_short_event:
893  * @descriptor: a %GST_MTS_DESC_DVB_SHORT_EVENT #GstMpegtsDescriptor
894  * @language_code: (out) (transfer full) (allow-none): the language code
895  * @event_name: (out) (transfer full) (allow-none): the event name
896  * @text: (out) (transfer full) (allow-none): the event text
897  *
898  * Extracts the DVB short event information from @descriptor.
899  *
900  * Returns: %TRUE if parsing succeeded, else %FALSE.
901  */
902 gboolean
gst_mpegts_descriptor_parse_dvb_short_event(const GstMpegtsDescriptor * descriptor,gchar ** language_code,gchar ** event_name,gchar ** text)903 gst_mpegts_descriptor_parse_dvb_short_event (const GstMpegtsDescriptor *
904     descriptor, gchar ** language_code, gchar ** event_name, gchar ** text)
905 {
906   guint8 *data;
907 
908   g_return_val_if_fail (descriptor != NULL, FALSE);
909   /* Need at least 5 bytes (3 for language code, 2 for each string length) */
910   __common_desc_checks (descriptor, GST_MTS_DESC_DVB_SHORT_EVENT, 5, FALSE);
911 
912   data = (guint8 *) descriptor->data + 2;
913 
914   if (language_code)
915     *language_code = convert_lang_code (data);
916 
917   data += 3;
918   if (event_name)
919     *event_name = get_encoding_and_convert ((const gchar *) data + 1, *data);
920   data += *data + 1;
921   if (text)
922     *text = get_encoding_and_convert ((const gchar *) data + 1, *data);
923   return TRUE;
924 }
925 
926 /* GST_MTS_DESC_DVB_TELETEXT (0x56) */
927 /**
928  * gst_mpegts_descriptor_parse_dvb_teletext_idx:
929  * @descriptor: a %GST_MTS_DESC_DVB_TELETEXT #GstMpegtsDescriptor
930  * @idx: The id of the teletext to get
931  * @language_code: (out) (transfer full) (allow-none): a null-terminated string
932  * @teletext_type: (out) (allow-none): #GstMpegtsDVBTeletextType
933  * @magazine_number: (out) (allow-none):
934  * @page_number: (out) (allow-none):
935  *
936  * Parses teletext number @idx in the @descriptor. The language is in ISO639 format.
937  *
938  * Returns: FALSE on out-of-bounds and errors
939  */
940 gboolean
gst_mpegts_descriptor_parse_dvb_teletext_idx(const GstMpegtsDescriptor * descriptor,guint idx,gchar ** language_code,GstMpegtsDVBTeletextType * teletext_type,guint8 * magazine_number,guint8 * page_number)941 gst_mpegts_descriptor_parse_dvb_teletext_idx (const GstMpegtsDescriptor *
942     descriptor, guint idx, gchar ** language_code,
943     GstMpegtsDVBTeletextType * teletext_type, guint8 * magazine_number,
944     guint8 * page_number)
945 {
946   guint8 *data;
947 
948   g_return_val_if_fail (descriptor != NULL, FALSE);
949   __common_desc_check_base (descriptor, GST_MTS_DESC_DVB_TELETEXT, FALSE);
950 
951   if (descriptor->length / 5 <= idx)
952     return FALSE;
953 
954   data = (guint8 *) descriptor->data + 2 + idx * 5;
955 
956   if (language_code)
957     *language_code = convert_lang_code (data);
958 
959   if (teletext_type)
960     *teletext_type = data[3] >> 3;
961 
962   if (magazine_number)
963     *magazine_number = data[3] & 0x07;
964 
965   if (page_number)
966     *page_number = data[4];
967 
968   return TRUE;
969 }
970 
971 /**
972  * gst_mpegts_descriptor_parse_dvb_teletext_nb:
973  * @descriptor: a %GST_MTS_DESC_DVB_TELETEXT #GstMpegtsDescriptor
974  *
975  * Find the number of teletext entries in @descriptor
976  *
977  * Returns: Number of teletext entries
978  */
979 guint
gst_mpegts_descriptor_parse_dvb_teletext_nb(const GstMpegtsDescriptor * descriptor)980 gst_mpegts_descriptor_parse_dvb_teletext_nb (const GstMpegtsDescriptor *
981     descriptor)
982 {
983   g_return_val_if_fail (descriptor != NULL, 0);
984   __common_desc_check_base (descriptor, GST_MTS_DESC_DVB_TELETEXT, FALSE);
985 
986   return descriptor->length / 5;
987 }
988 
989 /* GST_MTS_DESC_DVB_SUBTITLING (0x59) */
990 
991 /**
992  * gst_mpegts_descriptor_parse_dvb_subtitling_idx:
993  * @descriptor: a %GST_MTS_DESC_DVB_SUBTITLING #GstMpegtsDescriptor
994  * @idx: Table id of the entry to parse
995  * @lang: (out) (transfer full): the language code
996  * @type: (out) (transfer none) (allow-none): the type of subtitling
997  * @composition_page_id: (out) (transfer none) (allow-none): the composition page id
998  * @ancillary_page_id: (out) (transfer none) (allow-none): the ancillary page id
999  *
1000  * Extracts the DVB subtitling informatio from specific table id in @descriptor.
1001  *
1002  * Note: Use #gst_tag_get_language_code if you want to get the the
1003  * ISO 639-1 language code from the returned ISO 639-2 one.
1004  *
1005  * Returns: %TRUE if parsing succeeded, else %FALSE.
1006  */
1007 gboolean
gst_mpegts_descriptor_parse_dvb_subtitling_idx(const GstMpegtsDescriptor * descriptor,guint idx,gchar ** lang,guint8 * type,guint16 * composition_page_id,guint16 * ancillary_page_id)1008 gst_mpegts_descriptor_parse_dvb_subtitling_idx (const GstMpegtsDescriptor *
1009     descriptor, guint idx, gchar ** lang, guint8 * type,
1010     guint16 * composition_page_id, guint16 * ancillary_page_id)
1011 {
1012   guint8 *data;
1013 
1014   g_return_val_if_fail (descriptor != NULL && lang != NULL, FALSE);
1015   __common_desc_check_base (descriptor, GST_MTS_DESC_DVB_SUBTITLING, FALSE);
1016 
1017   /* If we went too far, return FALSE */
1018   if (descriptor->length / 8 <= idx)
1019     return FALSE;
1020 
1021   data = (guint8 *) descriptor->data + 2 + idx * 8;
1022 
1023   *lang = convert_lang_code (data);
1024 
1025   data += 3;
1026 
1027   if (type)
1028     *type = *data;
1029   data += 1;
1030   if (composition_page_id)
1031     *composition_page_id = GST_READ_UINT16_BE (data);
1032   data += 2;
1033   if (ancillary_page_id)
1034     *ancillary_page_id = GST_READ_UINT16_BE (data);
1035 
1036   return TRUE;
1037 }
1038 
1039 /**
1040  * gst_mpegts_descriptor_parse_dvb_subtitling_nb:
1041  * @descriptor: a %GST_MTS_DESC_DVB_SUBTITLING #GstMpegtsDescriptor
1042  *
1043  * Returns: The number of entries in @descriptor
1044  */
1045 guint
gst_mpegts_descriptor_parse_dvb_subtitling_nb(const GstMpegtsDescriptor * descriptor)1046 gst_mpegts_descriptor_parse_dvb_subtitling_nb (const GstMpegtsDescriptor *
1047     descriptor)
1048 {
1049   g_return_val_if_fail (descriptor != NULL, FALSE);
1050   __common_desc_check_base (descriptor, GST_MTS_DESC_DVB_SUBTITLING, FALSE);
1051 
1052   return descriptor->length / 8;
1053 }
1054 
1055 /**
1056  * gst_mpegts_descriptor_from_dvb_subtitling:
1057  * @lang: (transfer none): a string containing the ISO639 language
1058  * @type: subtitling type
1059  * @composition: composition page id
1060  * @ancillary: ancillary page id
1061  */
1062 GstMpegtsDescriptor *
gst_mpegts_descriptor_from_dvb_subtitling(const gchar * lang,guint8 type,guint16 composition,guint16 ancillary)1063 gst_mpegts_descriptor_from_dvb_subtitling (const gchar * lang,
1064     guint8 type, guint16 composition, guint16 ancillary)
1065 {
1066   GstMpegtsDescriptor *descriptor;
1067   guint8 *data;
1068 
1069   g_return_val_if_fail (lang != NULL, NULL);
1070 
1071   descriptor = _new_descriptor (GST_MTS_DESC_DVB_SUBTITLING, 8);
1072 
1073   data = descriptor->data + 2;
1074 
1075   memcpy (data, lang, 3);
1076   data += 3;
1077 
1078   *data++ = type;
1079 
1080   GST_WRITE_UINT16_BE (data, composition);
1081   data += 2;
1082 
1083   GST_WRITE_UINT16_BE (data, ancillary);
1084 
1085   return descriptor;
1086 }
1087 
1088 /* GST_MTS_DESC_DVB_EXTENDED_EVENT (0x4E) */
1089 static GstMpegtsExtendedEventDescriptor *
_gst_mpegts_extended_event_descriptor_copy(GstMpegtsExtendedEventDescriptor * source)1090 _gst_mpegts_extended_event_descriptor_copy (GstMpegtsExtendedEventDescriptor *
1091     source)
1092 {
1093   GstMpegtsExtendedEventDescriptor *copy;
1094 
1095   copy = g_slice_dup (GstMpegtsExtendedEventDescriptor, source);
1096   copy->items = g_ptr_array_ref (source->items);
1097   copy->text = g_strdup (source->text);
1098 
1099   return copy;
1100 }
1101 
1102 void
gst_mpegts_extended_event_descriptor_free(GstMpegtsExtendedEventDescriptor * source)1103 gst_mpegts_extended_event_descriptor_free (GstMpegtsExtendedEventDescriptor *
1104     source)
1105 {
1106   g_free (source->text);
1107   g_free (source->language_code);
1108   g_ptr_array_unref (source->items);
1109   g_slice_free (GstMpegtsExtendedEventDescriptor, source);
1110 }
1111 
1112 G_DEFINE_BOXED_TYPE (GstMpegtsExtendedEventDescriptor,
1113     gst_mpegts_extended_event_descriptor,
1114     (GBoxedCopyFunc) _gst_mpegts_extended_event_descriptor_copy,
1115     (GFreeFunc) gst_mpegts_extended_event_descriptor_free);
1116 
1117 static GstMpegtsExtendedEventItem *
_gst_mpegts_extended_event_item_copy(GstMpegtsExtendedEventItem * source)1118 _gst_mpegts_extended_event_item_copy (GstMpegtsExtendedEventItem * source)
1119 {
1120   GstMpegtsExtendedEventItem *copy =
1121       g_slice_dup (GstMpegtsExtendedEventItem, source);
1122   copy->item_description = g_strdup (source->item_description);
1123   copy->item = g_strdup (source->item);
1124   return copy;
1125 }
1126 
1127 static void
_gst_mpegts_extended_event_item_free(GstMpegtsExtendedEventItem * item)1128 _gst_mpegts_extended_event_item_free (GstMpegtsExtendedEventItem * item)
1129 {
1130   g_free (item->item);
1131   g_free (item->item_description);
1132   g_slice_free (GstMpegtsExtendedEventItem, item);
1133 }
1134 
1135 G_DEFINE_BOXED_TYPE (GstMpegtsExtendedEventItem,
1136     gst_mpegts_extended_event_item,
1137     (GBoxedCopyFunc) _gst_mpegts_extended_event_item_copy,
1138     (GFreeFunc) _gst_mpegts_extended_event_item_free);
1139 
1140 /**
1141  * gst_mpegts_descriptor_parse_dvb_extended_event:
1142  * @descriptor: a %GST_MTS_DESC_DVB_EXTENDED_EVENT #GstMpegtsDescriptor
1143  * @res: (out) (transfer full): the #GstMpegtsExtendedEventDescriptor to fill
1144  *
1145  * Extracts the DVB extended event information from @descriptor.
1146  *
1147  * Returns: %TRUE if parsing succeeded, else %FALSE.
1148  */
1149 gboolean
gst_mpegts_descriptor_parse_dvb_extended_event(const GstMpegtsDescriptor * descriptor,GstMpegtsExtendedEventDescriptor ** desc)1150 gst_mpegts_descriptor_parse_dvb_extended_event (const GstMpegtsDescriptor
1151     * descriptor, GstMpegtsExtendedEventDescriptor ** desc)
1152 {
1153   guint8 *data, *pdata;
1154   guint8 tmp, len_item;
1155   GstMpegtsExtendedEventItem *item;
1156   GstMpegtsExtendedEventDescriptor *res;
1157 
1158   g_return_val_if_fail (descriptor != NULL && desc != NULL, FALSE);
1159   /* Need at least 6 bytes (1 for desc number, 3 for language code, 2 for the loop length) */
1160   __common_desc_checks (descriptor, GST_MTS_DESC_DVB_EXTENDED_EVENT, 6, FALSE);
1161 
1162   res = g_slice_new0 (GstMpegtsExtendedEventDescriptor);
1163 
1164   data = (guint8 *) descriptor->data + 2;
1165 
1166   tmp = *data;
1167   res->descriptor_number = tmp >> 4;
1168   res->last_descriptor_number = tmp & 0x0f;
1169 
1170   data += 1;
1171 
1172   res->language_code = convert_lang_code (data);
1173   data += 3;
1174 
1175   len_item = *data;
1176   if (len_item > descriptor->length - 5) {
1177     gst_mpegts_extended_event_descriptor_free (res);
1178     return FALSE;
1179   }
1180 
1181   data += 1;
1182 
1183   res->items = g_ptr_array_new_with_free_func ((GDestroyNotify)
1184       _gst_mpegts_extended_event_item_free);
1185 
1186   pdata = data + len_item;
1187   while (data < pdata) {
1188     item = g_slice_new0 (GstMpegtsExtendedEventItem);
1189     item->item_description =
1190         get_encoding_and_convert ((const gchar *) data + 1, *data);
1191 
1192     data += *data + 1;
1193 
1194     item->item = get_encoding_and_convert ((const gchar *) data + 1, *data);
1195 
1196     data += *data + 1;
1197 
1198     g_ptr_array_add (res->items, item);
1199   }
1200   if (pdata != data) {
1201     gst_mpegts_extended_event_descriptor_free (res);
1202     return FALSE;
1203   }
1204   res->text = get_encoding_and_convert ((const gchar *) data + 1, *data);
1205 
1206   *desc = res;
1207 
1208   return TRUE;
1209 }
1210 
1211 /* GST_MTS_DESC_DVB_COMPONENT (0x50) */
1212 static GstMpegtsComponentDescriptor *
_gst_mpegts_dvb_component_descriptor_copy(GstMpegtsComponentDescriptor * source)1213 _gst_mpegts_dvb_component_descriptor_copy (GstMpegtsComponentDescriptor *
1214     source)
1215 {
1216   GstMpegtsComponentDescriptor *copy;
1217 
1218   copy = g_slice_dup (GstMpegtsComponentDescriptor, source);
1219   copy->language_code = g_strdup (source->language_code);
1220   copy->text = g_strdup (source->text);
1221 
1222   return copy;
1223 }
1224 
1225 void
gst_mpegts_dvb_component_descriptor_free(GstMpegtsComponentDescriptor * source)1226 gst_mpegts_dvb_component_descriptor_free (GstMpegtsComponentDescriptor * source)
1227 {
1228   g_free (source->language_code);
1229   g_free (source->text);
1230   g_slice_free (GstMpegtsComponentDescriptor, source);
1231 }
1232 
1233 G_DEFINE_BOXED_TYPE (GstMpegtsComponentDescriptor,
1234     gst_mpegts_component_descriptor,
1235     (GBoxedCopyFunc) _gst_mpegts_dvb_component_descriptor_copy,
1236     (GFreeFunc) gst_mpegts_dvb_component_descriptor_free);
1237 
1238 /**
1239  * gst_mpegts_descriptor_parse_dvb_component:
1240  * @descriptor: a %GST_MTS_DESC_DVB_COMPONENT #GstMpegtsDescriptor
1241  * @res: (out) (transfer full): the #GstMpegtsComponentDescriptor to fill
1242  *
1243  * Extracts the DVB component information from @descriptor.
1244  *
1245  * Returns: %TRUE if parsing succeeded, else %FALSE.
1246  */
1247 gboolean
gst_mpegts_descriptor_parse_dvb_component(const GstMpegtsDescriptor * descriptor,GstMpegtsComponentDescriptor ** res)1248 gst_mpegts_descriptor_parse_dvb_component (const GstMpegtsDescriptor
1249     * descriptor, GstMpegtsComponentDescriptor ** res)
1250 {
1251   guint8 *data;
1252   guint8 len;
1253   GstMpegtsComponentDescriptor *desc;
1254 
1255   g_return_val_if_fail (descriptor != NULL && res != NULL, FALSE);
1256   /* Need 6 bytes at least (1 for content, 1 for type, 1 for tag, 3 for language code) */
1257   __common_desc_checks (descriptor, GST_MTS_DESC_DVB_COMPONENT, 6, FALSE);
1258 
1259   data = (guint8 *) descriptor->data + 2;
1260 
1261   desc = g_slice_new0 (GstMpegtsComponentDescriptor);
1262 
1263   desc->stream_content = *data & 0x0f;
1264   data += 1;
1265 
1266   desc->component_type = *data;
1267   data += 1;
1268 
1269   desc->component_tag = *data;
1270   data += 1;
1271 
1272   desc->language_code = convert_lang_code (data);
1273   data += 3;
1274 
1275   len = descriptor->length - 6;
1276   if (len)
1277     desc->text = get_encoding_and_convert ((const gchar *) data, len);
1278 
1279   *res = desc;
1280 
1281   return TRUE;
1282 }
1283 
1284 /* GST_MTS_DESC_DVB_STREAM_IDENTIFIER (0x52) */
1285 /**
1286  * gst_mpegts_descriptor_parse_dvb_stream_identifier:
1287  * @descriptor: a %GST_MTS_DESC_DVB_CONTENT #GstMpegtsDescriptor
1288  * @component_tag: (out) (transfer none): the component tag
1289  *
1290  * Extracts the component tag from @descriptor.
1291  *
1292  * Returns: %TRUE if the parsing happended correctly, else %FALSE.
1293  */
1294 gboolean
gst_mpegts_descriptor_parse_dvb_stream_identifier(const GstMpegtsDescriptor * descriptor,guint8 * component_tag)1295 gst_mpegts_descriptor_parse_dvb_stream_identifier (const GstMpegtsDescriptor
1296     * descriptor, guint8 * component_tag)
1297 {
1298   guint8 *data;
1299 
1300   g_return_val_if_fail (descriptor != NULL && component_tag != NULL, FALSE);
1301   __common_desc_checks_exact (descriptor, GST_MTS_DESC_DVB_STREAM_IDENTIFIER,
1302       1, FALSE);
1303 
1304   data = (guint8 *) descriptor->data + 2;
1305 
1306   *component_tag = *data;
1307 
1308   return TRUE;
1309 }
1310 
1311 /* GST_MTS_DESC_DVB_CA_IDENTIFIER (0x53) */
1312 /**
1313  * gst_mpegts_descriptor_parse_dvb_ca_identifier:
1314  * @descriptor: a %GST_MTS_DESC_DVB_CA_IDENTIFIER #GstMpegtsDescriptor
1315  * @list: (out) (transfer full) (element-type guint16): a list of ca identifier.
1316  * Edge entry identifies the CA system. Allocations of the value of this field
1317  * are found in http://www.dvbservices.com
1318  *
1319  * Extracts ca id's from @descriptor.
1320  *
1321  * Returns: %TRUE if the parsing happened correctly, else %FALSE.
1322  */
1323 gboolean
gst_mpegts_descriptor_parse_dvb_ca_identifier(const GstMpegtsDescriptor * descriptor,GArray ** list)1324 gst_mpegts_descriptor_parse_dvb_ca_identifier (const GstMpegtsDescriptor *
1325     descriptor, GArray ** list)
1326 {
1327   guint8 *data;
1328   guint16 tmp;
1329   guint i;
1330 
1331   g_return_val_if_fail (descriptor != NULL && list != NULL, FALSE);
1332   /* 2 bytes = one entry */
1333   __common_desc_checks (descriptor, GST_MTS_DESC_DVB_CA_IDENTIFIER, 2, FALSE);
1334 
1335   data = (guint8 *) descriptor->data + 2;
1336 
1337   *list = g_array_new (FALSE, FALSE, sizeof (guint16));
1338 
1339   for (i = 0; i < descriptor->length - 1; i += 2) {
1340     tmp = GST_READ_UINT16_BE (data);
1341     g_array_append_val (*list, tmp);
1342     data += 2;
1343   }
1344 
1345   return TRUE;
1346 }
1347 
1348 /* GST_MTS_DESC_DVB_CONTENT (0x54) */
1349 
1350 DEFINE_STATIC_COPY_FUNCTION (GstMpegtsContent, gst_mpegts_content);
1351 
1352 DEFINE_STATIC_FREE_FUNCTION (GstMpegtsContent, gst_mpegts_content);
1353 
1354 G_DEFINE_BOXED_TYPE (GstMpegtsContent,
1355     gst_mpegts_content,
1356     (GBoxedCopyFunc) _gst_mpegts_content_copy,
1357     (GFreeFunc) _gst_mpegts_content_free);
1358 
1359 /**
1360  * gst_mpegts_descriptor_parse_dvb_content:
1361  * @descriptor: a %GST_MTS_DESC_DVB_CONTENT #GstMpegtsDescriptor
1362  * @content: (out) (transfer full) (element-type GstMpegtsContent): #GstMpegtsContent
1363  *
1364  * Extracts the DVB content information from @descriptor.
1365  *
1366  * Returns: %TRUE if the parsing happened correctly, else %FALSE.
1367  */
1368 gboolean
gst_mpegts_descriptor_parse_dvb_content(const GstMpegtsDescriptor * descriptor,GPtrArray ** content)1369 gst_mpegts_descriptor_parse_dvb_content (const GstMpegtsDescriptor
1370     * descriptor, GPtrArray ** content)
1371 {
1372   guint8 *data;
1373   guint8 len, tmp;
1374   guint8 i;
1375 
1376   g_return_val_if_fail (descriptor != NULL && content != NULL, FALSE);
1377   __common_desc_check_base (descriptor, GST_MTS_DESC_DVB_CONTENT, FALSE);
1378 
1379   data = (guint8 *) descriptor->data + 2;
1380   len = descriptor->length;
1381 
1382   *content = g_ptr_array_new_with_free_func ((GDestroyNotify)
1383       _gst_mpegts_content_free);
1384   for (i = 0; i < len;) {
1385     GstMpegtsContent *cont = g_slice_new0 (GstMpegtsContent);
1386     tmp = *data;
1387     cont->content_nibble_1 = (tmp & 0xf0) >> 4;
1388     cont->content_nibble_2 = tmp & 0x0f;
1389     data += 1;
1390     cont->user_byte = *data;
1391     data += 1;
1392     i += 2;
1393     g_ptr_array_add (*content, cont);
1394   }
1395 
1396   return TRUE;
1397 }
1398 
1399 /* GST_MTS_DESC_DVB_PARENTAL_RATING (0x55) */
1400 
1401 static GstMpegtsDVBParentalRatingItem *
_gst_mpegts_dvb_parental_rating_item_copy(GstMpegtsDVBParentalRatingItem * source)1402 _gst_mpegts_dvb_parental_rating_item_copy (GstMpegtsDVBParentalRatingItem *
1403     source)
1404 {
1405   GstMpegtsDVBParentalRatingItem *copy =
1406       g_slice_dup (GstMpegtsDVBParentalRatingItem, source);
1407   copy->country_code = g_strdup (source->country_code);
1408   return copy;
1409 }
1410 
1411 static void
_gst_mpegts_dvb_parental_rating_item_free(GstMpegtsDVBParentalRatingItem * item)1412 _gst_mpegts_dvb_parental_rating_item_free (GstMpegtsDVBParentalRatingItem *
1413     item)
1414 {
1415   g_free (item->country_code);
1416   g_slice_free (GstMpegtsDVBParentalRatingItem, item);
1417 }
1418 
1419 G_DEFINE_BOXED_TYPE (GstMpegtsDVBParentalRatingItem,
1420     gst_mpegts_dvb_parental_rating_item,
1421     (GBoxedCopyFunc) _gst_mpegts_dvb_parental_rating_item_copy,
1422     (GFreeFunc) _gst_mpegts_dvb_parental_rating_item_free);
1423 
1424 /**
1425  * gst_mpegts_descriptor_parse_dvb_parental_rating:
1426  * @descriptor: a %GST_MTS_DESC_DVB_PARENTAL_RATING #GstMpegtsDescriptor
1427  * @rating: (out) (transfer full) (element-type GstMpegtsDVBParentalRatingItem):
1428  * #GstMpegtsDVBParentalRatingItem
1429  *
1430  * Extracts the DVB parental rating information from @descriptor.
1431  *
1432  * Returns: %TRUE if the parsing happened correctly, else %FALSE.
1433  */
1434 gboolean
gst_mpegts_descriptor_parse_dvb_parental_rating(const GstMpegtsDescriptor * descriptor,GPtrArray ** rating)1435 gst_mpegts_descriptor_parse_dvb_parental_rating (const GstMpegtsDescriptor
1436     * descriptor, GPtrArray ** rating)
1437 {
1438   guint8 *data;
1439   guint i;
1440 
1441   g_return_val_if_fail (descriptor != NULL && rating != NULL, FALSE);
1442   __common_desc_check_base (descriptor, GST_MTS_DESC_DVB_PARENTAL_RATING,
1443       FALSE);
1444 
1445   data = (guint8 *) descriptor->data + 2;
1446 
1447   *rating = g_ptr_array_new_with_free_func ((GDestroyNotify)
1448       _gst_mpegts_dvb_parental_rating_item_free);
1449 
1450   for (i = 0; i < descriptor->length - 3; i += 4) {
1451     GstMpegtsDVBParentalRatingItem *item =
1452         g_slice_new0 (GstMpegtsDVBParentalRatingItem);
1453     g_ptr_array_add (*rating, item);
1454 
1455     item->country_code = convert_lang_code (data);
1456     data += 3;
1457 
1458     if (g_strcmp0 (item->country_code, "BRA") == 0) {
1459       /* brasil */
1460       switch (*data & 0xf) {
1461         case 1:
1462           item->rating = 6;
1463           break;
1464         case 2:
1465           item->rating = 10;
1466           break;
1467         case 3:
1468           item->rating = 12;
1469           break;
1470         case 4:
1471           item->rating = 14;
1472           break;
1473         case 5:
1474           item->rating = 16;
1475           break;
1476         case 6:
1477           item->rating = 18;
1478           break;
1479         default:
1480           item->rating = 0;
1481           break;
1482       }
1483     } else {
1484       item->rating = (*data & 0xf) + 3;
1485     }
1486 
1487     data += 1;
1488   }
1489 
1490   return TRUE;
1491 }
1492 
1493 /* GST_MTS_DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM (0x5A) */
1494 
1495 DEFINE_STATIC_COPY_FUNCTION (GstMpegtsTerrestrialDeliverySystemDescriptor,
1496     gst_mpegts_terrestrial_delivery_system_descriptor);
1497 
1498 DEFINE_STATIC_FREE_FUNCTION (GstMpegtsTerrestrialDeliverySystemDescriptor,
1499     gst_mpegts_terrestrial_delivery_system_descriptor);
1500 
1501 G_DEFINE_BOXED_TYPE (GstMpegtsTerrestrialDeliverySystemDescriptor,
1502     gst_mpegts_terrestrial_delivery_system_descriptor,
1503     (GBoxedCopyFunc) _gst_mpegts_terrestrial_delivery_system_descriptor_copy,
1504     (GFreeFunc) _gst_mpegts_terrestrial_delivery_system_descriptor_free);
1505 
1506 
1507 /**
1508  * gst_mpegts_descriptor_parse_terrestrial_delivery_system:
1509  * @descriptor: a %GST_MTS_DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM #GstMpegtsDescriptor
1510  * @res: (out) (transfer none): #GstMpegtsTerrestrialDeliverySystemDescriptor
1511  *
1512  * Parses out the terrestrial delivery system from the @descriptor.
1513  *
1514  * Returns: %TRUE if the parsing happened correctly, else %FALSE.
1515  */
1516 gboolean
gst_mpegts_descriptor_parse_terrestrial_delivery_system(const GstMpegtsDescriptor * descriptor,GstMpegtsTerrestrialDeliverySystemDescriptor * res)1517 gst_mpegts_descriptor_parse_terrestrial_delivery_system (const
1518     GstMpegtsDescriptor * descriptor,
1519     GstMpegtsTerrestrialDeliverySystemDescriptor * res)
1520 {
1521   guint8 *data;
1522   guint8 tmp;
1523 
1524   g_return_val_if_fail (descriptor != NULL && res != NULL, FALSE);
1525   /* Descriptor is always 11 bytes long */
1526   __common_desc_checks_exact (descriptor,
1527       GST_MTS_DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM, 11, FALSE);
1528 
1529   data = (guint8 *) descriptor->data + 2;
1530 
1531   res->frequency = 0;
1532   res->frequency = GST_READ_UINT32_BE (data);
1533   res->frequency *= 10;
1534 
1535   data += 4;
1536 
1537   tmp = *data;
1538   switch ((tmp >> 5) & 0x07) {
1539     case 0:
1540       res->bandwidth = 8000000;
1541       break;
1542     case 1:
1543       res->bandwidth = 7000000;
1544       break;
1545     case 2:
1546       res->bandwidth = 6000000;
1547       break;
1548     case 3:
1549       res->bandwidth = 5000000;
1550       break;
1551     default:
1552       res->bandwidth = 0;
1553       break;
1554   }
1555 
1556   res->priority = (tmp >> 4) & 0x01;
1557   res->time_slicing = (tmp >> 3) & 0x01;
1558   res->mpe_fec = (tmp >> 2) & 0x01;
1559   data += 1;
1560 
1561   tmp = *data;
1562   switch ((tmp >> 6) & 0x03) {
1563     case 0:
1564       res->constellation = GST_MPEGTS_MODULATION_QPSK;
1565       break;
1566     case 1:
1567       res->constellation = GST_MPEGTS_MODULATION_QAM_16;
1568       break;
1569     case 2:
1570       res->constellation = GST_MPEGTS_MODULATION_QAM_64;
1571       break;
1572     default:
1573       break;
1574   }
1575 
1576   switch ((tmp >> 3) & 0x07) {
1577     case 0:
1578       res->hierarchy = GST_MPEGTS_HIERARCHY_NONE;
1579       break;
1580     case 1:
1581       res->hierarchy = GST_MPEGTS_HIERARCHY_1;
1582       break;
1583     case 2:
1584       res->hierarchy = GST_MPEGTS_HIERARCHY_2;
1585       break;
1586     case 3:
1587       res->hierarchy = GST_MPEGTS_HIERARCHY_4;
1588       break;
1589     case 4:
1590       res->hierarchy = GST_MPEGTS_HIERARCHY_NONE;
1591       break;
1592     case 5:
1593       res->hierarchy = GST_MPEGTS_HIERARCHY_1;
1594       break;
1595     case 6:
1596       res->hierarchy = GST_MPEGTS_HIERARCHY_2;
1597       break;
1598     case 7:
1599       res->hierarchy = GST_MPEGTS_HIERARCHY_4;
1600       break;
1601     default:
1602       break;
1603   }
1604 
1605   switch (tmp & 0x07) {
1606     case 0:
1607       res->code_rate_hp = GST_MPEGTS_FEC_1_2;
1608       break;
1609     case 1:
1610       res->code_rate_hp = GST_MPEGTS_FEC_2_3;
1611       break;
1612     case 2:
1613       res->code_rate_hp = GST_MPEGTS_FEC_3_4;
1614       break;
1615     case 3:
1616       res->code_rate_hp = GST_MPEGTS_FEC_5_6;
1617       break;
1618     case 4:
1619       res->code_rate_hp = GST_MPEGTS_FEC_7_8;
1620       break;
1621     default:
1622       break;
1623   }
1624   data += 1;
1625 
1626   tmp = *data;
1627   switch ((tmp >> 5) & 0x07) {
1628     case 0:
1629       res->code_rate_lp = GST_MPEGTS_FEC_1_2;
1630       break;
1631     case 1:
1632       res->code_rate_lp = GST_MPEGTS_FEC_2_3;
1633       break;
1634     case 2:
1635       res->code_rate_lp = GST_MPEGTS_FEC_3_4;
1636       break;
1637     case 3:
1638       res->code_rate_lp = GST_MPEGTS_FEC_5_6;
1639       break;
1640     case 4:
1641       res->code_rate_lp = GST_MPEGTS_FEC_7_8;
1642       break;
1643     default:
1644       break;
1645   }
1646 
1647   switch ((tmp >> 3) & 0x03) {
1648     case 0:
1649       res->guard_interval = GST_MPEGTS_GUARD_INTERVAL_1_32;
1650       break;
1651     case 1:
1652       res->guard_interval = GST_MPEGTS_GUARD_INTERVAL_1_16;
1653       break;
1654     case 2:
1655       res->guard_interval = GST_MPEGTS_GUARD_INTERVAL_1_8;
1656       break;
1657     case 3:
1658       res->guard_interval = GST_MPEGTS_GUARD_INTERVAL_1_4;
1659       break;
1660     default:
1661       break;
1662   }
1663 
1664   switch ((tmp >> 1) & 0x03) {
1665     case 0:
1666       res->transmission_mode = GST_MPEGTS_TRANSMISSION_MODE_2K;
1667       break;
1668     case 1:
1669       res->transmission_mode = GST_MPEGTS_TRANSMISSION_MODE_8K;
1670       break;
1671     case 2:
1672       res->transmission_mode = GST_MPEGTS_TRANSMISSION_MODE_4K;
1673       break;
1674     default:
1675       break;
1676   }
1677   res->other_frequency = tmp & 0x01;
1678 
1679   return TRUE;
1680 }
1681 
1682 /* GST_MTS_DESC_DVB_MULTILINGUAL_NETWORK_NAME (0x5B) */
1683 
1684 static GstMpegtsDvbMultilingualNetworkNameItem
_gst_mpegts_dvb_multilingual_network_name_item_copy(GstMpegtsDvbMultilingualNetworkNameItem * source)1685     * _gst_mpegts_dvb_multilingual_network_name_item_copy
1686     (GstMpegtsDvbMultilingualNetworkNameItem * source)
1687 {
1688   GstMpegtsDvbMultilingualNetworkNameItem *copy =
1689       g_slice_dup (GstMpegtsDvbMultilingualNetworkNameItem, source);
1690   copy->language_code = g_strdup (source->language_code);
1691   copy->network_name = g_strdup (source->network_name);
1692   return copy;
1693 }
1694 
1695 static void
_gst_mpegts_dvb_multilingual_network_name_item_free(GstMpegtsDvbMultilingualNetworkNameItem * item)1696     _gst_mpegts_dvb_multilingual_network_name_item_free
1697     (GstMpegtsDvbMultilingualNetworkNameItem * item)
1698 {
1699   g_free (item->network_name);
1700   g_free (item->language_code);
1701   g_slice_free (GstMpegtsDvbMultilingualNetworkNameItem, item);
1702 }
1703 
1704 G_DEFINE_BOXED_TYPE (GstMpegtsDvbMultilingualNetworkNameItem,
1705     gst_mpegts_dvb_multilingual_network_name_item,
1706     (GBoxedCopyFunc) _gst_mpegts_dvb_multilingual_network_name_item_copy,
1707     (GFreeFunc) _gst_mpegts_dvb_multilingual_network_name_item_free);
1708 
1709 /**
1710  * gst_mpegts_descriptor_parse_dvb_multilingual_network_name:
1711  * @descriptor: a %GST_MTS_DESC_DVB_MULTILINGUAL_NETWORK_NAME
1712  * #GstMpegtsDescriptor
1713  * @network_name_items: (out) (transfer full) (element-type GstMpegtsDvbMultilingualNetworkNameItem):
1714  * a #GstMpegtsDvbMultilingualNetworkNameItem
1715  *
1716  * Parses out the multilingual network name from the @descriptor.
1717  *
1718  * Returns: %TRUE if the parsing happened correctly, else %FALSE.
1719  */
1720 gboolean
gst_mpegts_descriptor_parse_dvb_multilingual_network_name(const GstMpegtsDescriptor * descriptor,GPtrArray ** network_name_items)1721 gst_mpegts_descriptor_parse_dvb_multilingual_network_name (const
1722     GstMpegtsDescriptor * descriptor, GPtrArray ** network_name_items)
1723 {
1724   guint8 *data, i, len;
1725   GstMpegtsDvbMultilingualNetworkNameItem *item;
1726 
1727   g_return_val_if_fail (descriptor != NULL && network_name_items != NULL,
1728       FALSE);
1729   __common_desc_checks (descriptor, GST_MTS_DESC_DVB_MULTILINGUAL_NETWORK_NAME,
1730       5, FALSE);
1731 
1732   data = (guint8 *) descriptor->data + 2;
1733 
1734   *network_name_items = g_ptr_array_new_with_free_func ((GDestroyNotify)
1735       _gst_mpegts_dvb_multilingual_network_name_item_free);
1736 
1737   for (i = 0; i < descriptor->length - 3;) {
1738     item = g_slice_new0 (GstMpegtsDvbMultilingualNetworkNameItem);
1739     g_ptr_array_add (*network_name_items, item);
1740     item->language_code = convert_lang_code (data);
1741     data += 3;
1742     i += 3;
1743 
1744     len = *data;
1745     item->network_name =
1746         get_encoding_and_convert ((const gchar *) data + 1, len);
1747     data += len + 1;
1748     i += len + 1;
1749   }
1750 
1751   return TRUE;
1752 }
1753 
1754 /* GST_MTS_DESC_DVB_MULTILINGUAL_BOUQUET_NAME (0x5C) */
1755 
1756 static GstMpegtsDvbMultilingualBouquetNameItem
_gst_mpegts_dvb_multilingual_bouquet_name_item_copy(GstMpegtsDvbMultilingualBouquetNameItem * source)1757     * _gst_mpegts_dvb_multilingual_bouquet_name_item_copy
1758     (GstMpegtsDvbMultilingualBouquetNameItem * source)
1759 {
1760   GstMpegtsDvbMultilingualBouquetNameItem *copy =
1761       g_slice_dup (GstMpegtsDvbMultilingualBouquetNameItem, source);
1762   copy->bouquet_name = g_strdup (source->bouquet_name);
1763   copy->language_code = g_strdup (source->language_code);
1764   return copy;
1765 }
1766 
1767 static void
_gst_mpegts_dvb_multilingual_bouquet_name_item_free(GstMpegtsDvbMultilingualBouquetNameItem * item)1768     _gst_mpegts_dvb_multilingual_bouquet_name_item_free
1769     (GstMpegtsDvbMultilingualBouquetNameItem * item)
1770 {
1771   g_free (item->language_code);
1772   g_free (item->bouquet_name);
1773   g_slice_free (GstMpegtsDvbMultilingualBouquetNameItem, item);
1774 }
1775 
1776 G_DEFINE_BOXED_TYPE (GstMpegtsDvbMultilingualBouquetNameItem,
1777     gst_mpegts_dvb_multilingual_bouquet_name_item,
1778     (GBoxedCopyFunc) _gst_mpegts_dvb_multilingual_bouquet_name_item_copy,
1779     (GFreeFunc) _gst_mpegts_dvb_multilingual_bouquet_name_item_free);
1780 
1781 /**
1782  * gst_mpegts_descriptor_parse_dvb_multilingual_bouquet_name:
1783  * @descriptor: a %GST_MTS_DESC_DVB_MULTILINGUAL_BOUQUET_NAME
1784  * #GstMpegtsDescriptor
1785  * @bouquet_name_items: (out) (transfer full) (element-type GstMpegtsDvbMultilingualBouquetNameItem):
1786  * a #GstMpegtsDvbMultilingualBouquetNameItem
1787  *
1788  * Parses out the multilingual bouquet name from the @descriptor.
1789  *
1790  * Returns: %TRUE if the parsing happened correctly, else %FALSE.
1791  */
1792 gboolean
gst_mpegts_descriptor_parse_dvb_multilingual_bouquet_name(const GstMpegtsDescriptor * descriptor,GPtrArray ** bouquet_name_items)1793 gst_mpegts_descriptor_parse_dvb_multilingual_bouquet_name (const
1794     GstMpegtsDescriptor * descriptor, GPtrArray ** bouquet_name_items)
1795 {
1796   guint8 *data, i, len;
1797   GstMpegtsDvbMultilingualBouquetNameItem *item;
1798 
1799   g_return_val_if_fail (descriptor != NULL && bouquet_name_items != NULL,
1800       FALSE);
1801   __common_desc_checks (descriptor, GST_MTS_DESC_DVB_MULTILINGUAL_BOUQUET_NAME,
1802       5, FALSE);
1803 
1804   data = (guint8 *) descriptor->data + 2;
1805 
1806   *bouquet_name_items = g_ptr_array_new_with_free_func ((GDestroyNotify)
1807       _gst_mpegts_dvb_multilingual_bouquet_name_item_free);
1808 
1809   for (i = 0; i < descriptor->length - 3;) {
1810     item = g_slice_new0 (GstMpegtsDvbMultilingualBouquetNameItem);
1811     g_ptr_array_add (*bouquet_name_items, item);
1812     item->language_code = convert_lang_code (data);
1813     data += 3;
1814     i += 3;
1815 
1816     len = *data;
1817     item->bouquet_name =
1818         get_encoding_and_convert ((const gchar *) data + 1, len);
1819     data += len + 1;
1820     i += len + 1;
1821   }
1822 
1823   return TRUE;
1824 }
1825 
1826 /* GST_MTS_DESC_DVB_MULTILINGUAL_SERVICE_NAME (0x5D) */
1827 
1828 static GstMpegtsDvbMultilingualServiceNameItem
_gst_mpegts_dvb_multilingual_service_name_item_copy(GstMpegtsDvbMultilingualServiceNameItem * source)1829     * _gst_mpegts_dvb_multilingual_service_name_item_copy
1830     (GstMpegtsDvbMultilingualServiceNameItem * source)
1831 {
1832   GstMpegtsDvbMultilingualServiceNameItem *copy =
1833       g_slice_dup (GstMpegtsDvbMultilingualServiceNameItem, source);
1834   copy->language_code = g_strdup (source->language_code);
1835   copy->service_name = g_strdup (source->service_name);
1836   copy->provider_name = g_strdup (source->provider_name);
1837   return copy;
1838 }
1839 
1840 static void
_gst_mpegts_dvb_multilingual_service_name_item_free(GstMpegtsDvbMultilingualServiceNameItem * item)1841     _gst_mpegts_dvb_multilingual_service_name_item_free
1842     (GstMpegtsDvbMultilingualServiceNameItem * item)
1843 {
1844   g_free (item->provider_name);
1845   g_free (item->service_name);
1846   g_free (item->language_code);
1847   g_slice_free (GstMpegtsDvbMultilingualServiceNameItem, item);
1848 }
1849 
1850 G_DEFINE_BOXED_TYPE (GstMpegtsDvbMultilingualServiceNameItem,
1851     gst_mpegts_dvb_multilingual_service_name_item,
1852     (GBoxedCopyFunc) _gst_mpegts_dvb_multilingual_service_name_item_copy,
1853     (GFreeFunc) _gst_mpegts_dvb_multilingual_service_name_item_free);
1854 
1855 /**
1856  * gst_mpegts_descriptor_parse_dvb_multilingual_service_name:
1857  * @descriptor: a %GST_MTS_DESC_DVB_MULTILINGUAL_SERVICE_NAME
1858  * #GstMpegtsDescriptor
1859  * @service_name_items: (out) (transfer full) (element-type GstMpegtsDvbMultilingualServiceNameItem):
1860  * a #GstMpegtsDvbMultilingualServiceNameItem
1861  *
1862  * Parses out the multilingual service name from the @descriptor.
1863  *
1864  * Returns: %TRUE if the parsing happened correctly, else %FALSE.
1865  */
1866 gboolean
gst_mpegts_descriptor_parse_dvb_multilingual_service_name(const GstMpegtsDescriptor * descriptor,GPtrArray ** service_name_items)1867 gst_mpegts_descriptor_parse_dvb_multilingual_service_name (const
1868     GstMpegtsDescriptor * descriptor, GPtrArray ** service_name_items)
1869 {
1870   guint8 *data, i, len;
1871   GstMpegtsDvbMultilingualServiceNameItem *item;
1872 
1873   g_return_val_if_fail (descriptor != NULL && service_name_items != NULL,
1874       FALSE);
1875   __common_desc_checks (descriptor, GST_MTS_DESC_DVB_MULTILINGUAL_SERVICE_NAME,
1876       7, FALSE);
1877 
1878   data = (guint8 *) descriptor->data + 2;
1879 
1880   *service_name_items = g_ptr_array_new_with_free_func ((GDestroyNotify)
1881       _gst_mpegts_dvb_multilingual_service_name_item_free);
1882 
1883   for (i = 0; i < descriptor->length - 3;) {
1884     item = g_slice_new0 (GstMpegtsDvbMultilingualServiceNameItem);
1885     g_ptr_array_add (*service_name_items, item);
1886     item->language_code = convert_lang_code (data);
1887     data += 3;
1888     i += 3;
1889 
1890     len = *data;
1891     item->provider_name =
1892         get_encoding_and_convert ((const gchar *) data + 1, len);
1893     data += len + 1;
1894     i += len + 1;
1895 
1896     len = *data;
1897     item->service_name =
1898         get_encoding_and_convert ((const gchar *) data + 1, len);
1899     data += len + 1;
1900     i += len + 1;
1901   }
1902 
1903   return TRUE;
1904 }
1905 
1906 /* GST_MTS_DESC_DVB_MULTILINGUAL_COMPONENT (0x5E) */
1907 
1908 static GstMpegtsDvbMultilingualComponentItem
_gst_mpegts_dvb_multilingual_component_item_copy(GstMpegtsDvbMultilingualComponentItem * source)1909     * _gst_mpegts_dvb_multilingual_component_item_copy
1910     (GstMpegtsDvbMultilingualComponentItem * source)
1911 {
1912   GstMpegtsDvbMultilingualComponentItem *copy =
1913       g_slice_dup (GstMpegtsDvbMultilingualComponentItem, source);
1914   copy->description = g_strdup (source->description);
1915   copy->language_code = g_strdup (source->language_code);
1916   return copy;
1917 }
1918 
1919 static void
_gst_mpegts_dvb_multilingual_component_item_free(GstMpegtsDvbMultilingualComponentItem * item)1920     _gst_mpegts_dvb_multilingual_component_item_free
1921     (GstMpegtsDvbMultilingualComponentItem * item)
1922 {
1923   g_free (item->language_code);
1924   g_free (item->description);
1925   g_slice_free (GstMpegtsDvbMultilingualComponentItem, item);
1926 }
1927 
1928 G_DEFINE_BOXED_TYPE (GstMpegtsDvbMultilingualComponentItem,
1929     gst_mpegts_dvb_multilingual_component_item,
1930     (GBoxedCopyFunc) _gst_mpegts_dvb_multilingual_component_item_copy,
1931     (GFreeFunc) _gst_mpegts_dvb_multilingual_component_item_free);
1932 
1933 /**
1934  * gst_mpegts_descriptor_parse_dvb_multilingual_component:
1935  * @descriptor: a %GST_MTS_DESC_DVB_MULTILINGUAL_COMPONENT
1936  * #GstMpegtsDescriptor
1937  * @component_tag: (out): the component tag
1938  * @component_description_items: (out) (transfer full) (element-type GstMpegtsDvbMultilingualComponentItem):
1939  * a #GstMpegtsDvbMultilingualComponentItem
1940  *
1941  * Parses out the multilingual component from the @descriptor.
1942  *
1943  * Returns: %TRUE if the parsing happened correctly, else %FALSE.
1944  */
1945 gboolean
gst_mpegts_descriptor_parse_dvb_multilingual_component(const GstMpegtsDescriptor * descriptor,guint8 * component_tag,GPtrArray ** component_description_items)1946 gst_mpegts_descriptor_parse_dvb_multilingual_component (const
1947     GstMpegtsDescriptor * descriptor, guint8 * component_tag,
1948     GPtrArray ** component_description_items)
1949 {
1950   guint8 *data, i, len;
1951   GstMpegtsDvbMultilingualComponentItem *item;
1952 
1953   g_return_val_if_fail (descriptor != NULL
1954       && component_description_items != NULL && component_tag != NULL, FALSE);
1955   __common_desc_checks (descriptor, GST_MTS_DESC_DVB_MULTILINGUAL_COMPONENT, 6,
1956       FALSE);
1957 
1958   data = (guint8 *) descriptor->data + 2;
1959 
1960   *component_tag = *data;
1961   data += 1;
1962 
1963   *component_description_items =
1964       g_ptr_array_new_with_free_func ((GDestroyNotify)
1965       _gst_mpegts_dvb_multilingual_component_item_free);
1966 
1967   for (i = 0; i < descriptor->length - 3;) {
1968     item = g_slice_new0 (GstMpegtsDvbMultilingualComponentItem);
1969     g_ptr_array_add (*component_description_items, item);
1970     item->language_code = convert_lang_code (data);
1971     data += 3;
1972     i += 3;
1973 
1974     len = *data;
1975     item->description =
1976         get_encoding_and_convert ((const gchar *) data + 1, len);
1977     data += len + 1;
1978     i += len + 1;
1979   }
1980 
1981   return TRUE;
1982 }
1983 
1984 /* GST_MTS_DESC_DVB_PRIVATE_DATA_SPECIFIER (0x5F) */
1985 /**
1986  * gst_mpegts_descriptor_parse_dvb_private_data_specifier:
1987  * @descriptor: a %GST_MTS_DESC_DVB_PRIVATE_DATA_SPECIFIER #GstMpegtsDescriptor
1988  * @private_data_specifier: (out): the private data specifier id
1989  * registered by http://www.dvbservices.com/
1990  * @private_data: (out) (transfer full) (allow-none) (array length=length): additional data or NULL
1991  * @length: (out) (allow-none): length of %private_data
1992  *
1993  * Parses out the private data specifier from the @descriptor.
1994  *
1995  * Returns: %TRUE if the parsing happened correctly, else %FALSE.
1996  */
1997 gboolean
gst_mpegts_descriptor_parse_dvb_private_data_specifier(const GstMpegtsDescriptor * descriptor,guint32 * private_data_specifier,guint8 ** private_data,guint8 * length)1998 gst_mpegts_descriptor_parse_dvb_private_data_specifier (const
1999     GstMpegtsDescriptor * descriptor, guint32 * private_data_specifier,
2000     guint8 ** private_data, guint8 * length)
2001 {
2002   guint8 *data;
2003 
2004   g_return_val_if_fail (descriptor != NULL
2005       && private_data_specifier != NULL, FALSE);
2006   __common_desc_checks (descriptor,
2007       GST_MTS_DESC_DVB_PRIVATE_DATA_SPECIFIER, 4, FALSE);
2008 
2009   data = (guint8 *) descriptor->data + 2;
2010 
2011   *private_data_specifier = GST_READ_UINT32_BE (data);
2012 
2013   if (length && private_data) {
2014     *length = descriptor->length - 4;
2015 
2016     *private_data = g_memdup (data + 4, *length);
2017   }
2018   return TRUE;
2019 }
2020 
2021 /* GST_MTS_DESC_DVB_FREQUENCY_LIST (0x62) */
2022 /**
2023  * gst_mpegts_descriptor_parse_dvb_frequency_list:
2024  * @descriptor: a %GST_MTS_DESC_DVB_FREQUENCY_LIST #GstMpegtsDescriptor
2025  * @offset: (out): %FALSE in Hz, %TRUE in kHz
2026  * @list: (out) (transfer full) (element-type guint32): a list of all frequencies in Hz/kHz
2027  * depending on %offset
2028  *
2029  * Parses out a list of frequencies from the @descriptor.
2030  *
2031  * Returns: %TRUE if the parsing happened correctly, else %FALSE.
2032  */
2033 gboolean
gst_mpegts_descriptor_parse_dvb_frequency_list(const GstMpegtsDescriptor * descriptor,gboolean * offset,GArray ** list)2034 gst_mpegts_descriptor_parse_dvb_frequency_list (const GstMpegtsDescriptor
2035     * descriptor, gboolean * offset, GArray ** list)
2036 {
2037   guint8 *data, type, len;
2038   guint32 freq;
2039   guint i;
2040 
2041   g_return_val_if_fail (descriptor != NULL && offset != NULL &&
2042       list != NULL, FALSE);
2043   /* 1 byte coding system, 4 bytes each frequency entry */
2044   __common_desc_checks (descriptor, GST_MTS_DESC_DVB_FREQUENCY_LIST, 5, FALSE);
2045 
2046   data = (guint8 *) descriptor->data + 2;
2047 
2048   type = *data & 0x03;
2049   data += 1;
2050 
2051   if (type == 1) {
2052     /* satellite */
2053     *offset = TRUE;
2054   } else {
2055     /* cable, terrestrial */
2056     *offset = FALSE;
2057   }
2058 
2059   *list = g_array_new (FALSE, FALSE, sizeof (guint32));
2060 
2061   len = descriptor->length - 1;
2062 
2063   for (i = 0; i < len - 3; i += 4) {
2064     switch (type) {
2065       case 1:
2066         freq = BCD_32 (data) * 10;
2067         break;
2068       case 2:
2069         freq = BCD_32 (data) * 100;
2070         break;
2071       case 3:
2072         freq = GST_READ_UINT32_BE (data) * 10;
2073         break;
2074       default:
2075         break;
2076     }
2077 
2078     g_array_append_val (*list, freq);
2079     data += 4;
2080   }
2081 
2082   return TRUE;
2083 }
2084 
2085 /* GST_MTS_DESC_DVB_DATA_BROADCAST (0x64) */
2086 static GstMpegtsDataBroadcastDescriptor *
_gst_mpegts_dvb_data_broadcast_descriptor_copy(GstMpegtsDataBroadcastDescriptor * source)2087 _gst_mpegts_dvb_data_broadcast_descriptor_copy (GstMpegtsDataBroadcastDescriptor
2088     * source)
2089 {
2090   GstMpegtsDataBroadcastDescriptor *copy;
2091 
2092   copy = g_slice_dup (GstMpegtsDataBroadcastDescriptor, source);
2093 
2094   copy->selector_bytes = g_memdup (source->selector_bytes, source->length);
2095   copy->language_code = g_strdup (source->language_code);
2096   copy->text = g_strdup (source->text);
2097 
2098   return copy;
2099 }
2100 
2101 void
gst_mpegts_dvb_data_broadcast_descriptor_free(GstMpegtsDataBroadcastDescriptor * source)2102 gst_mpegts_dvb_data_broadcast_descriptor_free (GstMpegtsDataBroadcastDescriptor
2103     * source)
2104 {
2105   g_free (source->selector_bytes);
2106   g_free (source->language_code);
2107   g_free (source->text);
2108   g_slice_free (GstMpegtsDataBroadcastDescriptor, source);
2109 }
2110 
2111 G_DEFINE_BOXED_TYPE (GstMpegtsDataBroadcastDescriptor,
2112     gst_mpegts_dvb_data_broadcast_descriptor,
2113     (GBoxedCopyFunc) _gst_mpegts_dvb_data_broadcast_descriptor_copy,
2114     (GFreeFunc) gst_mpegts_dvb_data_broadcast_descriptor_free);
2115 
2116 /**
2117  * gst_mpegts_descriptor_parse_dvb_data_broadcast:
2118  * @descriptor: a %GST_MTS_DESC_DVB_DATA_BROADCAST #GstMpegtsDescriptor
2119  * @res: (out) (transfer full): #GstMpegtsDataBroadcastDescriptor
2120  *
2121  * Parses out the data broadcast from the @descriptor.
2122  *
2123  * Returns: %TRUE if the parsing happened correctly, else %FALSE.
2124  */
2125 gboolean
gst_mpegts_descriptor_parse_dvb_data_broadcast(const GstMpegtsDescriptor * descriptor,GstMpegtsDataBroadcastDescriptor ** desc)2126 gst_mpegts_descriptor_parse_dvb_data_broadcast (const GstMpegtsDescriptor
2127     * descriptor, GstMpegtsDataBroadcastDescriptor ** desc)
2128 {
2129   guint8 *data;
2130   GstMpegtsDataBroadcastDescriptor *res;
2131 
2132   g_return_val_if_fail (descriptor != NULL && desc != NULL, FALSE);
2133   __common_desc_checks (descriptor, GST_MTS_DESC_DVB_DATA_BROADCAST, 8, FALSE);
2134 
2135   data = (guint8 *) descriptor->data + 2;
2136 
2137   res = g_slice_new0 (GstMpegtsDataBroadcastDescriptor);
2138 
2139   res->data_broadcast_id = GST_READ_UINT16_BE (data);
2140   data += 2;
2141 
2142   res->component_tag = *data;
2143   data += 1;
2144 
2145   res->length = *data;
2146   data += 1;
2147 
2148   res->selector_bytes = g_memdup (data, res->length);
2149   data += res->length;
2150 
2151   res->language_code = convert_lang_code (data);
2152   data += 3;
2153 
2154   res->text = get_encoding_and_convert ((const gchar *) data + 1, *data);
2155 
2156   *desc = res;
2157 
2158   return TRUE;
2159 }
2160 
2161 /* GST_MTS_DESC_DVB_SCRAMBLING (0x65) */
2162 /**
2163  * gst_mpegts_descriptor_parse_dvb_scrambling:
2164  * @descriptor: a %GST_MTS_DESC_DVB_SCRAMBLING #GstMpegtsDescriptor
2165  * @scrambling_mode: (out): This 8-bit field identifies the selected
2166  * mode of the scrambling algorithm (#GstMpegtsDVBScramblingModeType).
2167  * The technical details of the scrambling algorithm are available only
2168  * to bona-fide users upon signature of a Non Disclosure Agreement (NDA)
2169  * administered by the DVB Common Scrambling Algorithm Custodian.
2170  *
2171  * Parses out the scrambling mode from the @descriptor.
2172  *
2173  * Returns: %TRUE if the parsing happened correctly, else %FALSE.
2174  */
2175 gboolean
gst_mpegts_descriptor_parse_dvb_scrambling(const GstMpegtsDescriptor * descriptor,GstMpegtsDVBScramblingModeType * scrambling_mode)2176 gst_mpegts_descriptor_parse_dvb_scrambling (const GstMpegtsDescriptor *
2177     descriptor, GstMpegtsDVBScramblingModeType * scrambling_mode)
2178 {
2179   guint8 *data;
2180 
2181   g_return_val_if_fail (descriptor != NULL && scrambling_mode != NULL, FALSE);
2182   __common_desc_checks_exact (descriptor, GST_MTS_DESC_DVB_SCRAMBLING, 1,
2183       FALSE);
2184 
2185   data = (guint8 *) descriptor->data + 2;
2186 
2187   *scrambling_mode = *data;
2188 
2189   return TRUE;
2190 }
2191 
2192 /* GST_MTS_DESC_DVB_DATA_BROADCAST_ID (0x66) */
2193 /**
2194  * gst_mpegts_descriptor_parse_dvb_data_broadcast_id:
2195  * @descriptor: a %GST_MTS_DESC_DVB_DATA_BROADCAST_ID #GstMpegtsDescriptor
2196  * @data_broadcast_id: (out): the data broadcast id
2197  * @id_selector_bytes: (out) (transfer full) (array length=len): the selector bytes, if present
2198  * @len: (out): the length of #id_selector_bytes
2199  *
2200  * Parses out the data broadcast id from the @descriptor.
2201  *
2202  * Returns: %TRUE if the parsing happened correctly, else %FALSE.
2203  */
2204 gboolean
gst_mpegts_descriptor_parse_dvb_data_broadcast_id(const GstMpegtsDescriptor * descriptor,guint16 * data_broadcast_id,guint8 ** id_selector_bytes,guint8 * len)2205 gst_mpegts_descriptor_parse_dvb_data_broadcast_id (const GstMpegtsDescriptor
2206     * descriptor, guint16 * data_broadcast_id, guint8 ** id_selector_bytes,
2207     guint8 * len)
2208 {
2209   guint8 *data;
2210 
2211   g_return_val_if_fail (descriptor != NULL && data_broadcast_id != NULL &&
2212       id_selector_bytes != NULL, FALSE);
2213   __common_desc_checks (descriptor, GST_MTS_DESC_DVB_DATA_BROADCAST_ID, 2,
2214       FALSE);
2215 
2216   data = (guint8 *) descriptor->data + 2;
2217 
2218   *data_broadcast_id = GST_READ_UINT16_BE (data);
2219   data += 2;
2220 
2221   *len = descriptor->length - 2;
2222 
2223   *id_selector_bytes = g_memdup (data, *len);
2224 
2225   return TRUE;
2226 }
2227 
2228 /* GST_MTS_DESC_EXT_DVB_T2_DELIVERY_SYSTEM (0x7F && 0x04) */
2229 static GstMpegtsT2DeliverySystemDescriptor
_gst_mpegts_t2_delivery_system_descriptor_copy(GstMpegtsT2DeliverySystemDescriptor * source)2230     * _gst_mpegts_t2_delivery_system_descriptor_copy
2231     (GstMpegtsT2DeliverySystemDescriptor * source)
2232 {
2233   GstMpegtsT2DeliverySystemDescriptor *copy;
2234 
2235   copy = g_slice_dup (GstMpegtsT2DeliverySystemDescriptor, source);
2236   copy->cells = g_ptr_array_ref (source->cells);
2237 
2238   return copy;
2239 }
2240 
gst_mpegts_t2_delivery_system_descriptor_free(GstMpegtsT2DeliverySystemDescriptor * source)2241 void gst_mpegts_t2_delivery_system_descriptor_free
2242     (GstMpegtsT2DeliverySystemDescriptor * source)
2243 {
2244   g_ptr_array_unref (source->cells);
2245   g_slice_free (GstMpegtsT2DeliverySystemDescriptor, source);
2246 }
2247 
2248 G_DEFINE_BOXED_TYPE (GstMpegtsT2DeliverySystemDescriptor,
2249     gst_mpegts_t2_delivery_system_descriptor,
2250     (GBoxedCopyFunc) _gst_mpegts_t2_delivery_system_descriptor_copy,
2251     (GFreeFunc) gst_mpegts_t2_delivery_system_descriptor_free);
2252 
2253 DEFINE_STATIC_COPY_FUNCTION (GstMpegtsT2DeliverySystemCellExtension,
2254     gst_mpegts_t2_delivery_system_cell_extension);
2255 
2256 DEFINE_STATIC_FREE_FUNCTION (GstMpegtsT2DeliverySystemCellExtension,
2257     gst_mpegts_t2_delivery_system_cell_extension);
2258 
2259 G_DEFINE_BOXED_TYPE (GstMpegtsT2DeliverySystemCellExtension,
2260     gst_mpegts_t2_delivery_system_cell_extension,
2261     (GBoxedCopyFunc) _gst_mpegts_t2_delivery_system_cell_extension_copy,
2262     (GFreeFunc) _gst_mpegts_t2_delivery_system_cell_extension_free);
2263 
2264 static GstMpegtsT2DeliverySystemCell *
_gst_mpegts_t2_delivery_system_cell_copy(GstMpegtsT2DeliverySystemCell * source)2265 _gst_mpegts_t2_delivery_system_cell_copy (GstMpegtsT2DeliverySystemCell
2266     * source)
2267 {
2268   GstMpegtsT2DeliverySystemCell *copy =
2269       g_slice_dup (GstMpegtsT2DeliverySystemCell, source);
2270   copy->centre_frequencies = g_array_ref (source->centre_frequencies);
2271   copy->sub_cells = g_ptr_array_ref (source->sub_cells);
2272   return copy;
2273 }
2274 
2275 static void
_gst_mpegts_t2_delivery_system_cell_free(GstMpegtsT2DeliverySystemCell * cell)2276 _gst_mpegts_t2_delivery_system_cell_free (GstMpegtsT2DeliverySystemCell * cell)
2277 {
2278   g_ptr_array_unref (cell->sub_cells);
2279   g_array_unref (cell->centre_frequencies);
2280   g_slice_free (GstMpegtsT2DeliverySystemCell, cell);
2281 }
2282 
2283 G_DEFINE_BOXED_TYPE (GstMpegtsT2DeliverySystemCell,
2284     gst_mpegts_t2_delivery_system_cell,
2285     (GBoxedCopyFunc) _gst_mpegts_t2_delivery_system_cell_copy,
2286     (GFreeFunc) _gst_mpegts_t2_delivery_system_cell_free);
2287 
2288 /**
2289  * gst_mpegts_descriptor_parse_dvb_t2_delivery_system:
2290  * @descriptor: a %GST_MTS_DESC_EXT_DVB_T2_DELIVERY_SYSTEM #GstMpegtsDescriptor
2291  * @res: (out) (transfer full): #GstMpegtsT2DeliverySystemDescriptor
2292  *
2293  * Parses out the DVB-T2 delivery system from the @descriptor.
2294  *
2295  * Returns: %TRUE if the parsing happened correctly, else %FALSE.
2296  */
2297 gboolean
gst_mpegts_descriptor_parse_dvb_t2_delivery_system(const GstMpegtsDescriptor * descriptor,GstMpegtsT2DeliverySystemDescriptor ** desc)2298 gst_mpegts_descriptor_parse_dvb_t2_delivery_system (const GstMpegtsDescriptor
2299     * descriptor, GstMpegtsT2DeliverySystemDescriptor ** desc)
2300 {
2301   guint8 *data;
2302   guint8 len, freq_len, sub_cell_len;
2303   guint32 tmp_freq;
2304   guint8 i;
2305   GstMpegtsT2DeliverySystemDescriptor *res;
2306 
2307   g_return_val_if_fail (descriptor != NULL && desc != NULL, FALSE);
2308   __common_desc_ext_checks (descriptor, GST_MTS_DESC_EXT_DVB_T2_DELIVERY_SYSTEM,
2309       4, FALSE);
2310 
2311   data = (guint8 *) descriptor->data + 3;
2312 
2313   res = g_slice_new0 (GstMpegtsT2DeliverySystemDescriptor);
2314 
2315   res->plp_id = *data;
2316   data += 1;
2317 
2318   res->t2_system_id = GST_READ_UINT16_BE (data);
2319   data += 2;
2320 
2321   if (descriptor->length > 4) {
2322     // FIXME: siso / miso
2323     res->siso_miso = (*data >> 6) & 0x03;
2324     switch ((*data >> 2) & 0x0f) {
2325       case 0:
2326         res->bandwidth = 8000000;
2327         break;
2328       case 1:
2329         res->bandwidth = 7000000;
2330         break;
2331       case 2:
2332         res->bandwidth = 6000000;
2333         break;
2334       case 3:
2335         res->bandwidth = 5000000;
2336         break;
2337       case 4:
2338         res->bandwidth = 10000000;
2339         break;
2340       case 5:
2341         res->bandwidth = 1712000;
2342         break;
2343       default:
2344         res->bandwidth = 0;
2345         break;
2346     }
2347     data += 1;
2348 
2349     switch ((*data >> 5) & 0x07) {
2350       case 0:
2351         res->guard_interval = GST_MPEGTS_GUARD_INTERVAL_1_32;
2352         break;
2353       case 1:
2354         res->guard_interval = GST_MPEGTS_GUARD_INTERVAL_1_16;
2355         break;
2356       case 2:
2357         res->guard_interval = GST_MPEGTS_GUARD_INTERVAL_1_8;
2358         break;
2359       case 3:
2360         res->guard_interval = GST_MPEGTS_GUARD_INTERVAL_1_4;
2361         break;
2362       case 4:
2363         res->guard_interval = GST_MPEGTS_GUARD_INTERVAL_1_128;
2364         break;
2365       case 5:
2366         res->guard_interval = GST_MPEGTS_GUARD_INTERVAL_19_128;
2367         break;
2368       case 6:
2369         res->guard_interval = GST_MPEGTS_GUARD_INTERVAL_19_256;
2370         break;
2371       default:
2372         break;
2373     }
2374 
2375     switch ((*data >> 2) & 0x07) {
2376       case 0:
2377         res->transmission_mode = GST_MPEGTS_TRANSMISSION_MODE_2K;
2378         break;
2379       case 1:
2380         res->transmission_mode = GST_MPEGTS_TRANSMISSION_MODE_8K;
2381         break;
2382       case 2:
2383         res->transmission_mode = GST_MPEGTS_TRANSMISSION_MODE_4K;
2384         break;
2385       case 3:
2386         res->transmission_mode = GST_MPEGTS_TRANSMISSION_MODE_1K;
2387         break;
2388       case 4:
2389         res->transmission_mode = GST_MPEGTS_TRANSMISSION_MODE_16K;
2390         break;
2391       case 5:
2392         res->transmission_mode = GST_MPEGTS_TRANSMISSION_MODE_32K;
2393         break;
2394       default:
2395         break;
2396     }
2397     res->other_frequency = (*data >> 1) & 0x01;
2398     res->tfs = (*data) & 0x01;
2399     data += 1;
2400 
2401     len = descriptor->length - 6;
2402 
2403     res->cells = g_ptr_array_new_with_free_func ((GDestroyNotify)
2404         _gst_mpegts_t2_delivery_system_cell_free);
2405 
2406     for (i = 0; i < len;) {
2407       GstMpegtsT2DeliverySystemCell *cell;
2408       guint8 j, k;
2409 
2410       cell = g_slice_new0 (GstMpegtsT2DeliverySystemCell);
2411       g_ptr_array_add (res->cells, cell);
2412 
2413       cell->cell_id = GST_READ_UINT16_BE (data);
2414       data += 2;
2415       i += 2;
2416 
2417       cell->centre_frequencies = g_array_new (FALSE, FALSE, sizeof (guint32));
2418 
2419       if (res->tfs == TRUE) {
2420         freq_len = *data;
2421         data += 1;
2422         i += 1;
2423 
2424         for (j = 0; j < freq_len;) {
2425           tmp_freq = GST_READ_UINT32_BE (data) * 10;
2426           g_array_append_val (cell->centre_frequencies, tmp_freq);
2427           data += 4;
2428           j += 4;
2429           i += 4;
2430         }
2431       } else {
2432         tmp_freq = GST_READ_UINT32_BE (data) * 10;
2433         g_array_append_val (cell->centre_frequencies, tmp_freq);
2434         data += 4;
2435         i += 4;
2436       }
2437       sub_cell_len = (*data);
2438       data += 1;
2439       i += 1;
2440 
2441       cell->sub_cells = g_ptr_array_new_with_free_func ((GDestroyNotify)
2442           _gst_mpegts_t2_delivery_system_cell_extension_free);
2443 
2444       for (k = 0; k < sub_cell_len;) {
2445         GstMpegtsT2DeliverySystemCellExtension *cell_ext;
2446         cell_ext = g_slice_new0 (GstMpegtsT2DeliverySystemCellExtension);
2447 
2448         g_ptr_array_add (cell->sub_cells, cell_ext);
2449         cell_ext->cell_id_extension = *data;
2450         data += 1;
2451 
2452         cell_ext->transposer_frequency = GST_READ_UINT32_BE (data) * 10;
2453         data += 4;
2454         i += 5;
2455         k += 5;
2456       }
2457     }
2458   }
2459 
2460   *desc = res;
2461   return TRUE;
2462 }
2463