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