1 /* GStreamer
2  *
3  * ts-parser.c: sample application to display mpeg-ts info from any pipeline
4  * Copyright (C) 2013
5  *           Edward Hervey <bilboed@gmail.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 
27 #define DUMP_DESCRIPTORS 0
28 
29 #include <glib.h>
30 #include <glib-object.h>
31 #include <glib/gprintf.h>
32 #include <gst/gst.h>
33 #include <gst/mpegts/mpegts.h>
34 
35 static void
gst_info_dump_mem_line(gchar * linebuf,gsize linebuf_size,const guint8 * mem,gsize mem_offset,gsize mem_size)36 gst_info_dump_mem_line (gchar * linebuf, gsize linebuf_size,
37     const guint8 * mem, gsize mem_offset, gsize mem_size)
38 {
39   gchar hexstr[50], ascstr[18], digitstr[4];
40 
41   if (mem_size > 16)
42     mem_size = 16;
43 
44   hexstr[0] = '\0';
45   ascstr[0] = '\0';
46 
47   if (mem != NULL) {
48     guint i = 0;
49 
50     mem += mem_offset;
51     while (i < mem_size) {
52       ascstr[i] = (g_ascii_isprint (mem[i])) ? mem[i] : '.';
53       g_snprintf (digitstr, sizeof (digitstr), "%02x ", mem[i]);
54       g_strlcat (hexstr, digitstr, sizeof (hexstr));
55       ++i;
56     }
57     ascstr[i] = '\0';
58   }
59 
60   g_snprintf (linebuf, linebuf_size, "%08x: %-48.48s %-16.16s",
61       (guint) mem_offset, hexstr, ascstr);
62 }
63 
64 static void
dump_memory_bytes(guint8 * data,guint len,guint spacing)65 dump_memory_bytes (guint8 * data, guint len, guint spacing)
66 {
67   gsize off = 0;
68 
69   while (off < len) {
70     gchar buf[128];
71 
72     /* gst_info_dump_mem_line will process 16 bytes at most */
73     gst_info_dump_mem_line (buf, sizeof (buf), data, off, len - off);
74     g_printf ("%*s   %s\n", spacing, "", buf);
75     off += 16;
76   }
77 }
78 
79 #define dump_memory_content(desc, spacing) dump_memory_bytes((desc)->data + 2, (desc)->length, spacing)
80 
81 static const gchar *
descriptor_name(gint val)82 descriptor_name (gint val)
83 {
84   GEnumValue *en;
85 
86   en = g_enum_get_value (G_ENUM_CLASS (g_type_class_peek
87           (GST_TYPE_MPEGTS_DESCRIPTOR_TYPE)), val);
88   if (en == NULL)
89     /* Else try with DVB enum types */
90     en = g_enum_get_value (G_ENUM_CLASS (g_type_class_peek
91             (GST_TYPE_MPEGTS_DVB_DESCRIPTOR_TYPE)), val);
92   if (en == NULL)
93     /* Else try with ATSC enum types */
94     en = g_enum_get_value (G_ENUM_CLASS (g_type_class_peek
95             (GST_TYPE_MPEGTS_ATSC_DESCRIPTOR_TYPE)), val);
96   if (en == NULL)
97     /* Else try with ISB enum types */
98     en = g_enum_get_value (G_ENUM_CLASS (g_type_class_peek
99             (GST_TYPE_MPEGTS_ISDB_DESCRIPTOR_TYPE)), val);
100   if (en == NULL)
101     /* Else try with misc enum types */
102     en = g_enum_get_value (G_ENUM_CLASS (g_type_class_peek
103             (GST_TYPE_MPEGTS_MISC_DESCRIPTOR_TYPE)), val);
104   if (en == NULL)
105     return "UNKNOWN/PRIVATE";
106   return en->value_nick;
107 }
108 
109 static const gchar *
table_id_name(gint val)110 table_id_name (gint val)
111 {
112   GEnumValue *en;
113 
114   en = g_enum_get_value (G_ENUM_CLASS (g_type_class_peek
115           (GST_TYPE_MPEGTS_SECTION_TABLE_ID)), val);
116   if (en == NULL)
117     /* Else try with DVB enum types */
118     en = g_enum_get_value (G_ENUM_CLASS (g_type_class_peek
119             (GST_TYPE_MPEGTS_SECTION_DVB_TABLE_ID)), val);
120   if (en == NULL)
121     /* Else try with ATSC enum types */
122     en = g_enum_get_value (G_ENUM_CLASS (g_type_class_peek
123             (GST_TYPE_MPEGTS_SECTION_ATSC_TABLE_ID)), val);
124   if (en == NULL)
125     /* Else try with SCTE enum types */
126     en = g_enum_get_value (G_ENUM_CLASS (g_type_class_peek
127             (GST_TYPE_MPEGTS_SECTION_SCTE_TABLE_ID)), val);
128   if (en == NULL)
129     return "UNKNOWN/PRIVATE";
130   return en->value_nick;
131 }
132 
133 static const gchar *
enum_name(GType instance_type,gint val)134 enum_name (GType instance_type, gint val)
135 {
136   GEnumValue *en;
137 
138   en = g_enum_get_value (G_ENUM_CLASS (g_type_class_peek (instance_type)), val);
139 
140   if (!en)
141     return "UNKNOWN/PRIVATE";
142   return en->value_nick;
143 }
144 
145 static void
dump_cable_delivery_descriptor(GstMpegtsDescriptor * desc,guint spacing)146 dump_cable_delivery_descriptor (GstMpegtsDescriptor * desc, guint spacing)
147 {
148   GstMpegtsCableDeliverySystemDescriptor res;
149 
150   if (gst_mpegts_descriptor_parse_cable_delivery_system (desc, &res)) {
151     g_printf ("%*s Cable Delivery Descriptor\n", spacing, "");
152     g_printf ("%*s   Frequency   : %d Hz\n", spacing, "", res.frequency);
153     g_printf ("%*s   Outer FEC   : %d (%s)\n", spacing, "", res.outer_fec,
154         enum_name (GST_TYPE_MPEGTS_CABLE_OUTER_FEC_SCHEME, res.outer_fec));
155     g_printf ("%*s   modulation  : %d (%s)\n", spacing, "", res.modulation,
156         enum_name (GST_TYPE_MPEGTS_MODULATION_TYPE, res.modulation));
157     g_printf ("%*s   Symbol rate : %d sym/s\n", spacing, "", res.symbol_rate);
158     g_printf ("%*s   Inner FEC   : %d (%s)\n", spacing, "", res.fec_inner,
159         enum_name (GST_TYPE_MPEGTS_DVB_CODE_RATE, res.fec_inner));
160   }
161 }
162 
163 static void
dump_terrestrial_delivery(GstMpegtsDescriptor * desc,guint spacing)164 dump_terrestrial_delivery (GstMpegtsDescriptor * desc, guint spacing)
165 {
166   GstMpegtsTerrestrialDeliverySystemDescriptor res;
167 
168   if (gst_mpegts_descriptor_parse_terrestrial_delivery_system (desc, &res)) {
169     g_printf ("%*s Terrestrial Delivery Descriptor\n", spacing, "");
170     g_printf ("%*s   Frequency         : %d Hz\n", spacing, "", res.frequency);
171     g_printf ("%*s   Bandwidth         : %d Hz\n", spacing, "", res.bandwidth);
172     g_printf ("%*s   Priority          : %s\n", spacing, "",
173         res.priority ? "TRUE" : "FALSE");
174     g_printf ("%*s   Time slicing      : %s\n", spacing, "",
175         res.time_slicing ? "TRUE" : "FALSE");
176     g_printf ("%*s   MPE FEC           : %s\n", spacing, "",
177         res.mpe_fec ? "TRUE" : "FALSE");
178     g_printf ("%*s   Constellation     : %d (%s)\n", spacing, "",
179         res.constellation, enum_name (GST_TYPE_MPEGTS_MODULATION_TYPE,
180             res.constellation));
181     g_printf ("%*s   Hierarchy         : %d (%s)\n", spacing, "",
182         res.hierarchy, enum_name (GST_TYPE_MPEGTS_TERRESTRIAL_HIERARCHY,
183             res.hierarchy));
184     g_printf ("%*s   Code Rate HP      : %d (%s)\n", spacing, "",
185         res.code_rate_hp, enum_name (GST_TYPE_MPEGTS_DVB_CODE_RATE,
186             res.code_rate_hp));
187     g_printf ("%*s   Code Rate LP      : %d (%s)\n", spacing, "",
188         res.code_rate_lp, enum_name (GST_TYPE_MPEGTS_DVB_CODE_RATE,
189             res.code_rate_lp));
190     g_printf ("%*s   Guard Interval    : %d (%s)\n", spacing, "",
191         res.guard_interval,
192         enum_name (GST_TYPE_MPEGTS_TERRESTRIAL_GUARD_INTERVAL,
193             res.guard_interval));
194     g_printf ("%*s   Transmission Mode : %d (%s)\n", spacing, "",
195         res.transmission_mode,
196         enum_name (GST_TYPE_MPEGTS_TERRESTRIAL_TRANSMISSION_MODE,
197             res.transmission_mode));
198     g_printf ("%*s   Other Frequency   : %s\n", spacing, "",
199         res.other_frequency ? "TRUE" : "FALSE");
200   }
201 }
202 
203 static void
dump_dvb_service_list(GstMpegtsDescriptor * desc,guint spacing)204 dump_dvb_service_list (GstMpegtsDescriptor * desc, guint spacing)
205 {
206   GPtrArray *res;
207 
208   if (gst_mpegts_descriptor_parse_dvb_service_list (desc, &res)) {
209     guint i;
210     g_printf ("%*s DVB Service List Descriptor\n", spacing, "");
211     for (i = 0; i < res->len; i++) {
212       GstMpegtsDVBServiceListItem *item = g_ptr_array_index (res, i);
213       g_printf ("%*s   Service #%d, id:0x%04x, type:0x%x (%s)\n",
214           spacing, "", i, item->service_id, item->type,
215           enum_name (GST_TYPE_MPEGTS_DVB_SERVICE_TYPE, item->type));
216     }
217     g_ptr_array_unref (res);
218   }
219 }
220 
221 static void
dump_logical_channel_descriptor(GstMpegtsDescriptor * desc,guint spacing)222 dump_logical_channel_descriptor (GstMpegtsDescriptor * desc, guint spacing)
223 {
224   GstMpegtsLogicalChannelDescriptor res;
225   guint i;
226 
227   if (gst_mpegts_descriptor_parse_logical_channel (desc, &res)) {
228     g_printf ("%*s Logical Channel Descriptor (%d channels)\n", spacing, "",
229         res.nb_channels);
230     for (i = 0; i < res.nb_channels; i++) {
231       GstMpegtsLogicalChannel *chann = &res.channels[i];
232       g_printf ("%*s   service_id: 0x%04x, logical channel number:%4d\n",
233           spacing, "", chann->service_id, chann->logical_channel_number);
234     }
235   }
236 }
237 
238 static void
dump_multiligual_network_name(GstMpegtsDescriptor * desc,guint spacing)239 dump_multiligual_network_name (GstMpegtsDescriptor * desc, guint spacing)
240 {
241   GPtrArray *items;
242   if (gst_mpegts_descriptor_parse_dvb_multilingual_network_name (desc, &items)) {
243     guint i;
244     for (i = 0; i < items->len; i++) {
245       GstMpegtsDvbMultilingualNetworkNameItem *item =
246           g_ptr_array_index (items, i);
247       g_printf ("%*s item : %u\n", spacing, "", i);
248       g_printf ("%*s   language_code : %s\n", spacing, "", item->language_code);
249       g_printf ("%*s   network_name  : %s\n", spacing, "", item->network_name);
250     }
251     g_ptr_array_unref (items);
252   }
253 }
254 
255 static void
dump_multiligual_bouquet_name(GstMpegtsDescriptor * desc,guint spacing)256 dump_multiligual_bouquet_name (GstMpegtsDescriptor * desc, guint spacing)
257 {
258   GPtrArray *items;
259   if (gst_mpegts_descriptor_parse_dvb_multilingual_bouquet_name (desc, &items)) {
260     guint i;
261     for (i = 0; i < items->len; i++) {
262       GstMpegtsDvbMultilingualBouquetNameItem *item =
263           g_ptr_array_index (items, i);
264       g_printf ("%*s item : %u\n", spacing, "", i);
265       g_printf ("%*s   language_code : %s\n", spacing, "", item->language_code);
266       g_printf ("%*s   bouguet_name  : %s\n", spacing, "", item->bouquet_name);
267     }
268     g_ptr_array_unref (items);
269   }
270 }
271 
272 static void
dump_multiligual_service_name(GstMpegtsDescriptor * desc,guint spacing)273 dump_multiligual_service_name (GstMpegtsDescriptor * desc, guint spacing)
274 {
275   GPtrArray *items;
276   if (gst_mpegts_descriptor_parse_dvb_multilingual_service_name (desc, &items)) {
277     guint i;
278     for (i = 0; i < items->len; i++) {
279       GstMpegtsDvbMultilingualServiceNameItem *item =
280           g_ptr_array_index (items, i);
281       g_printf ("%*s item : %u\n", spacing, "", i);
282       g_printf ("%*s   language_code : %s\n", spacing, "", item->language_code);
283       g_printf ("%*s   service_name  : %s\n", spacing, "", item->service_name);
284       g_printf ("%*s   provider_name : %s\n", spacing, "", item->provider_name);
285     }
286     g_ptr_array_unref (items);
287   }
288 }
289 
290 static void
dump_multiligual_component(GstMpegtsDescriptor * desc,guint spacing)291 dump_multiligual_component (GstMpegtsDescriptor * desc, guint spacing)
292 {
293   GPtrArray *items;
294   guint8 tag;
295   if (gst_mpegts_descriptor_parse_dvb_multilingual_component (desc, &tag,
296           &items)) {
297     guint8 i;
298     g_printf ("%*s component_tag : 0x%02x\n", spacing, "", tag);
299     for (i = 0; i < items->len; i++) {
300       GstMpegtsDvbMultilingualComponentItem *item =
301           g_ptr_array_index (items, i);
302       g_printf ("%*s   item : %u\n", spacing, "", i);
303       g_printf ("%*s     language_code : %s\n", spacing, "",
304           item->language_code);
305       g_printf ("%*s     description   : %s\n", spacing, "", item->description);
306     }
307     g_ptr_array_unref (items);
308   }
309 }
310 
311 static void
dump_linkage(GstMpegtsDescriptor * desc,guint spacing)312 dump_linkage (GstMpegtsDescriptor * desc, guint spacing)
313 {
314   GstMpegtsDVBLinkageDescriptor *res;
315 
316   if (gst_mpegts_descriptor_parse_dvb_linkage (desc, &res)) {
317     g_printf ("%*s Linkage Descriptor : 0x%02x (%s)\n", spacing, "",
318         res->linkage_type, enum_name (GST_TYPE_MPEGTS_DVB_LINKAGE_TYPE,
319             res->linkage_type));
320 
321     g_printf ("%*s   Transport Stream ID : 0x%04x\n", spacing, "",
322         res->transport_stream_id);
323     g_printf ("%*s   Original Network ID : 0x%04x\n", spacing, "",
324         res->original_network_id);
325     g_printf ("%*s   Service ID          : 0x%04x\n", spacing, "",
326         res->service_id);
327 
328     switch (res->linkage_type) {
329       case GST_MPEGTS_DVB_LINKAGE_MOBILE_HAND_OVER:
330       {
331         const GstMpegtsDVBLinkageMobileHandOver *linkage =
332             gst_mpegts_dvb_linkage_descriptor_get_mobile_hand_over (res);
333         g_printf ("%*s   hand_over_type    : 0x%02x (%s)\n", spacing,
334             "", linkage->hand_over_type,
335             enum_name (GST_TYPE_MPEGTS_DVB_LINKAGE_HAND_OVER_TYPE,
336                 linkage->hand_over_type));
337         g_printf ("%*s   origin_type       : %s\n", spacing, "",
338             linkage->origin_type ? "SDT" : "NIT");
339         g_printf ("%*s   network_id        : 0x%04x\n", spacing, "",
340             linkage->network_id);
341         g_printf ("%*s   initial_service_id: 0x%04x\n", spacing, "",
342             linkage->initial_service_id);
343         break;
344       }
345       case GST_MPEGTS_DVB_LINKAGE_EVENT:
346       {
347         const GstMpegtsDVBLinkageEvent *linkage =
348             gst_mpegts_dvb_linkage_descriptor_get_event (res);
349         g_printf ("%*s   target_event_id   : 0x%04x\n", spacing, "",
350             linkage->target_event_id);
351         g_printf ("%*s   target_listed     : %s\n", spacing, "",
352             linkage->target_listed ? "TRUE" : "FALSE");
353         g_printf ("%*s   event_simulcast   : %s\n", spacing, "",
354             linkage->event_simulcast ? "TRUE" : "FALSE");
355         break;
356       }
357       case GST_MPEGTS_DVB_LINKAGE_EXTENDED_EVENT:
358       {
359         guint i;
360         const GPtrArray *items =
361             gst_mpegts_dvb_linkage_descriptor_get_extended_event (res);
362 
363         for (i = 0; i < items->len; i++) {
364           GstMpegtsDVBLinkageExtendedEvent *linkage =
365               g_ptr_array_index (items, i);
366           g_printf ("%*s   target_event_id   : 0x%04x\n", spacing, "",
367               linkage->target_event_id);
368           g_printf ("%*s   target_listed     : %s\n", spacing, "",
369               linkage->target_listed ? "TRUE" : "FALSE");
370           g_printf ("%*s   event_simulcast   : %s\n", spacing, "",
371               linkage->event_simulcast ? "TRUE" : "FALSE");
372           g_printf ("%*s   link_type         : 0x%01x\n", spacing, "",
373               linkage->link_type);
374           g_printf ("%*s   target_id_type    : 0x%01x\n", spacing, "",
375               linkage->target_id_type);
376           g_printf ("%*s   original_network_id_flag : %s\n", spacing, "",
377               linkage->original_network_id_flag ? "TRUE" : "FALSE");
378           g_printf ("%*s   service_id_flag   : %s\n", spacing, "",
379               linkage->service_id_flag ? "TRUE" : "FALSE");
380           if (linkage->target_id_type == 3) {
381             g_printf ("%*s   user_defined_id   : 0x%02x\n", spacing, "",
382                 linkage->user_defined_id);
383           } else {
384             if (linkage->target_id_type == 1)
385               g_printf ("%*s   target_transport_stream_id : 0x%04x\n",
386                   spacing, "", linkage->target_transport_stream_id);
387             if (linkage->original_network_id_flag)
388               g_printf ("%*s   target_original_network_id : 0x%04x\n",
389                   spacing, "", linkage->target_original_network_id);
390             if (linkage->service_id_flag)
391               g_printf ("%*s   target_service_id          : 0x%04x\n",
392                   spacing, "", linkage->target_service_id);
393           }
394         }
395         break;
396       }
397       default:
398         break;
399     }
400     if (res->private_data_length > 0) {
401       dump_memory_bytes (res->private_data_bytes, res->private_data_length,
402           spacing + 2);
403     }
404     gst_mpegts_dvb_linkage_descriptor_free (res);
405   }
406 }
407 
408 static void
dump_component(GstMpegtsDescriptor * desc,guint spacing)409 dump_component (GstMpegtsDescriptor * desc, guint spacing)
410 {
411   GstMpegtsComponentDescriptor *res;
412 
413   if (gst_mpegts_descriptor_parse_dvb_component (desc, &res)) {
414     g_printf ("%*s stream_content : 0x%02x (%s)\n", spacing, "",
415         res->stream_content,
416         enum_name (GST_TYPE_MPEGTS_COMPONENT_STREAM_CONTENT,
417             res->stream_content));
418     g_printf ("%*s component_type : 0x%02x\n", spacing, "",
419         res->component_type);
420     g_printf ("%*s component_tag  : 0x%02x\n", spacing, "", res->component_tag);
421     g_printf ("%*s language_code  : %s\n", spacing, "", res->language_code);
422     g_printf ("%*s text           : %s\n", spacing, "",
423         res->text ? res->text : "NULL");
424     gst_mpegts_dvb_component_descriptor_free (res);
425   }
426 }
427 
428 static void
dump_content(GstMpegtsDescriptor * desc,guint spacing)429 dump_content (GstMpegtsDescriptor * desc, guint spacing)
430 {
431   GPtrArray *contents;
432   guint i;
433 
434   if (gst_mpegts_descriptor_parse_dvb_content (desc, &contents)) {
435     for (i = 0; i < contents->len; i++) {
436       GstMpegtsContent *item = g_ptr_array_index (contents, i);
437       g_printf ("%*s content nibble 1 : 0x%01x (%s)\n", spacing, "",
438           item->content_nibble_1,
439           enum_name (GST_TYPE_MPEGTS_CONTENT_NIBBLE_HI,
440               item->content_nibble_1));
441       g_printf ("%*s content nibble 2 : 0x%01x\n", spacing, "",
442           item->content_nibble_2);
443       g_printf ("%*s user_byte        : 0x%02x\n", spacing, "",
444           item->user_byte);
445     }
446     g_ptr_array_unref (contents);
447   }
448 }
449 
450 static void
dump_iso_639_language(GstMpegtsDescriptor * desc,guint spacing)451 dump_iso_639_language (GstMpegtsDescriptor * desc, guint spacing)
452 {
453   guint i;
454   GstMpegtsISO639LanguageDescriptor *res;
455 
456   if (gst_mpegts_descriptor_parse_iso_639_language (desc, &res)) {
457     for (i = 0; i < res->nb_language; i++) {
458       g_print
459           ("%*s ISO 639 Language Descriptor %s , audio_type:0x%x (%s)\n",
460           spacing, "", res->language[i], res->audio_type[i],
461           enum_name (GST_TYPE_MPEGTS_ISO639_AUDIO_TYPE, res->audio_type[i]));
462     }
463     gst_mpegts_iso_639_language_descriptor_free (res);
464   }
465 }
466 
467 static void
dump_dvb_extended_event(GstMpegtsDescriptor * desc,guint spacing)468 dump_dvb_extended_event (GstMpegtsDescriptor * desc, guint spacing)
469 {
470   GstMpegtsExtendedEventDescriptor *res;
471 
472   if (gst_mpegts_descriptor_parse_dvb_extended_event (desc, &res)) {
473     guint i;
474     g_printf ("%*s DVB Extended Event\n", spacing, "");
475     g_printf ("%*s   descriptor_number:%d, last_descriptor_number:%d\n",
476         spacing, "", res->descriptor_number, res->last_descriptor_number);
477     g_printf ("%*s   language_code:%s\n", spacing, "", res->language_code);
478     g_printf ("%*s   text : %s\n", spacing, "", res->text);
479     for (i = 0; i < res->items->len; i++) {
480       GstMpegtsExtendedEventItem *item = g_ptr_array_index (res->items, i);
481       g_printf ("%*s     #%d [description:item]  %s : %s\n",
482           spacing, "", i, item->item_description, item->item);
483     }
484     gst_mpegts_extended_event_descriptor_free (res);
485   }
486 }
487 
488 static void
dump_descriptors(GPtrArray * descriptors,guint spacing)489 dump_descriptors (GPtrArray * descriptors, guint spacing)
490 {
491   guint i;
492 
493   for (i = 0; i < descriptors->len; i++) {
494     GstMpegtsDescriptor *desc = g_ptr_array_index (descriptors, i);
495     g_printf ("%*s [descriptor 0x%02x (%s) length:%d]\n", spacing, "",
496         desc->tag, descriptor_name (desc->tag), desc->length);
497     if (DUMP_DESCRIPTORS)
498       dump_memory_content (desc, spacing + 2);
499     switch (desc->tag) {
500       case GST_MTS_DESC_REGISTRATION:
501       {
502         const guint8 *data = desc->data + 2;
503 #define SAFE_CHAR(a) (g_ascii_isprint(a) ? a : '.')
504         g_printf ("%*s   Registration : %c%c%c%c [%02x%02x%02x%02x]\n", spacing,
505             "", SAFE_CHAR (data[0]), SAFE_CHAR (data[1]), SAFE_CHAR (data[2]),
506             SAFE_CHAR (data[3]), data[0], data[1], data[2], data[3]);
507 
508         break;
509       }
510       case GST_MTS_DESC_CA:
511       {
512         guint16 ca_pid, ca_system_id;
513         const guint8 *private_data;
514         gsize private_data_size;
515         if (gst_mpegts_descriptor_parse_ca (desc, &ca_system_id, &ca_pid,
516                 &private_data, &private_data_size)) {
517           g_printf ("%*s   CA system id : 0x%04x\n", spacing, "", ca_system_id);
518           g_printf ("%*s   CA PID       : 0x%04x\n", spacing, "", ca_pid);
519           if (private_data_size) {
520             g_printf ("%*s   Private Data :\n", spacing, "");
521             dump_memory_bytes ((guint8 *) private_data, private_data_size,
522                 spacing + 2);
523           }
524         }
525         break;
526       }
527       case GST_MTS_DESC_DVB_NETWORK_NAME:
528       {
529         gchar *network_name;
530         if (gst_mpegts_descriptor_parse_dvb_network_name (desc, &network_name)) {
531           g_printf ("%*s   Network Name : %s\n", spacing, "", network_name);
532           g_free (network_name);
533         }
534         break;
535       }
536       case GST_MTS_DESC_DVB_SERVICE_LIST:
537       {
538         dump_dvb_service_list (desc, spacing + 2);
539         break;
540       }
541       case GST_MTS_DESC_DVB_CABLE_DELIVERY_SYSTEM:
542         dump_cable_delivery_descriptor (desc, spacing + 2);
543         break;
544       case GST_MTS_DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM:
545         dump_terrestrial_delivery (desc, spacing + 2);
546         break;
547       case GST_MTS_DESC_DVB_BOUQUET_NAME:
548       {
549         gchar *bouquet_name;
550         if (gst_mpegts_descriptor_parse_dvb_bouquet_name (desc, &bouquet_name)) {
551           g_printf ("%*s   Bouquet Name Descriptor, bouquet_name:%s\n", spacing,
552               "", bouquet_name);
553           g_free (bouquet_name);
554         }
555         break;
556       }
557       case GST_MTS_DESC_DTG_LOGICAL_CHANNEL:
558         dump_logical_channel_descriptor (desc, spacing + 2);
559         break;
560       case GST_MTS_DESC_DVB_SERVICE:
561       {
562         gchar *service_name, *provider_name;
563         GstMpegtsDVBServiceType service_type;
564         if (gst_mpegts_descriptor_parse_dvb_service (desc, &service_type,
565                 &service_name, &provider_name)) {
566           g_printf ("%*s   Service Descriptor, type:0x%02x (%s)\n", spacing, "",
567               service_type, enum_name (GST_TYPE_MPEGTS_DVB_SERVICE_TYPE,
568                   service_type));
569           g_printf ("%*s      service_name  : %s\n", spacing, "", service_name);
570           g_printf ("%*s      provider_name : %s\n", spacing, "",
571               provider_name);
572           g_free (service_name);
573           g_free (provider_name);
574 
575         }
576         break;
577       }
578       case GST_MTS_DESC_DVB_MULTILINGUAL_BOUQUET_NAME:
579       {
580         dump_multiligual_bouquet_name (desc, spacing + 2);
581         break;
582       }
583       case GST_MTS_DESC_DVB_MULTILINGUAL_NETWORK_NAME:
584       {
585         dump_multiligual_network_name (desc, spacing + 2);
586         break;
587       }
588       case GST_MTS_DESC_DVB_MULTILINGUAL_SERVICE_NAME:
589       {
590         dump_multiligual_service_name (desc, spacing + 2);
591         break;
592       }
593       case GST_MTS_DESC_DVB_MULTILINGUAL_COMPONENT:
594       {
595         dump_multiligual_component (desc, spacing + 2);
596         break;
597       }
598       case GST_MTS_DESC_DVB_PRIVATE_DATA_SPECIFIER:
599       {
600         guint32 specifier;
601         guint8 len = 0, *data = NULL;
602 
603         if (gst_mpegts_descriptor_parse_dvb_private_data_specifier (desc,
604                 &specifier, &data, &len)) {
605           g_printf ("%*s   private_data_specifier : 0x%08x\n", spacing, "",
606               specifier);
607           if (len > 0) {
608             dump_memory_bytes (data, len, spacing + 2);
609             g_free (data);
610           }
611         }
612         break;
613       }
614       case GST_MTS_DESC_DVB_FREQUENCY_LIST:
615       {
616         gboolean offset;
617         GArray *list;
618         if (gst_mpegts_descriptor_parse_dvb_frequency_list (desc, &offset,
619                 &list)) {
620           guint j;
621           for (j = 0; j < list->len; j++) {
622             guint32 freq = g_array_index (list, guint32, j);
623             g_printf ("%*s   Frequency : %u %s\n", spacing, "", freq,
624                 offset ? "kHz" : "Hz");
625           }
626           g_array_unref (list);
627         }
628         break;
629       }
630       case GST_MTS_DESC_DVB_LINKAGE:
631         dump_linkage (desc, spacing + 2);
632         break;
633       case GST_MTS_DESC_DVB_COMPONENT:
634         dump_component (desc, spacing + 2);
635         break;
636       case GST_MTS_DESC_DVB_STREAM_IDENTIFIER:
637       {
638         guint8 tag;
639         if (gst_mpegts_descriptor_parse_dvb_stream_identifier (desc, &tag)) {
640           g_printf ("%*s   Component Tag : 0x%02x\n", spacing, "", tag);
641         }
642         break;
643       }
644       case GST_MTS_DESC_DVB_CA_IDENTIFIER:
645       {
646         GArray *list;
647         guint j;
648         guint16 ca_id;
649         if (gst_mpegts_descriptor_parse_dvb_ca_identifier (desc, &list)) {
650           for (j = 0; j < list->len; j++) {
651             ca_id = g_array_index (list, guint16, j);
652             g_printf ("%*s   CA Identifier : 0x%04x\n", spacing, "", ca_id);
653           }
654           g_array_unref (list);
655         }
656         break;
657       }
658       case GST_MTS_DESC_DVB_CONTENT:
659         dump_content (desc, spacing + 2);
660         break;
661       case GST_MTS_DESC_DVB_PARENTAL_RATING:
662       {
663         GPtrArray *ratings;
664         guint j;
665 
666         if (gst_mpegts_descriptor_parse_dvb_parental_rating (desc, &ratings)) {
667           for (j = 0; j < ratings->len; j++) {
668             GstMpegtsDVBParentalRatingItem *item =
669                 g_ptr_array_index (ratings, j);
670             g_printf ("%*s   country_code : %s\n", spacing, "",
671                 item->country_code);
672             g_printf ("%*s   rating age   : %d\n", spacing, "", item->rating);
673           }
674           g_ptr_array_unref (ratings);
675         }
676         break;
677       }
678       case GST_MTS_DESC_DVB_DATA_BROADCAST:
679       {
680         GstMpegtsDataBroadcastDescriptor *res;
681 
682         if (gst_mpegts_descriptor_parse_dvb_data_broadcast (desc, &res)) {
683           g_printf ("%*s   data_broadcast_id : 0x%04x\n", spacing, "",
684               res->data_broadcast_id);
685           g_printf ("%*s   component_tag     : 0x%02x\n", spacing, "",
686               res->component_tag);
687           if (res->length > 0) {
688             g_printf ("%*s   selector_bytes:\n", spacing, "");
689             dump_memory_bytes (res->selector_bytes, res->length, spacing + 2);
690           }
691           g_printf ("%*s   text              : %s\n", spacing, "",
692               res->text ? res->text : "NULL");
693           gst_mpegts_dvb_data_broadcast_descriptor_free (res);
694         }
695         break;
696       }
697       case GST_MTS_DESC_ISO_639_LANGUAGE:
698         dump_iso_639_language (desc, spacing + 2);
699         break;
700       case GST_MTS_DESC_DVB_SHORT_EVENT:
701       {
702         gchar *language_code, *event_name, *text;
703         if (gst_mpegts_descriptor_parse_dvb_short_event (desc, &language_code,
704                 &event_name, &text)) {
705           g_printf ("%*s   Short Event, language_code:%s\n", spacing, "",
706               language_code);
707           g_printf ("%*s     event_name : %s\n", spacing, "", event_name);
708           g_printf ("%*s     text       : %s\n", spacing, "", text);
709           g_free (language_code);
710           g_free (event_name);
711           g_free (text);
712         }
713       }
714         break;
715       case GST_MTS_DESC_DVB_EXTENDED_EVENT:
716       {
717         dump_dvb_extended_event (desc, spacing + 2);
718         break;
719       }
720       case GST_MTS_DESC_DVB_SUBTITLING:
721       {
722         gchar *lang;
723         guint8 type;
724         guint16 composition;
725         guint16 ancillary;
726         guint j;
727 
728         for (j = 0;
729             gst_mpegts_descriptor_parse_dvb_subtitling_idx (desc, j, &lang,
730                 &type, &composition, &ancillary); j++) {
731           g_printf ("%*s   Subtitling, language_code:%s\n", spacing, "", lang);
732           g_printf ("%*s      type                : %u\n", spacing, "", type);
733           g_printf ("%*s      composition page id : %u\n", spacing, "",
734               composition);
735           g_printf ("%*s      ancillary page id   : %u\n", spacing, "",
736               ancillary);
737           g_free (lang);
738         }
739       }
740         break;
741       case GST_MTS_DESC_DVB_TELETEXT:
742       {
743         GstMpegtsDVBTeletextType type;
744         gchar *lang;
745         guint8 magazine, page_number;
746         guint j;
747 
748         for (j = 0;
749             gst_mpegts_descriptor_parse_dvb_teletext_idx (desc, j, &lang, &type,
750                 &magazine, &page_number); j++) {
751           g_printf ("%*s   Teletext, type:0x%02x (%s)\n", spacing, "", type,
752               enum_name (GST_TYPE_MPEGTS_DVB_TELETEXT_TYPE, type));
753           g_printf ("%*s      language    : %s\n", spacing, "", lang);
754           g_printf ("%*s      magazine    : %u\n", spacing, "", magazine);
755           g_printf ("%*s      page number : %u\n", spacing, "", page_number);
756           g_free (lang);
757         }
758       }
759         break;
760       default:
761         break;
762     }
763   }
764 }
765 
766 static void
dump_pat(GstMpegtsSection * section)767 dump_pat (GstMpegtsSection * section)
768 {
769   GPtrArray *pat = gst_mpegts_section_get_pat (section);
770   guint i, len;
771 
772   len = pat->len;
773   g_printf ("   %d program(s):\n", len);
774 
775   for (i = 0; i < len; i++) {
776     GstMpegtsPatProgram *patp = g_ptr_array_index (pat, i);
777 
778     g_print
779         ("     program_number:%6d (0x%04x), network_or_program_map_PID:0x%04x\n",
780         patp->program_number, patp->program_number,
781         patp->network_or_program_map_PID);
782   }
783 
784   g_ptr_array_unref (pat);
785 }
786 
787 static void
dump_pmt(GstMpegtsSection * section)788 dump_pmt (GstMpegtsSection * section)
789 {
790   const GstMpegtsPMT *pmt = gst_mpegts_section_get_pmt (section);
791   guint i, len;
792 
793   g_printf ("     program_number : 0x%04x\n", section->subtable_extension);
794   g_printf ("     pcr_pid        : 0x%04x\n", pmt->pcr_pid);
795   dump_descriptors (pmt->descriptors, 7);
796   len = pmt->streams->len;
797   g_printf ("     %d Streams:\n", len);
798   for (i = 0; i < len; i++) {
799     GstMpegtsPMTStream *stream = g_ptr_array_index (pmt->streams, i);
800     g_printf ("       pid:0x%04x , stream_type:0x%02x (%s)\n", stream->pid,
801         stream->stream_type,
802         enum_name (GST_TYPE_MPEGTS_STREAM_TYPE, stream->stream_type));
803     dump_descriptors (stream->descriptors, 9);
804   }
805 }
806 
807 static void
dump_eit(GstMpegtsSection * section)808 dump_eit (GstMpegtsSection * section)
809 {
810   const GstMpegtsEIT *eit = gst_mpegts_section_get_eit (section);
811   guint i, len;
812 
813   g_assert (eit);
814 
815   g_printf ("     service_id          : 0x%04x\n", section->subtable_extension);
816   g_printf ("     transport_stream_id : 0x%04x\n", eit->transport_stream_id);
817   g_printf ("     original_network_id : 0x%04x\n", eit->original_network_id);
818   g_printf ("     segment_last_section_number:0x%02x, last_table_id:0x%02x\n",
819       eit->segment_last_section_number, eit->last_table_id);
820   g_printf ("     actual_stream : %s, present_following : %s\n",
821       eit->actual_stream ? "TRUE" : "FALSE",
822       eit->present_following ? "TRUE" : "FALSE");
823 
824   len = eit->events->len;
825   g_printf ("     %d Event(s):\n", len);
826   for (i = 0; i < len; i++) {
827     gchar *tmp = (gchar *) "<NO TIME>";
828     GstMpegtsEITEvent *event = g_ptr_array_index (eit->events, i);
829 
830     if (event->start_time)
831       tmp = gst_date_time_to_iso8601_string (event->start_time);
832     g_printf ("       event_id:0x%04x, start_time:%s, duration:%"
833         GST_TIME_FORMAT "\n", event->event_id, tmp,
834         GST_TIME_ARGS (event->duration * GST_SECOND));
835     g_printf ("       running_status:0x%02x (%s), free_CA_mode:%d (%s)\n",
836         event->running_status, enum_name (GST_TYPE_MPEGTS_RUNNING_STATUS,
837             event->running_status), event->free_CA_mode,
838         event->free_CA_mode ? "MAYBE SCRAMBLED" : "NOT SCRAMBLED");
839     if (event->start_time)
840       g_free (tmp);
841     dump_descriptors (event->descriptors, 9);
842   }
843 }
844 
845 static void
dump_atsc_mult_string(GPtrArray * mstrings,guint spacing)846 dump_atsc_mult_string (GPtrArray * mstrings, guint spacing)
847 {
848   guint i;
849 
850   for (i = 0; i < mstrings->len; i++) {
851     GstMpegtsAtscMultString *mstring = g_ptr_array_index (mstrings, i);
852     gint j, n;
853 
854     n = mstring->segments->len;
855 
856     g_printf ("%*s [multstring entry (%d) iso_639 langcode: %s]\n", spacing, "",
857         i, mstring->iso_639_langcode);
858     g_printf ("%*s   segments:%d\n", spacing, "", n);
859     for (j = 0; j < n; j++) {
860       GstMpegtsAtscStringSegment *segment =
861           g_ptr_array_index (mstring->segments, j);
862 
863       g_printf ("%*s    Compression:0x%x\n", spacing, "",
864           segment->compression_type);
865       g_printf ("%*s    Mode:0x%x\n", spacing, "", segment->mode);
866       g_printf ("%*s    Len:%u\n", spacing, "", segment->compressed_data_size);
867       g_printf ("%*s    %s\n", spacing, "",
868           gst_mpegts_atsc_string_segment_get_string (segment));
869     }
870   }
871 }
872 
873 static void
dump_atsc_eit(GstMpegtsSection * section)874 dump_atsc_eit (GstMpegtsSection * section)
875 {
876   const GstMpegtsAtscEIT *eit = gst_mpegts_section_get_atsc_eit (section);
877   guint i, len;
878 
879   g_assert (eit);
880 
881   g_printf ("     event_id            : 0x%04x\n", eit->source_id);
882   g_printf ("     protocol_version    : %u\n", eit->protocol_version);
883 
884   len = eit->events->len;
885   g_printf ("     %d Event(s):\n", len);
886   for (i = 0; i < len; i++) {
887     GstMpegtsAtscEITEvent *event = g_ptr_array_index (eit->events, i);
888 
889     g_printf ("     %d)\n", i);
890     g_printf ("       event_id: 0x%04x\n", event->event_id);
891     g_printf ("       start_time: %u\n", event->start_time);
892     g_printf ("       etm_location: 0x%x\n", event->etm_location);
893     g_printf ("       length_in_seconds: %u\n", event->length_in_seconds);
894     g_printf ("       Title(s):\n");
895     dump_atsc_mult_string (event->titles, 9);
896     dump_descriptors (event->descriptors, 9);
897   }
898 }
899 
900 static void
dump_ett(GstMpegtsSection * section)901 dump_ett (GstMpegtsSection * section)
902 {
903   const GstMpegtsAtscETT *ett = gst_mpegts_section_get_atsc_ett (section);
904   guint len;
905 
906   g_assert (ett);
907 
908   g_printf ("     ett_table_id_ext    : 0x%04x\n", ett->ett_table_id_extension);
909   g_printf ("     protocol_version    : 0x%04x\n", ett->protocol_version);
910   g_printf ("     etm_id              : 0x%04x\n", ett->etm_id);
911 
912   len = ett->messages->len;
913   g_printf ("     %d Messages(s):\n", len);
914   dump_atsc_mult_string (ett->messages, 9);
915 }
916 
917 static void
dump_stt(GstMpegtsSection * section)918 dump_stt (GstMpegtsSection * section)
919 {
920   const GstMpegtsAtscSTT *stt = gst_mpegts_section_get_atsc_stt (section);
921   GstDateTime *dt;
922   gchar *dt_str = NULL;
923 
924   g_assert (stt);
925 
926   dt = gst_mpegts_atsc_stt_get_datetime_utc ((GstMpegtsAtscSTT *) stt);
927   if (dt)
928     dt_str = gst_date_time_to_iso8601_string (dt);
929 
930   g_printf ("     protocol_version    : 0x%04x\n", stt->protocol_version);
931   g_printf ("     system_time         : 0x%08x\n", stt->system_time);
932   g_printf ("     gps_utc_offset      : %d\n", stt->gps_utc_offset);
933   g_printf ("     daylight saving     : %d day:%d hour:%d\n", stt->ds_status,
934       stt->ds_dayofmonth, stt->ds_hour);
935   g_printf ("     utc datetime        : %s", dt_str);
936 
937   g_free (dt_str);
938   gst_date_time_unref (dt);
939 }
940 
941 static void
dump_nit(GstMpegtsSection * section)942 dump_nit (GstMpegtsSection * section)
943 {
944   const GstMpegtsNIT *nit = gst_mpegts_section_get_nit (section);
945   guint i, len;
946 
947   g_assert (nit);
948 
949   g_printf ("     network_id     : 0x%04x\n", section->subtable_extension);
950   g_printf ("     actual_network : %s\n",
951       nit->actual_network ? "TRUE" : "FALSE");
952   dump_descriptors (nit->descriptors, 7);
953   len = nit->streams->len;
954   g_printf ("     %d Streams:\n", len);
955   for (i = 0; i < len; i++) {
956     GstMpegtsNITStream *stream = g_ptr_array_index (nit->streams, i);
957     g_printf
958         ("       transport_stream_id:0x%04x , original_network_id:0x%02x\n",
959         stream->transport_stream_id, stream->original_network_id);
960     dump_descriptors (stream->descriptors, 9);
961   }
962 }
963 
964 static void
dump_bat(GstMpegtsSection * section)965 dump_bat (GstMpegtsSection * section)
966 {
967   const GstMpegtsBAT *bat = gst_mpegts_section_get_bat (section);
968   guint i, len;
969 
970   g_assert (bat);
971 
972   g_printf ("     bouquet_id     : 0x%04x\n", section->subtable_extension);
973   dump_descriptors (bat->descriptors, 7);
974   len = bat->streams->len;
975   g_printf ("     %d Streams:\n", len);
976   for (i = 0; i < len; i++) {
977     GstMpegtsBATStream *stream = g_ptr_array_index (bat->streams, i);
978     g_printf
979         ("       transport_stream_id:0x%04x , original_network_id:0x%02x\n",
980         stream->transport_stream_id, stream->original_network_id);
981     dump_descriptors (stream->descriptors, 9);
982   }
983 }
984 
985 static void
dump_sdt(GstMpegtsSection * section)986 dump_sdt (GstMpegtsSection * section)
987 {
988   const GstMpegtsSDT *sdt = gst_mpegts_section_get_sdt (section);
989   guint i, len;
990 
991   g_assert (sdt);
992 
993   g_printf ("     original_network_id : 0x%04x\n", sdt->original_network_id);
994   g_printf ("     actual_ts           : %s\n",
995       sdt->actual_ts ? "TRUE" : "FALSE");
996   len = sdt->services->len;
997   g_printf ("     %d Services:\n", len);
998   for (i = 0; i < len; i++) {
999     GstMpegtsSDTService *service = g_ptr_array_index (sdt->services, i);
1000     g_print
1001         ("       service_id:0x%04x, EIT_schedule_flag:%d, EIT_present_following_flag:%d\n",
1002         service->service_id, service->EIT_schedule_flag,
1003         service->EIT_present_following_flag);
1004     g_print
1005         ("       running_status:0x%02x (%s), free_CA_mode:%d (%s)\n",
1006         service->running_status,
1007         enum_name (GST_TYPE_MPEGTS_RUNNING_STATUS, service->running_status),
1008         service->free_CA_mode,
1009         service->free_CA_mode ? "MAYBE SCRAMBLED" : "NOT SCRAMBLED");
1010     dump_descriptors (service->descriptors, 9);
1011   }
1012 }
1013 
1014 static void
dump_tdt(GstMpegtsSection * section)1015 dump_tdt (GstMpegtsSection * section)
1016 {
1017   GstDateTime *date = gst_mpegts_section_get_tdt (section);
1018 
1019   if (date) {
1020     gchar *str = gst_date_time_to_iso8601_string (date);
1021     g_printf ("     utc_time : %s\n", str);
1022     g_free (str);
1023     gst_date_time_unref (date);
1024   } else {
1025     g_printf ("     No utc_time present\n");
1026   }
1027 }
1028 
1029 static void
dump_tot(GstMpegtsSection * section)1030 dump_tot (GstMpegtsSection * section)
1031 {
1032   const GstMpegtsTOT *tot = gst_mpegts_section_get_tot (section);
1033   gchar *str = gst_date_time_to_iso8601_string (tot->utc_time);
1034 
1035   g_printf ("     utc_time : %s\n", str);
1036   dump_descriptors (tot->descriptors, 7);
1037   g_free (str);
1038 }
1039 
1040 static void
dump_mgt(GstMpegtsSection * section)1041 dump_mgt (GstMpegtsSection * section)
1042 {
1043   const GstMpegtsAtscMGT *mgt = gst_mpegts_section_get_atsc_mgt (section);
1044   gint i;
1045 
1046   g_printf ("     protocol_version    : %u\n", mgt->protocol_version);
1047   g_printf ("     tables number       : %d\n", mgt->tables->len);
1048   for (i = 0; i < mgt->tables->len; i++) {
1049     GstMpegtsAtscMGTTable *table = g_ptr_array_index (mgt->tables, i);
1050     g_printf ("     table %d)\n", i);
1051     g_printf ("       table_type    : %u\n", table->table_type);
1052     g_printf ("       pid           : 0x%x\n", table->pid);
1053     g_printf ("       version_number: %u\n", table->version_number);
1054     g_printf ("       number_bytes  : %u\n", table->number_bytes);
1055     dump_descriptors (table->descriptors, 9);
1056   }
1057   dump_descriptors (mgt->descriptors, 7);
1058 }
1059 
1060 static void
dump_vct(GstMpegtsSection * section)1061 dump_vct (GstMpegtsSection * section)
1062 {
1063   const GstMpegtsAtscVCT *vct;
1064   gint i;
1065 
1066   if (GST_MPEGTS_SECTION_TYPE (section) == GST_MPEGTS_SECTION_ATSC_CVCT) {
1067     vct = gst_mpegts_section_get_atsc_cvct (section);
1068   } else {
1069     /* GST_MPEGTS_SECTION_ATSC_TVCT */
1070     vct = gst_mpegts_section_get_atsc_tvct (section);
1071   }
1072 
1073   g_assert (vct);
1074 
1075   g_printf ("     transport_stream_id : 0x%04x\n", vct->transport_stream_id);
1076   g_printf ("     protocol_version    : %u\n", vct->protocol_version);
1077   g_printf ("     %d Sources:\n", vct->sources->len);
1078   for (i = 0; i < vct->sources->len; i++) {
1079     GstMpegtsAtscVCTSource *source = g_ptr_array_index (vct->sources, i);
1080     g_print ("       short_name: %s\n", source->short_name);
1081     g_print ("       major_channel_number: %u, minor_channel_number: %u\n",
1082         source->major_channel_number, source->minor_channel_number);
1083     g_print ("       modulation_mode: %u\n", source->modulation_mode);
1084     g_print ("       carrier_frequency: %u\n", source->carrier_frequency);
1085     g_print ("       channel_tsid: %u\n", source->channel_TSID);
1086     g_print ("       program_number: %u\n", source->program_number);
1087     g_print ("       ETM_location: %u\n", source->ETM_location);
1088     g_print ("       access_controlled: %u\n", source->access_controlled);
1089     g_print ("       hidden: %u\n", source->hidden);
1090     if (section->table_id == GST_MPEGTS_SECTION_ATSC_CVCT) {
1091       g_print ("       path_select: %u\n", source->path_select);
1092       g_print ("       out_of_band: %u\n", source->out_of_band);
1093     }
1094     g_print ("       hide_guide: %u\n", source->hide_guide);
1095     g_print ("       service_type: %u\n", source->service_type);
1096     g_print ("       source_id: %u\n", source->source_id);
1097 
1098     dump_descriptors (source->descriptors, 9);
1099   }
1100   dump_descriptors (vct->descriptors, 7);
1101 }
1102 
1103 static void
dump_cat(GstMpegtsSection * section)1104 dump_cat (GstMpegtsSection * section)
1105 {
1106   GPtrArray *descriptors;
1107 
1108   descriptors = gst_mpegts_section_get_cat (section);
1109   g_assert (descriptors);
1110   dump_descriptors (descriptors, 7);
1111   g_ptr_array_unref (descriptors);
1112 }
1113 
1114 static void
dump_section(GstMpegtsSection * section)1115 dump_section (GstMpegtsSection * section)
1116 {
1117   switch (GST_MPEGTS_SECTION_TYPE (section)) {
1118     case GST_MPEGTS_SECTION_PAT:
1119       dump_pat (section);
1120       break;
1121     case GST_MPEGTS_SECTION_PMT:
1122       dump_pmt (section);
1123       break;
1124     case GST_MPEGTS_SECTION_CAT:
1125       dump_cat (section);
1126       break;
1127     case GST_MPEGTS_SECTION_TDT:
1128       dump_tdt (section);
1129       break;
1130     case GST_MPEGTS_SECTION_TOT:
1131       dump_tot (section);
1132       break;
1133     case GST_MPEGTS_SECTION_SDT:
1134       dump_sdt (section);
1135       break;
1136     case GST_MPEGTS_SECTION_NIT:
1137       dump_nit (section);
1138       break;
1139     case GST_MPEGTS_SECTION_BAT:
1140       dump_bat (section);
1141       break;
1142     case GST_MPEGTS_SECTION_EIT:
1143       dump_eit (section);
1144       break;
1145     case GST_MPEGTS_SECTION_ATSC_MGT:
1146       dump_mgt (section);
1147       break;
1148     case GST_MPEGTS_SECTION_ATSC_CVCT:
1149     case GST_MPEGTS_SECTION_ATSC_TVCT:
1150       dump_vct (section);
1151       break;
1152     case GST_MPEGTS_SECTION_ATSC_EIT:
1153       dump_atsc_eit (section);
1154       break;
1155     case GST_MPEGTS_SECTION_ATSC_ETT:
1156       dump_ett (section);
1157       break;
1158     case GST_MPEGTS_SECTION_ATSC_STT:
1159       dump_stt (section);
1160       break;
1161     default:
1162       g_printf ("     Unknown section type\n");
1163       break;
1164   }
1165 }
1166 
1167 static void
_on_bus_message(GstBus * bus,GstMessage * message,GMainLoop * mainloop)1168 _on_bus_message (GstBus * bus, GstMessage * message, GMainLoop * mainloop)
1169 {
1170   /* g_printf ("Got message %s\n", GST_MESSAGE_TYPE_NAME (message)); */
1171 
1172   switch (GST_MESSAGE_TYPE (message)) {
1173     case GST_MESSAGE_ERROR:
1174     case GST_MESSAGE_EOS:
1175       g_main_loop_quit (mainloop);
1176       break;
1177     case GST_MESSAGE_ELEMENT:
1178     {
1179       GstMpegtsSection *section;
1180       if ((section = gst_message_parse_mpegts_section (message))) {
1181         const gchar *table_name;
1182 
1183         table_name = table_id_name (section->table_id);
1184         g_print
1185             ("Got section: PID:0x%04x type:%s (table_id 0x%02x (%s)) at offset %"
1186             G_GUINT64_FORMAT "\n", section->pid,
1187             enum_name (GST_TYPE_MPEGTS_SECTION_TYPE, section->section_type),
1188             section->table_id, table_name, section->offset);
1189         if (!section->short_section) {
1190           g_print
1191               ("   subtable_extension:0x%04x, version_number:0x%02x\n",
1192               section->subtable_extension, section->version_number);
1193           g_print
1194               ("   section_number:0x%02x last_section_number:0x%02x crc:0x%08x\n",
1195               section->section_number, section->last_section_number,
1196               section->crc);
1197         }
1198         dump_section (section);
1199         g_printf ("\n\n");
1200         gst_mpegts_section_unref (section);
1201       }
1202       break;
1203     }
1204     default:
1205       break;
1206   }
1207 }
1208 
1209 int
main(int argc,gchar ** argv)1210 main (int argc, gchar ** argv)
1211 {
1212   GstElement *pipeline = NULL;
1213   GError *error = NULL;
1214   GstBus *bus;
1215   GMainLoop *mainloop;
1216 
1217   gst_init (&argc, &argv);
1218 
1219   gst_mpegts_initialize ();
1220 
1221   pipeline = gst_parse_launchv ((const gchar **) &argv[1], &error);
1222   if (error) {
1223     g_printf ("pipeline could not be constructed: %s\n", error->message);
1224     g_error_free (error);
1225     return 1;
1226   }
1227 
1228   /* Hack: ensure all enum type classes are loaded */
1229   g_type_class_ref (GST_TYPE_MPEGTS_SECTION_TYPE);
1230   g_type_class_ref (GST_TYPE_MPEGTS_SECTION_TABLE_ID);
1231   g_type_class_ref (GST_TYPE_MPEGTS_RUNNING_STATUS);
1232   g_type_class_ref (GST_TYPE_MPEGTS_DESCRIPTOR_TYPE);
1233   g_type_class_ref (GST_TYPE_MPEGTS_DVB_DESCRIPTOR_TYPE);
1234   g_type_class_ref (GST_TYPE_MPEGTS_ATSC_DESCRIPTOR_TYPE);
1235   g_type_class_ref (GST_TYPE_MPEGTS_ISDB_DESCRIPTOR_TYPE);
1236   g_type_class_ref (GST_TYPE_MPEGTS_MISC_DESCRIPTOR_TYPE);
1237   g_type_class_ref (GST_TYPE_MPEGTS_ISO639_AUDIO_TYPE);
1238   g_type_class_ref (GST_TYPE_MPEGTS_DVB_SERVICE_TYPE);
1239   g_type_class_ref (GST_TYPE_MPEGTS_DVB_TELETEXT_TYPE);
1240   g_type_class_ref (GST_TYPE_MPEGTS_STREAM_TYPE);
1241   g_type_class_ref (GST_TYPE_MPEGTS_SECTION_DVB_TABLE_ID);
1242   g_type_class_ref (GST_TYPE_MPEGTS_SECTION_ATSC_TABLE_ID);
1243   g_type_class_ref (GST_TYPE_MPEGTS_SECTION_SCTE_TABLE_ID);
1244   g_type_class_ref (GST_TYPE_MPEGTS_MODULATION_TYPE);
1245   g_type_class_ref (GST_TYPE_MPEGTS_DVB_CODE_RATE);
1246   g_type_class_ref (GST_TYPE_MPEGTS_CABLE_OUTER_FEC_SCHEME);
1247   g_type_class_ref (GST_TYPE_MPEGTS_TERRESTRIAL_TRANSMISSION_MODE);
1248   g_type_class_ref (GST_TYPE_MPEGTS_TERRESTRIAL_GUARD_INTERVAL);
1249   g_type_class_ref (GST_TYPE_MPEGTS_TERRESTRIAL_HIERARCHY);
1250   g_type_class_ref (GST_TYPE_MPEGTS_DVB_LINKAGE_TYPE);
1251   g_type_class_ref (GST_TYPE_MPEGTS_DVB_LINKAGE_HAND_OVER_TYPE);
1252   g_type_class_ref (GST_TYPE_MPEGTS_COMPONENT_STREAM_CONTENT);
1253   g_type_class_ref (GST_TYPE_MPEGTS_CONTENT_NIBBLE_HI);
1254 
1255   mainloop = g_main_loop_new (NULL, FALSE);
1256 
1257   /* Put a bus handler */
1258   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
1259   gst_bus_add_signal_watch (bus);
1260   g_signal_connect (bus, "message", (GCallback) _on_bus_message, mainloop);
1261 
1262   /* Start pipeline */
1263   gst_element_set_state (pipeline, GST_STATE_PLAYING);
1264   g_main_loop_run (mainloop);
1265 
1266   gst_element_set_state (pipeline, GST_STATE_NULL);
1267 
1268   gst_object_unref (pipeline);
1269   gst_object_unref (bus);
1270 
1271   return 0;
1272 }
1273