2 * gstmpegtsdescriptor.c -
3 * Copyright (C) 2013 Edward Hervey
6 * Edward Hervey <edward@collabora.com>
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.
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.
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.
31 #include "gstmpegts-private.h"
33 #define DEFINE_STATIC_COPY_FUNCTION(type, name) \
34 static type * _##name##_copy (type * source) \
36 return g_slice_dup (type, source); \
39 #define DEFINE_STATIC_FREE_FUNCTION(type, name) \
40 static void _##name##_free (type * source) \
42 g_slice_free (type, source); \
46 * SECTION:gstmpegtsdescriptor
47 * @title: Base MPEG-TS descriptors
48 * @short_description: Descriptors for ITU H.222.0 | ISO/IEC 13818-1
49 * @include: gst/mpegts/mpegts.h
51 * - GstMpegtsDescriptor
52 * - GstMpegtsDescriptorType
53 * - GstMpegtsMiscDescriptorType
54 * - gst_mpegts_find_descriptor
55 * - gst_mpegts_parse_descriptors
56 * - gst_mpegts_descriptor_from_custom
57 * - gst_mpegts_descriptor_from_registration
58 * - GstMpegtsISO639LanguageDescriptor
59 * - GstMpegtsIso639AudioType
60 * - gst_mpegts_descriptor_parse_iso_639_language
61 * - gst_mpegts_descriptor_parse_iso_639_language_idx
62 * - gst_mpegts_descriptor_parse_iso_639_language_nb
63 * - gst_mpegts_iso_639_language_descriptor_free
64 * - GstMpegtsLogicalChannel
65 * - GstMpegtsLogicalChannelDescriptor
66 * - gst_mpegts_descriptor_parse_logical_channel
67 * - GST_TYPE_MPEGTS_DVB_CODE_RATE
68 * - GST_TYPE_MPEGTS_CABLE_OUTER_FEC_SCHEME
69 * - GST_TYPE_MPEGTS_MODULATION_TYPE
70 * - GST_TYPE_MPEGTS_SATELLITE_POLARIZATION_TYPE
71 * - GST_TYPE_MPEGTS_SATELLITE_ROLLOFF
72 * - GST_TYPE_MPEGTS_ISO_639_LANGUAGE
73 * - GST_TYPE_MPEGTS_DESCRIPTOR
74 * - GST_TYPE_MPEGTS_DVB_SERVICE_TYPE
75 * - GST_TYPE_MPEGTS_DESCRIPTOR_TYPE
76 * - GST_TYPE_MPEGTS_ISO639_AUDIO_TYPE
77 * - GST_TYPE_MPEGTS_DVB_DESCRIPTOR_TYPE
78 * - GST_TYPE_MPEGTS_MISC_DESCRIPTOR_TYPE
79 * - gst_mpegts_descriptor_get_type
80 * - gst_mpegts_iso_639_language_get_type
81 * - gst_mpegts_cable_outer_fec_scheme_get_type
82 * - gst_mpegts_modulation_type_get_type
83 * - gst_mpegts_satellite_polarization_type_get_type
84 * - gst_mpegts_satellite_rolloff_get_type
85 * - gst_mpegts_descriptor_type_get_type
86 * - gst_mpegts_dvb_descriptor_type_get_type
87 * - gst_mpegts_misc_descriptor_type_get_type
88 * - gst_mpegts_iso639_audio_type_get_type
89 * - gst_mpegts_dvb_service_type_get_type
91 * These are the base descriptor types and methods.
93 * For more details, refer to the ITU H.222.0 or ISO/IEC 13818-1 specifications
94 * and other specifications mentioned in the documentation.
97 /* FIXME : Move this to proper file once we have a C file for ATSC/ISDB descriptors */
99 * SECTION:gst-atsc-descriptor
100 * @title: ATSC variants of MPEG-TS descriptors
101 * @short_description: Descriptors for the various ATSC specifications
102 * @include: gst/mpegts/mpegts.h
104 * - GstMpegtsATSCDescriptorType
105 * - GST_TYPE_MPEGTS_ATSC_DESCRIPTOR_TYPE
106 * - gst_mpegts_atsc_descriptor_type_get_type
107 * - GstMpegtsDVBDescriptorType
108 * - GstMpegtsDVBExtendedDescriptorType
110 * - gst_mpegts_descriptor_parse_dvb_content
111 * - GstMpegtsComponentDescriptor
112 * - gst_mpegts_dvb_component_descriptor_free
113 * - gst_mpegts_descriptor_parse_dvb_component
114 * - GstMpegtsExtendedEventItem
115 * - GstMpegtsExtendedEventDescriptor
116 * - gst_mpegts_extended_event_descriptor_free
117 * - gst_mpegts_descriptor_parse_dvb_extended_event
118 * - GstMpegtsSatelliteDeliverySystemDescriptor
119 * - GstMpegtsDVBCodeRate
120 * - GstMpegtsModulationType
121 * - GstMpegtsSatellitePolarizationType
122 * - GstMpegtsSatelliteRolloff
123 * - gst_mpegts_descriptor_parse_satellite_delivery_system
124 * - GstMpegtsCableDeliverySystemDescriptor
125 * - GstMpegtsCableOuterFECScheme
126 * - gst_mpegts_descriptor_parse_cable_delivery_system
127 * - GstMpegtsTerrestrialDeliverySystemDescriptor
128 * - GstMpegtsTerrestrialTransmissionMode
129 * - GstMpegtsTerrestrialGuardInterval
130 * - GstMpegtsTerrestrialHierarchy
131 * - gst_mpegts_descriptor_parse_terrestrial_delivery_system
132 * - GstMpegtsT2DeliverySystemCellExtension
133 * - GstMpegtsT2DeliverySystemCell
134 * - GstMpegtsT2DeliverySystemDescriptor
135 * - gst_mpegts_t2_delivery_system_descriptor_free
136 * - gst_mpegts_descriptor_parse_dvb_t2_delivery_system
137 * - gst_mpegts_descriptor_parse_dvb_short_event
138 * - gst_mpegts_descriptor_parse_dvb_network_name
139 * - gst_mpegts_descriptor_from_dvb_network_name
140 * - GstMpegtsDVBServiceType
141 * - gst_mpegts_descriptor_parse_dvb_service
142 * - gst_mpegts_descriptor_from_dvb_service
143 * - GstMpegtsDVBTeletextType
144 * - gst_mpegts_descriptor_parse_dvb_teletext_idx
145 * - gst_mpegts_descriptor_parse_dvb_teletext_nb
146 * - gst_mpegts_descriptor_parse_dvb_subtitling_idx
147 * - gst_mpegts_descriptor_parse_dvb_subtitling_nb
148 * - gst_mpegts_descriptor_from_dvb_subtitling
149 * - GstMpegtsDVBLinkageType
150 * - GstMpegtsDVBLinkageHandOverType
151 * - GstMpegtsDVBLinkageMobileHandOver
152 * - GstMpegtsDVBLinkageEvent
153 * - GstMpegtsDVBLinkageExtendedEvent
154 * - GstMpegtsDVBLinkageDescriptor
155 * - gst_mpegts_dvb_linkage_descriptor_free
156 * - gst_mpegts_dvb_linkage_descriptor_get_mobile_hand_over
157 * - gst_mpegts_dvb_linkage_descriptor_get_event
158 * - gst_mpegts_dvb_linkage_descriptor_get_extended_event
159 * - gst_mpegts_descriptor_parse_dvb_linkage
160 * - gst_mpegts_descriptor_parse_dvb_private_data_specifier
161 * - gst_mpegts_descriptor_parse_dvb_frequency_list
162 * - GstMpegtsDataBroadcastDescriptor
163 * - gst_mpegts_dvb_data_broadcast_descriptor_free
164 * - gst_mpegts_descriptor_parse_dvb_data_broadcast
165 * - GstMpegtsDVBScramblingModeType
166 * - gst_mpegts_descriptor_parse_dvb_scrambling
167 * - gst_mpegts_descriptor_parse_dvb_data_broadcast_id
168 * - GstMpegtsDVBParentalRatingItem
169 * - gst_mpegts_descriptor_parse_dvb_parental_rating
170 * - gst_mpegts_descriptor_parse_dvb_stream_identifier
171 * - gst_mpegts_descriptor_parse_dvb_ca_identifier
172 * - GstMpegtsDVBServiceListItem
173 * - gst_mpegts_descriptor_parse_dvb_service_list
174 * - gst_mpegts_descriptor_parse_dvb_stuffing
175 * - gst_mpegts_descriptor_parse_dvb_bouquet_name
176 * - GstMpegtsDvbMultilingualNetworkNameItem
177 * - gst_mpegts_descriptor_parse_dvb_multilingual_network_name
178 * - GstMpegtsDvbMultilingualBouquetNameItem
179 * - gst_mpegts_descriptor_parse_dvb_multilingual_bouquet_name
180 * - GstMpegtsDvbMultilingualServiceNameItem
181 * - gst_mpegts_descriptor_parse_dvb_multilingual_service_name
182 * - GstMpegtsDvbMultilingualComponentItem
183 * - gst_mpegts_descriptor_parse_dvb_multilingual_component
184 * - GST_TYPE_MPEGTS_COMPONENT_DESCRIPTOR
185 * - GST_TYPE_MPEGTS_DVB_DATA_BROADCAST_DESCRIPTOR
186 * - GST_TYPE_MPEGTS_DVB_LINKAGE_DESCRIPTOR
187 * - GST_TYPE_MPEGTS_EXTENDED_EVENT_DESCRIPTOR
188 * - GST_TYPE_MPEGTS_T2_DELIVERY_SYSTEM_DESCRIPTOR
189 * - gst_mpegts_dvb_code_rate_get_type
190 * - gst_mpegts_component_descriptor_get_type
191 * - gst_mpegts_dvb_data_broadcast_descriptor_get_type
192 * - gst_mpegts_dvb_linkage_descriptor_get_type
193 * - gst_mpegts_extended_event_descriptor_get_type
194 * - gst_mpegts_t2_delivery_system_descriptor_get_type
199 * SECTION:gst-isdb-descriptor
200 * @title: ISDB variants of MPEG-TS descriptors
201 * @short_description: Descriptors for the various ISDB specifications
202 * @include: gst/mpegts/mpegts.h
204 * - GstMpegtsISDBDescriptorType
205 * - GST_TYPE_MPEGTS_ISDB_DESCRIPTOR_TYPE
206 * - gst_mpegts_isdb_descriptor_type_get_type
213 * * Add common validation code for data presence and minimum/maximum expected
215 * * Add parsing methods for the following descriptors that were previously
216 * handled in mpegtsbase:
217 * * GST_MTS_DESC_DVB_DATA_BROADCAST_ID
218 * * GST_MTS_DESC_DVB_CAROUSEL_IDENTIFIER
219 * * GST_MTS_DESC_DVB_FREQUENCY_LIST
222 #define MAX_KNOWN_ICONV 25
224 /* First column is the original encoding,
225 * second column is the target encoding */
227 static GIConv __iconvs[MAX_KNOWN_ICONV][MAX_KNOWN_ICONV];
229 /* All these conversions will be to UTF8 */
252 _ICONV_ISO10646_UTF8,
255 /* Insert more here if needed */
259 static const gchar *iconvtablename[] = {
282 /* Insert more here if needed */
286 __initialize_descriptors (void)
290 /* Initialize converters */
291 /* FIXME : How/when should we close them ??? */
292 for (i = 0; i < MAX_KNOWN_ICONV; i++) {
293 for (j = 0; j < MAX_KNOWN_ICONV; j++)
294 __iconvs[i][j] = ((GIConv) - 1);
299 * @text: The text you want to get the encoding from
300 * @start_text: Location where the beginning of the actual text is stored
301 * @is_multibyte: Location where information whether it's a multibyte encoding
303 * @returns: GIconv for conversion or NULL
305 static LocalIconvCode
306 get_encoding (const gchar * text, guint * start_text, gboolean * is_multibyte)
308 LocalIconvCode encoding;
311 *is_multibyte = FALSE;
314 firstbyte = (guint8) text[0];
317 g_return_val_if_fail (firstbyte != 0x00, _ICONV_UNKNOWN);
319 if (firstbyte <= 0x0B) {
320 /* 0x01 => iso 8859-5 */
321 encoding = firstbyte + _ICONV_ISO8859_4;
326 /* ETSI EN 300 468, "Selection of character table" */
333 encoding = _ICONV_UNKNOWN;
339 table = GST_READ_UINT16_BE (text + 1);
342 encoding = _ICONV_UNKNOWN + table;
344 encoding = _ICONV_UNKNOWN;
349 encoding = _ICONV_UCS_2BE;
351 *is_multibyte = TRUE;
354 /* EUC-KR implements KSX1001 */
355 encoding = _ICONV_EUC_KR;
357 *is_multibyte = TRUE;
360 encoding = _ICONV_GB2312;
364 encoding = _ICONV_UTF_16BE;
366 *is_multibyte = TRUE;
369 /* TODO : Where does this come from ?? */
370 encoding = _ICONV_ISO10646_UTF8;
384 encoding = _ICONV_UNKNOWN;
387 encoding = _ICONV_ISO6937;
393 ("Found encoding %d, first byte is 0x%02x, start_text: %u, is_multibyte: %d",
394 encoding, firstbyte, *start_text, *is_multibyte);
400 _get_iconv (LocalIconvCode from, LocalIconvCode to)
402 if (__iconvs[from][to] == (GIConv) - 1)
403 __iconvs[from][to] = g_iconv_open (iconvtablename[to],
404 iconvtablename[from]);
405 return __iconvs[from][to];
409 _encode_control_codes (gchar * text, gsize length, gboolean is_multibyte)
413 while (pos < length) {
415 guint16 code = GST_READ_UINT16_BE (text + pos);
416 if (code == 0x000A) {
418 text[pos + 1] = 0x8A;
422 guint8 code = text[pos];
431 * dvb_text_from_utf8:
432 * @text: The text to convert. This should be in UTF-8 format
433 * @out_size: (out): the byte length of the new text
435 * Converts UTF-8 strings to text characters compliant with EN 300 468.
436 * The converted text can be used directly in DVB #GstMpegtsDescriptor
438 * The function will try different character maps until the string is
439 * completely converted.
441 * The function tries the default ISO 6937 character map first.
443 * If no character map that contains all characters could be found, the
444 * string is converted to ISO 6937 with unknown characters set to `?`.
446 * Returns: (transfer full): byte array of size @out_size
449 dvb_text_from_utf8 (const gchar * text, gsize * out_size)
451 GError *error = NULL;
455 GIConv giconv = (GIConv) - 1;
457 /* We test character maps one-by-one. Start with the default */
458 encoding = _ICONV_ISO6937;
459 giconv = _get_iconv (_ICONV_UTF8, encoding);
460 out_text = g_convert_with_iconv (text, -1, giconv, NULL, out_size, &error);
463 GST_DEBUG ("Using default ISO6937 encoding");
467 g_clear_error (&error);
469 for (encoding = _ICONV_ISO8859_1; encoding <= _ICONV_ISO10646_UTF8;
471 giconv = _get_iconv (_ICONV_UTF8, encoding);
472 if (giconv == (GIConv) - 1)
474 out_text = g_convert_with_iconv (text, -1, giconv, NULL, out_size, &error);
477 GST_DEBUG ("Found suitable character map - %s", iconvtablename[encoding]);
481 g_clear_error (&error);
484 out_text = g_convert_with_fallback (text, -1, iconvtablename[_ICONV_ISO6937],
485 iconvtablename[_ICONV_UTF8], "?", NULL, out_size, &error);
490 GST_WARNING ("Could not convert from utf-8: %s", error->message);
491 g_error_free (error);
498 /* Default encoding contains no selection bytes. */
499 _encode_control_codes (out_text, *out_size, FALSE);
500 return (guint8 *) out_text;
501 case _ICONV_ISO8859_1:
502 case _ICONV_ISO8859_2:
503 case _ICONV_ISO8859_3:
504 case _ICONV_ISO8859_4:
505 /* These character sets requires 3 selection bytes */
506 _encode_control_codes (out_text, *out_size, FALSE);
507 out_buffer = g_malloc (*out_size + 3);
508 out_buffer[0] = 0x10;
509 out_buffer[1] = 0x00;
510 out_buffer[2] = encoding - _ICONV_ISO8859_1 + 1;
511 memcpy (out_buffer + 3, out_text, *out_size);
515 case _ICONV_ISO8859_5:
516 case _ICONV_ISO8859_6:
517 case _ICONV_ISO8859_7:
518 case _ICONV_ISO8859_8:
519 case _ICONV_ISO8859_9:
520 case _ICONV_ISO8859_10:
521 case _ICONV_ISO8859_11:
522 case _ICONV_ISO8859_12:
523 case _ICONV_ISO8859_13:
524 case _ICONV_ISO8859_14:
525 case _ICONV_ISO8859_15:
526 /* These character sets requires 1 selection byte */
527 _encode_control_codes (out_text, *out_size, FALSE);
528 out_buffer = g_malloc (*out_size + 1);
529 out_buffer[0] = encoding - _ICONV_ISO8859_5 + 1;
530 memcpy (out_buffer + 1, out_text, *out_size);
536 case _ICONV_UTF_16BE:
537 /* These character sets requires 1 selection byte */
538 _encode_control_codes (out_text, *out_size, TRUE);
539 out_buffer = g_malloc (*out_size + 1);
540 out_buffer[0] = encoding - _ICONV_UCS_2BE + 0x11;
541 memcpy (out_buffer + 1, out_text, *out_size);
546 case _ICONV_ISO10646_UTF8:
547 /* These character sets requires 1 selection byte */
548 _encode_control_codes (out_text, *out_size, FALSE);
549 out_buffer = g_malloc (*out_size + 1);
550 out_buffer[0] = encoding - _ICONV_UCS_2BE + 0x11;
551 memcpy (out_buffer + 1, out_text, *out_size);
562 * @text: The text to convert. It may include pango markup (<b> and </b>)
563 * @length: The length of the string -1 if it's nul-terminated
564 * @start: Where to start converting in the text
565 * @encoding: The encoding of text
566 * @is_multibyte: Whether the encoding is a multibyte encoding
567 * @error: The location to store the error, or NULL to ignore errors
568 * @returns: UTF-8 encoded string
570 * Convert text to UTF-8.
573 convert_to_utf8 (const gchar * text, gint length, guint start,
574 GIConv giconv, gboolean is_multibyte, GError ** error)
582 pos = tmp = g_malloc (length * 2);
586 while (*text != '\0') {
587 guint16 code = GST_READ_UINT16_BE (text);
590 case 0xE086: /* emphasis on */
591 case 0xE087: /* emphasis off */
595 pos[0] = 0x00; /* 0x00 0x0A is a new line */
610 for (i = 0; i < length; i += 2) {
611 guint16 code = GST_READ_UINT16_BE (text);
614 case 0xE086: /* emphasis on */
615 case 0xE087: /* emphasis off */
619 pos[0] = 0x00; /* 0x00 0x0A is a new line */
636 while (*text != '\0') {
637 guint8 code = (guint8) (*text);
640 case 0x86: /* emphasis on */
641 case 0x87: /* emphasis off */
657 for (i = 0; i < length; i++) {
658 guint8 code = (guint8) (*text);
661 case 0x86: /* emphasis on */
662 case 0x87: /* emphasis off */
683 g_convert_with_iconv (tmp, pos - tmp, giconv, &bread, NULL, error);
684 GST_DEBUG ("Converted to : %s", new_text);
686 new_text = g_strdup ("");
695 get_encoding_and_convert (const gchar * text, guint length)
697 GError *error = NULL;
698 gchar *converted_str;
699 guint start_text = 0;
700 gboolean is_multibyte;
701 LocalIconvCode encoding;
702 GIConv giconv = (GIConv) - 1;
704 g_return_val_if_fail (text != NULL, NULL);
706 if (text == NULL || length == 0)
707 return g_strdup ("");
709 encoding = get_encoding (text, &start_text, &is_multibyte);
711 if (encoding > _ICONV_UNKNOWN && encoding < _ICONV_MAX) {
712 GST_DEBUG ("Encoding %s", iconvtablename[encoding]);
713 giconv = _get_iconv (encoding, _ICONV_UTF8);
715 GST_FIXME ("Could not detect encoding. Returning NULL string");
716 converted_str = NULL;
720 converted_str = convert_to_utf8 (text, length - start_text, start_text,
721 giconv, is_multibyte, &error);
723 GST_WARNING ("Could not convert string: %s", error->message);
724 g_free (converted_str);
725 g_error_free (error);
728 if (encoding >= _ICONV_ISO8859_2 && encoding <= _ICONV_ISO8859_15) {
729 /* Sometimes using the standard 8859-1 set fixes issues */
730 GST_DEBUG ("Encoding %s", iconvtablename[_ICONV_ISO8859_1]);
731 giconv = _get_iconv (_ICONV_ISO8859_1, _ICONV_UTF8);
733 GST_INFO ("Trying encoding ISO 8859-1");
734 converted_str = convert_to_utf8 (text, length, 1, giconv, FALSE, &error);
737 ("Could not convert string while assuming encoding ISO 8859-1: %s",
739 g_error_free (error);
742 } else if (encoding == _ICONV_ISO6937) {
744 /* The first part of ISO 6937 is identical to ISO 8859-9, but
745 * they differ in the second part. Some channels don't
746 * provide the first byte that indicates ISO 8859-9 encoding.
747 * If decoding from ISO 6937 failed, we try ISO 8859-9 here.
749 giconv = _get_iconv (_ICONV_ISO8859_9, _ICONV_UTF8);
751 GST_INFO ("Trying encoding ISO 8859-9");
752 converted_str = convert_to_utf8 (text, length, 0, giconv, FALSE, &error);
755 ("Could not convert string while assuming encoding ISO 8859-9: %s",
757 g_error_free (error);
765 return converted_str;
770 return g_strndup (text, length - start_text);
775 convert_lang_code (guint8 * data)
778 /* the iso language code and country code is always 3 byte long */
779 code = g_malloc0 (4);
780 memcpy (code, data, 3);
786 _packetize_descriptor_array (GPtrArray * array, guint8 ** out_data)
789 GstMpegtsDescriptor *descriptor;
791 g_return_if_fail (out_data != NULL);
792 g_return_if_fail (*out_data != NULL);
797 for (i = 0; i < array->len; i++) {
798 descriptor = g_ptr_array_index (array, i);
800 memcpy (*out_data, descriptor->data, descriptor->length + 2);
801 *out_data += descriptor->length + 2;
805 GstMpegtsDescriptor *
806 _new_descriptor (guint8 tag, guint8 length)
808 GstMpegtsDescriptor *descriptor;
811 descriptor = g_slice_new (GstMpegtsDescriptor);
813 descriptor->tag = tag;
814 descriptor->tag_extension = 0;
815 descriptor->length = length;
817 descriptor->data = g_malloc (length + 2);
819 data = descriptor->data;
821 *data++ = descriptor->tag;
822 *data = descriptor->length;
827 GstMpegtsDescriptor *
828 _new_descriptor_with_extension (guint8 tag, guint8 tag_extension, guint8 length)
830 GstMpegtsDescriptor *descriptor;
833 descriptor = g_slice_new (GstMpegtsDescriptor);
835 descriptor->tag = tag;
836 descriptor->tag_extension = tag_extension;
837 descriptor->length = length + 1;
839 descriptor->data = g_malloc (length + 3);
841 data = descriptor->data;
843 *data++ = descriptor->tag;
844 *data++ = descriptor->length;
845 *data = descriptor->tag_extension;
850 static GstMpegtsDescriptor *
851 _copy_descriptor (GstMpegtsDescriptor * desc)
853 GstMpegtsDescriptor *copy;
855 copy = g_slice_dup (GstMpegtsDescriptor, desc);
856 copy->data = g_memdup (desc->data, desc->length + 2);
862 * gst_mpegts_descriptor_free:
863 * @desc: The descriptor to free
868 gst_mpegts_descriptor_free (GstMpegtsDescriptor * desc)
870 g_free ((gpointer) desc->data);
871 g_slice_free (GstMpegtsDescriptor, desc);
874 G_DEFINE_BOXED_TYPE (GstMpegtsDescriptor, gst_mpegts_descriptor,
875 (GBoxedCopyFunc) _copy_descriptor,
876 (GBoxedFreeFunc) gst_mpegts_descriptor_free);
879 * gst_mpegts_parse_descriptors:
880 * @buffer: (transfer none): descriptors to parse
881 * @buf_len: Size of @buffer
883 * Parses the descriptors present in @buffer and returns them as an
886 * Note: The data provided in @buffer will not be copied.
888 * Returns: (transfer full) (element-type GstMpegtsDescriptor): an
889 * array of the parsed descriptors or %NULL if there was an error.
890 * Release with #g_array_unref when done with it.
893 gst_mpegts_parse_descriptors (guint8 * buffer, gsize buf_len)
898 guint i, nb_desc = 0;
902 return g_ptr_array_new ();
906 GST_MEMDUMP ("Full descriptor array", buffer, buf_len);
908 while (data - buffer < buf_len) {
909 data++; /* skip tag */
912 if (data - buffer > buf_len) {
913 GST_WARNING ("invalid descriptor length %d now at %d max %"
914 G_GSIZE_FORMAT, length, (gint) (data - buffer), buf_len);
922 GST_DEBUG ("Saw %d descriptors, read %" G_GSIZE_FORMAT " bytes",
923 nb_desc, (gsize) (data - buffer));
925 if (data - buffer != buf_len) {
926 GST_WARNING ("descriptors size %d expected %" G_GSIZE_FORMAT,
927 (gint) (data - buffer), buf_len);
932 g_ptr_array_new_full (nb_desc + 1,
933 (GDestroyNotify) gst_mpegts_descriptor_free);
937 for (i = 0; i < nb_desc; i++) {
938 GstMpegtsDescriptor *desc = g_slice_new0 (GstMpegtsDescriptor);
942 desc->length = *data++;
943 /* Copy the data now that we known the size */
944 desc->data = g_memdup (desc->data, desc->length + 2);
945 GST_LOG ("descriptor 0x%02x length:%d", desc->tag, desc->length);
946 GST_MEMDUMP ("descriptor", desc->data + 2, desc->length);
947 /* extended descriptors */
948 if (G_UNLIKELY (desc->tag == 0x7f))
949 desc->tag_extension = *data;
951 data += desc->length;
953 /* Set the descriptor in the array */
954 g_ptr_array_index (res, i) = desc;
963 * gst_mpegts_find_descriptor:
964 * @descriptors: (element-type GstMpegtsDescriptor) (transfer none): an array
965 * of #GstMpegtsDescriptor
966 * @tag: the tag to look for
968 * Finds the first descriptor of type @tag in the array.
970 * Note: To look for descriptors that can be present more than once in an
971 * array of descriptors, iterate the #GArray manually.
973 * Returns: (transfer none): the first descriptor matching @tag, else %NULL.
975 const GstMpegtsDescriptor *
976 gst_mpegts_find_descriptor (GPtrArray * descriptors, guint8 tag)
980 g_return_val_if_fail (descriptors != NULL, NULL);
982 nb_desc = descriptors->len;
983 for (i = 0; i < nb_desc; i++) {
984 GstMpegtsDescriptor *desc = g_ptr_array_index (descriptors, i);
985 if (desc->tag == tag)
986 return (const GstMpegtsDescriptor *) desc;
991 /* GST_MTS_DESC_REGISTRATION (0x05) */
993 * gst_mpegts_descriptor_from_registration:
994 * @format_identifier: (transfer none): a 4 character format identifier string
995 * @additional_info: (transfer none) (allow-none) (array length=additional_info_length): pointer to optional additional info
996 * @additional_info_length: length of the optional @additional_info
998 * Creates a %GST_MTS_DESC_REGISTRATION #GstMpegtsDescriptor
1000 * Return: #GstMpegtsDescriptor, %NULL on failure
1002 GstMpegtsDescriptor *
1003 gst_mpegts_descriptor_from_registration (const gchar * format_identifier,
1004 guint8 * additional_info, gsize additional_info_length)
1006 GstMpegtsDescriptor *descriptor;
1008 g_return_val_if_fail (format_identifier != NULL, NULL);
1009 g_return_val_if_fail (additional_info_length > 0 || !additional_info, NULL);
1011 descriptor = _new_descriptor (GST_MTS_DESC_REGISTRATION,
1012 4 + additional_info_length);
1014 memcpy (descriptor->data + 2, format_identifier, 4);
1015 if (additional_info && (additional_info_length > 0))
1016 memcpy (descriptor->data + 6, additional_info, additional_info_length);
1021 /* GST_MTS_DESC_CA (0x09) */
1024 * gst_mpegts_descriptor_parse_ca:
1025 * @descriptor: a %GST_MTS_DESC_CA #GstMpegtsDescriptor
1026 * @ca_system_id: (out): the type of CA system used
1027 * @ca_pid: (out): The PID containing ECM or EMM data
1028 * @private_data: (out) (allow-none) (array length=private_data_size): The private data
1029 * @private_data_size: (out) (allow-none): The size of @private_data in bytes
1031 * Extracts the Conditional Access information from @descriptor.
1033 * Returns: %TRUE if parsing succeeded, else %FALSE.
1037 gst_mpegts_descriptor_parse_ca (GstMpegtsDescriptor * descriptor,
1038 guint16 * ca_system_id, guint16 * ca_pid,
1039 const guint8 ** private_data, gsize * private_data_size)
1043 g_return_val_if_fail (descriptor != NULL && ca_system_id != NULL
1044 && ca_pid != NULL, FALSE);
1045 /* The smallest CA is 4 bytes (though not having any private data
1046 * sounds a bit ... weird) */
1047 __common_desc_checks (descriptor, GST_MTS_DESC_CA, 4, FALSE);
1049 data = (guint8 *) descriptor->data + 2;
1050 *ca_system_id = GST_READ_UINT16_BE (data);
1052 *ca_pid = GST_READ_UINT16_BE (data) & 0x1fff;
1054 if (private_data && private_data_size) {
1055 *private_data = data;
1056 *private_data_size = descriptor->length - 4;
1062 /* GST_MTS_DESC_ISO_639_LANGUAGE (0x0A) */
1063 static GstMpegtsISO639LanguageDescriptor *
1064 _gst_mpegts_iso_639_language_descriptor_copy (GstMpegtsISO639LanguageDescriptor
1067 GstMpegtsISO639LanguageDescriptor *copy;
1070 copy = g_slice_dup (GstMpegtsISO639LanguageDescriptor, source);
1072 for (i = 0; i < source->nb_language; i++) {
1073 copy->language[i] = g_strdup (source->language[i]);
1080 gst_mpegts_iso_639_language_descriptor_free (GstMpegtsISO639LanguageDescriptor
1085 for (i = 0; i < desc->nb_language; i++) {
1086 g_free (desc->language[i]);
1088 g_slice_free (GstMpegtsISO639LanguageDescriptor, desc);
1091 G_DEFINE_BOXED_TYPE (GstMpegtsISO639LanguageDescriptor,
1092 gst_mpegts_iso_639_language,
1093 (GBoxedCopyFunc) _gst_mpegts_iso_639_language_descriptor_copy,
1094 (GFreeFunc) gst_mpegts_iso_639_language_descriptor_free);
1097 * gst_mpegts_descriptor_parse_iso_639_language:
1098 * @descriptor: a %GST_MTS_DESC_ISO_639_LANGUAGE #GstMpegtsDescriptor
1099 * @res: (out) (transfer full): the #GstMpegtsISO639LanguageDescriptor to fill
1101 * Extracts the iso 639-2 language information from @descriptor.
1103 * Note: Use #gst_tag_get_language_code if you want to get the the
1104 * ISO 639-1 language code from the returned ISO 639-2 one.
1106 * Returns: %TRUE if parsing succeeded, else %FALSE.
1109 gst_mpegts_descriptor_parse_iso_639_language (const GstMpegtsDescriptor *
1110 descriptor, GstMpegtsISO639LanguageDescriptor ** desc)
1114 GstMpegtsISO639LanguageDescriptor *res;
1116 g_return_val_if_fail (descriptor != NULL && desc != NULL, FALSE);
1117 /* This descriptor can be empty, no size check needed */
1118 __common_desc_check_base (descriptor, GST_MTS_DESC_ISO_639_LANGUAGE, FALSE);
1120 data = (guint8 *) descriptor->data + 2;
1122 res = g_slice_new0 (GstMpegtsISO639LanguageDescriptor);
1124 /* Each language is 3 + 1 bytes */
1125 res->nb_language = descriptor->length / 4;
1126 for (i = 0; i < res->nb_language; i++) {
1127 res->language[i] = convert_lang_code (data);
1128 res->audio_type[i] = data[3];
1139 * gst_mpegts_descriptor_parse_iso_639_language_idx:
1140 * @descriptor: a %GST_MTS_DESC_ISO_639_LANGUAGE #GstMpegtsDescriptor
1141 * @idx: Table id of the language to parse
1142 * @lang: (out) (transfer full): 4-byte gchar array to hold the language code
1143 * @audio_type: (out) (transfer none) (allow-none): the #GstMpegtsIso639AudioType to set
1145 * Extracts the iso 639-2 language information from specific table id in @descriptor.
1147 * Note: Use #gst_tag_get_language_code if you want to get the the
1148 * ISO 639-1 language code from the returned ISO 639-2 one.
1150 * Returns: %TRUE if parsing succeeded, else %FALSE.
1153 gst_mpegts_descriptor_parse_iso_639_language_idx (const GstMpegtsDescriptor *
1154 descriptor, guint idx, gchar ** lang, GstMpegtsIso639AudioType * audio_type)
1158 g_return_val_if_fail (descriptor != NULL && lang != NULL, FALSE);
1159 /* This descriptor can be empty, no size check needed */
1160 __common_desc_check_base (descriptor, GST_MTS_DESC_ISO_639_LANGUAGE, FALSE);
1162 if (descriptor->length / 4 <= idx)
1165 data = (guint8 *) descriptor->data + 2 + idx * 4;
1167 *lang = convert_lang_code (data);
1172 *audio_type = *data;
1178 * gst_mpegts_descriptor_parse_iso_639_language_nb:
1179 * @descriptor: a %GST_MTS_DESC_ISO_639_LANGUAGE #GstMpegtsDescriptor
1181 * Returns: The number of languages in @descriptor
1184 gst_mpegts_descriptor_parse_iso_639_language_nb (const GstMpegtsDescriptor *
1187 g_return_val_if_fail (descriptor != NULL, 0);
1188 /* This descriptor can be empty, no size check needed */
1189 __common_desc_check_base (descriptor, GST_MTS_DESC_ISO_639_LANGUAGE, FALSE);
1191 return descriptor->length / 4;
1195 * gst_mpegts_descriptor_from_iso_639_language:
1196 * @language: (transfer none): ISO-639-2 language 3-char code
1198 * Creates a %GST_MTS_DESC_ISO_639_LANGUAGE #GstMpegtsDescriptor with
1201 * Return: #GstMpegtsDescriptor, %NULL on failure
1203 GstMpegtsDescriptor *
1204 gst_mpegts_descriptor_from_iso_639_language (const gchar * language)
1206 GstMpegtsDescriptor *descriptor;
1208 g_return_val_if_fail (language != NULL, NULL);
1210 descriptor = _new_descriptor (GST_MTS_DESC_ISO_639_LANGUAGE, 4); /* a language takes 4 bytes */
1212 memcpy (descriptor->data + 2, language, 3);
1213 descriptor->data[2 + 3] = 0; /* set audio type to undefined */
1218 DEFINE_STATIC_COPY_FUNCTION (GstMpegtsLogicalChannelDescriptor,
1219 gst_mpegts_logical_channel_descriptor);
1221 DEFINE_STATIC_FREE_FUNCTION (GstMpegtsLogicalChannelDescriptor,
1222 gst_mpegts_logical_channel_descriptor);
1224 G_DEFINE_BOXED_TYPE (GstMpegtsLogicalChannelDescriptor,
1225 gst_mpegts_logical_channel_descriptor,
1226 (GBoxedCopyFunc) _gst_mpegts_logical_channel_descriptor_copy,
1227 (GFreeFunc) _gst_mpegts_logical_channel_descriptor_free);
1229 DEFINE_STATIC_COPY_FUNCTION (GstMpegtsLogicalChannel,
1230 gst_mpegts_logical_channel);
1232 DEFINE_STATIC_FREE_FUNCTION (GstMpegtsLogicalChannel,
1233 gst_mpegts_logical_channel);
1235 G_DEFINE_BOXED_TYPE (GstMpegtsLogicalChannel,
1236 gst_mpegts_logical_channel,
1237 (GBoxedCopyFunc) _gst_mpegts_logical_channel_copy,
1238 (GFreeFunc) _gst_mpegts_logical_channel_free);
1241 * gst_mpegts_descriptor_parse_logical_channel:
1242 * @descriptor: a %GST_MTS_DESC_DTG_LOGICAL_CHANNEL #GstMpegtsDescriptor
1243 * @res: (out) (transfer none): the #GstMpegtsLogicalChannelDescriptor to fill
1245 * Extracts the logical channels from @descriptor.
1247 * Returns: %TRUE if parsing succeeded, else %FALSE.
1250 gst_mpegts_descriptor_parse_logical_channel (const GstMpegtsDescriptor *
1251 descriptor, GstMpegtsLogicalChannelDescriptor * res)
1256 g_return_val_if_fail (descriptor != NULL && res != NULL, FALSE);
1257 /* This descriptor loop can be empty, no size check required */
1258 __common_desc_check_base (descriptor, GST_MTS_DESC_DTG_LOGICAL_CHANNEL,
1261 data = (guint8 *) descriptor->data + 2;
1263 res->nb_channels = descriptor->length / 4;
1265 for (i = 0; i < res->nb_channels; i++) {
1266 res->channels[i].service_id = GST_READ_UINT16_BE (data);
1268 res->channels[i].visible_service = *data >> 7;
1269 res->channels[i].logical_channel_number =
1270 GST_READ_UINT16_BE (data) & 0x03ff;
1278 * gst_mpegts_descriptor_from_custom:
1279 * @tag: descriptor tag
1280 * @data: (transfer none) (array length=length): descriptor data (after tag and length field)
1281 * @length: length of @data
1283 * Creates a #GstMpegtsDescriptor with custom @tag and @data
1285 * Returns: #GstMpegtsDescriptor
1287 GstMpegtsDescriptor *
1288 gst_mpegts_descriptor_from_custom (guint8 tag, const guint8 * data,
1291 GstMpegtsDescriptor *descriptor;
1293 g_return_val_if_fail (length > 0 || !data, NULL);
1295 descriptor = _new_descriptor (tag, length);
1297 if (data && (length > 0))
1298 memcpy (descriptor->data + 2, data, length);
1304 * gst_mpegts_descriptor_from_custom_with_extension:
1305 * @tag: descriptor tag
1306 * @tag_extension: descriptor tag extension
1307 * @data: (transfer none) (array length=length): descriptor data (after tag and length field)
1308 * @length: length of @data
1310 * Creates a #GstMpegtsDescriptor with custom @tag, @tag_extension and @data
1312 * Returns: #GstMpegtsDescriptor
1314 GstMpegtsDescriptor *
1315 gst_mpegts_descriptor_from_custom_with_extension (guint8 tag,
1316 guint8 tag_extension, const guint8 * data, gsize length)
1318 GstMpegtsDescriptor *descriptor;
1320 descriptor = _new_descriptor_with_extension (tag, tag_extension, length);
1322 if (data && (length > 0))
1323 memcpy (descriptor->data + 3, data, length);