ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Linux-DVB/DVB.xs
Revision: 1.2
Committed: Wed Sep 8 19:47:30 2004 UTC (19 years, 8 months ago) by root
Branch: MAIN
Changes since 1.1: +126 -23 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4
5 #include <string.h>
6
7 #include <linux/dvb/frontend.h>
8 #include <linux/dvb/dmx.h>
9
10 #define CONST(name) { #name, name }
11
12 enum {
13 SCT_PAT = 0x00,
14 SCT_CAT = 0x01,
15 SCT_PMT = 0x02,
16 SCT_TSDT = 0x03,
17 SCT_NIT = 0x40,//TODO
18 SCT_NIT_OTHER = 0x41,
19 SCT_SDT = 0x42,
20 SCT_SDT_OTHER = 0x46,
21 SCT_BAT = 0x4a,//TODO
22 SCT_EIT_PRESENT = 0x4e,
23 SCT_EIT_PRESENT_OTHER = 0x4f,
24 SCT_EIT_SCHEDULE0 = 0x50,
25 SCT_EIT_SCHEDULE15 = 0x5f,
26 SCT_EIT_SCHEDULE_OTHER0 = 0x60,
27 SCT_EIT_SCHEDULE_OTHER15 = 0x6f,
28 SCT_TDT = 0x70,
29 SCT_RST = 0x71,
30 SCT_ST = 0x72,
31 SCT_TOT = 0x73,
32 SCT_RNT = 0x74,
33 SCT_CST = 0x75,
34 SCT_RCT = 0x76,
35 SCT_CIT = 0x77,
36 SCT_MPE = 0x78,
37 SCT_DIT = 0x7e,
38 SCT_SIT = 0x7f,
39 };
40
41 enum {
42 DT_service = 0x48,
43 DT_country_availability = 0x49,
44 DT_linkage = 0x4a,
45 DT_short_event = 0x4d,
46 DT_extended_event = 0x4e, //NYI
47 DT_component = 0x50,
48 DT_content = 0x54,
49 DT_private_data_specifier = 0x5f,
50 DT_short_smoothing_buffer = 0x61, //NYI
51 DT_scrambling_indicator = 0x65, //NYI
52 DT_PDC = 0x69,
53 };
54
55 static const struct consts {
56 const char *name;
57 const long value;
58 } consts [] = {
59 CONST (FE_QPSK),
60 CONST (FE_QAM),
61 CONST (FE_OFDM),
62
63 CONST (FE_IS_STUPID),
64 CONST (FE_CAN_INVERSION_AUTO),
65 CONST (FE_CAN_FEC_1_2),
66 CONST (FE_CAN_FEC_2_3),
67 CONST (FE_CAN_FEC_3_4),
68 CONST (FE_CAN_FEC_4_5),
69 CONST (FE_CAN_FEC_5_6),
70 CONST (FE_CAN_FEC_6_7),
71 CONST (FE_CAN_FEC_7_8),
72 CONST (FE_CAN_FEC_8_9),
73 CONST (FE_CAN_FEC_AUTO),
74 CONST (FE_CAN_QPSK),
75 CONST (FE_CAN_QAM_16),
76 CONST (FE_CAN_QAM_32),
77 CONST (FE_CAN_QAM_64),
78 CONST (FE_CAN_QAM_128),
79 CONST (FE_CAN_QAM_256),
80 CONST (FE_CAN_QAM_AUTO),
81 CONST (FE_CAN_TRANSMISSION_MODE_AUTO),
82 CONST (FE_CAN_BANDWIDTH_AUTO),
83 CONST (FE_CAN_GUARD_INTERVAL_AUTO),
84 CONST (FE_CAN_HIERARCHY_AUTO),
85 CONST (FE_NEEDS_BENDING),
86 CONST (FE_CAN_RECOVER),
87 CONST (FE_CAN_MUTE_TS),
88
89 CONST (FE_HAS_SIGNAL),
90 CONST (FE_HAS_CARRIER),
91 CONST (FE_HAS_VITERBI),
92 CONST (FE_HAS_SYNC),
93 CONST (FE_HAS_LOCK),
94 CONST (FE_TIMEDOUT),
95 CONST (FE_REINIT),
96
97 CONST (INVERSION_OFF),
98 CONST (INVERSION_ON),
99 CONST (INVERSION_AUTO),
100
101 CONST (FEC_NONE),
102 CONST (FEC_1_2),
103 CONST (FEC_2_3),
104 CONST (FEC_3_4),
105 CONST (FEC_4_5),
106 CONST (FEC_5_6),
107 CONST (FEC_6_7),
108 CONST (FEC_7_8),
109 CONST (FEC_8_9),
110 CONST (FEC_AUTO),
111
112 CONST (QPSK),
113 CONST (QAM_16),
114 CONST (QAM_32),
115 CONST (QAM_64),
116 CONST (QAM_128),
117 CONST (QAM_256),
118 CONST (QAM_AUTO),
119
120 CONST (TRANSMISSION_MODE_2K),
121 CONST (TRANSMISSION_MODE_8K),
122 CONST (TRANSMISSION_MODE_AUTO),
123
124 CONST (BANDWIDTH_8_MHZ),
125 CONST (BANDWIDTH_7_MHZ),
126 CONST (BANDWIDTH_6_MHZ),
127 CONST (BANDWIDTH_AUTO),
128
129 CONST (GUARD_INTERVAL_1_32),
130 CONST (GUARD_INTERVAL_1_16),
131 CONST (GUARD_INTERVAL_1_8),
132 CONST (GUARD_INTERVAL_1_4),
133 CONST (GUARD_INTERVAL_AUTO),
134
135 CONST (HIERARCHY_NONE),
136 CONST (HIERARCHY_1),
137 CONST (HIERARCHY_2),
138 CONST (HIERARCHY_4),
139 CONST (HIERARCHY_AUTO),
140
141 CONST (DMX_OUT_DECODER),
142 CONST (DMX_OUT_TAP),
143 CONST (DMX_OUT_TS_TAP),
144
145 CONST (DMX_IN_FRONTEND),
146 CONST (DMX_IN_DVR),
147
148 CONST (DMX_PES_AUDIO0),
149 CONST (DMX_PES_VIDEO0),
150 CONST (DMX_PES_TELETEXT0),
151 CONST (DMX_PES_SUBTITLE0),
152 CONST (DMX_PES_PCR0),
153
154 CONST (DMX_PES_AUDIO1),
155 CONST (DMX_PES_VIDEO1),
156 CONST (DMX_PES_TELETEXT1),
157 CONST (DMX_PES_SUBTITLE1),
158 CONST (DMX_PES_PCR1),
159
160 CONST (DMX_PES_AUDIO2),
161 CONST (DMX_PES_VIDEO2),
162 CONST (DMX_PES_TELETEXT2),
163 CONST (DMX_PES_SUBTITLE2),
164 CONST (DMX_PES_PCR2),
165
166 CONST (DMX_PES_AUDIO3),
167 CONST (DMX_PES_VIDEO3),
168 CONST (DMX_PES_TELETEXT3),
169 CONST (DMX_PES_SUBTITLE3),
170 CONST (DMX_PES_PCR3),
171
172 CONST (DMX_PES_OTHER),
173
174 CONST (DMX_PES_AUDIO),
175 CONST (DMX_PES_VIDEO),
176 CONST (DMX_PES_TELETEXT),
177 CONST (DMX_PES_SUBTITLE),
178 CONST (DMX_PES_PCR),
179
180 CONST (DMX_SCRAMBLING_EV),
181 CONST (DMX_FRONTEND_EV),
182
183 CONST (DMX_CHECK_CRC),
184 CONST (DMX_ONESHOT),
185 CONST (DMX_IMMEDIATE_START),
186 CONST (DMX_KERNEL_CLIENT),
187
188 CONST (DMX_SOURCE_FRONT0),
189 CONST (DMX_SOURCE_FRONT1),
190 CONST (DMX_SOURCE_FRONT2),
191 CONST (DMX_SOURCE_FRONT3),
192
193 CONST (DMX_SOURCE_DVR0),
194 CONST (DMX_SOURCE_DVR1),
195 CONST (DMX_SOURCE_DVR2),
196 CONST (DMX_SOURCE_DVR3),
197
198 CONST (DMX_SCRAMBLING_OFF),
199 CONST (DMX_SCRAMBLING_ON),
200
201 // constants defined by this file
202 CONST (SCT_PAT),
203 CONST (SCT_CAT),
204 CONST (SCT_PMT),
205 CONST (SCT_TSDT),
206 CONST (SCT_NIT),
207 CONST (SCT_NIT_OTHER),
208 CONST (SCT_SDT),
209 CONST (SCT_SDT_OTHER),
210 CONST (SCT_BAT),
211 CONST (SCT_EIT_PRESENT),
212 CONST (SCT_EIT_PRESENT_OTHER),
213 CONST (SCT_EIT_SCHEDULE0),
214 CONST (SCT_EIT_SCHEDULE15),
215 CONST (SCT_EIT_SCHEDULE_OTHER0),
216 CONST (SCT_EIT_SCHEDULE_OTHER15),
217 CONST (SCT_TDT),
218 CONST (SCT_RST),
219 CONST (SCT_ST),
220 CONST (SCT_TOT),
221 CONST (SCT_RNT),
222 CONST (SCT_CST),
223 CONST (SCT_RCT),
224 CONST (SCT_CIT),
225 CONST (SCT_MPE),
226 CONST (SCT_DIT),
227 CONST (SCT_SIT),
228
229 CONST (DT_service),
230 CONST (DT_country_availability),
231 CONST (DT_linkage),
232 CONST (DT_short_event),
233 CONST (DT_extended_event),
234 CONST (DT_component),
235 CONST (DT_content),
236 CONST (DT_private_data_specifier),
237 CONST (DT_short_smoothing_buffer),
238 CONST (DT_scrambling_indicator),
239 CONST (DT_PDC),
240 };
241
242 #define HVS_S(hv,struct,member) hv_store (hv, #member, sizeof (#member) - 1, newSVpv (struct.member, 0), 0)
243 #define HVS_I(hv,struct,member) hv_store (hv, #member, sizeof (#member) - 1, newSViv (struct.member), 0)
244 #define HVS(hv,name,sv) hv_store (hv, #name, sizeof (#name) - 1, (sv), 0)
245
246 static void
247 set_parameters (HV *hv, struct dvb_frontend_parameters *p, fe_type_t type)
248 {
249 HVS_I (hv, (*p), frequency);
250 HVS_I (hv, (*p), inversion);
251
252 switch (type)
253 {
254 case FE_QPSK:
255 HVS_I (hv, (*p).u.qpsk, symbol_rate);
256 HVS_I (hv, (*p).u.qpsk, fec_inner);
257 break;
258
259 case FE_QAM:
260 HVS_I (hv, (*p).u.qam, symbol_rate);
261 HVS_I (hv, (*p).u.qam, fec_inner);
262 HVS_I (hv, (*p).u.qam, modulation);
263 break;
264
265 case FE_OFDM:
266 HVS_I (hv, (*p).u.ofdm, bandwidth);
267 HVS_I (hv, (*p).u.ofdm, code_rate_HP);
268 HVS_I (hv, (*p).u.ofdm, code_rate_LP);
269 HVS_I (hv, (*p).u.ofdm, constellation);
270 HVS_I (hv, (*p).u.ofdm, transmission_mode);
271 break;
272 }
273 }
274
275 typedef unsigned char u8;
276
277 static SV *dec_sv;
278 static u8 *dec_data;
279 static long dec_ofs, dec_len8;
280 static U32 dec_field;
281 STRLEN dec_len;
282
283 #define decode_overflow (dec_ofs > dec_len8)
284
285 static void
286 decode_set (SV *data)
287 {
288 if (dec_sv)
289 SvREFCNT_dec (dec_sv);
290
291 dec_sv = newSVsv (data);
292 dec_data = SvPVbyte (dec_sv, dec_len);
293 dec_ofs = 0;
294 dec_len8 = dec_len << 3;
295 }
296
297 static U32
298 decode_field (int bits)
299 {
300 u8 *p = dec_data + (dec_ofs >> 3);
301 int frac = 8 - (dec_ofs & 7);
302 dec_ofs += bits;
303
304 if (decode_overflow)
305 return dec_field = 0;
306
307 U32 r = *p++;
308
309 r &= (1UL << frac) - 1;
310
311 if (bits < frac)
312 r >>= (frac - bits);
313 else
314 {
315 bits -= frac;
316
317 while (bits >= 8)
318 {
319 r = (r << 8) | *p++;
320 bits -= 8;
321 }
322
323 if (bits > 0)
324 r = (r << bits) | (*p >> (8 - bits));
325 }
326
327 return dec_field = r;
328 }
329
330 static SV *
331 text2sv (u8 *data, U32 len)
332 {
333 dSP;
334 SV *sv = newSVpvn (data, len);
335
336 PUSHMARK (SP);
337 XPUSHs (sv);
338 PUTBACK;
339 call_pv ("Linux::DVB::Decode::text", G_VOID);
340
341 return sv;
342 }
343
344 #define DEC_I(hv, bits, name) HVS (hv, name, newSViv (decode_field (bits)))
345 #define DEC_T(hv, bytes, name) HVS (hv, name, text2sv (dec_data + (dec_ofs >> 3), (bytes))), dec_ofs += (bytes) << 3
346 #define DEC_S(hv, bytes, name) HVS (hv, name, newSVpvn (dec_data + (dec_ofs >> 3), (bytes))), dec_ofs += (bytes) << 3
347
348 static AV *
349 decode_descriptors (long end)
350 {
351 AV *av = newAV ();
352
353 while (dec_ofs < end)
354 {
355 HV *hv = newHV ();
356 U8 type, len, len2;
357 AV *av2;
358 long end, end2;
359
360 av_push (av, newRV_noinc ((SV *)hv));
361
362 DEC_I (hv, 8, type);
363 type = dec_field;
364 len = decode_field (8);
365 end = dec_ofs + (len << 3);
366
367 if (end > dec_len8)
368 return av;
369
370 switch (type)
371 {
372 case DT_service:
373 DEC_I (hv, 8, service_type);
374 len2 = decode_field (8); DEC_T (hv, len2, service_provider_name);
375 len2 = decode_field (8); DEC_T (hv, len2, service_name);
376 break;
377
378 case DT_country_availability:
379 DEC_I (hv, 1, country_availability_flag);
380 decode_field (7);
381
382 DEC_S (hv, (end - dec_ofs) >> 3, private_data);
383 //while (dec_ofs + 24 <= end)
384 // av_push (av,
385 break;
386
387 case DT_linkage:
388 DEC_I (hv, 16, transport_stream_id);
389 DEC_I (hv, 16, original_network_id);
390 DEC_I (hv, 16, service_id);
391 DEC_I (hv, 8, linkage_type);
392
393 if (dec_field == 8)
394 {
395 U32 hot, org;
396
397 DEC_I (hv, 8, hand_over_type); hot = dec_field;
398 decode_field (3);
399 DEC_I (hv, 1, origin_type); org = dec_field;
400
401 if (hot > 0x00 && hot < 0x04)
402 DEC_I (hv, 16, network_id);
403
404 if (org == 0)
405 DEC_I (hv, 16, initial_service_id);
406 }
407
408 DEC_S (hv, (end - dec_ofs) >> 3, private_data);
409 break;
410
411 case DT_PDC:
412 decode_field (4);
413 DEC_I (hv, 20, programme_identification_label);
414 break;
415
416 case DT_component:
417 decode_field (4);
418 DEC_I (hv, 4, stream_content);
419 DEC_I (hv, 8, component_type);
420 DEC_I (hv, 8, component_tag);
421 DEC_S (hv, 3, ISO_639_language_code);
422 DEC_T (hv, (end - dec_ofs) >> 3, text);
423 break;
424
425 case DT_short_event:
426 DEC_S (hv, 3, ISO_639_language_code);
427 len2 = decode_field (8); DEC_T (hv, len2, event_name);
428 len2 = decode_field (8); DEC_T (hv, len2, text);
429 break;
430
431 case DT_extended_event:
432 DEC_I (hv, 4, descriptor_number);
433 DEC_I (hv, 4, last_descriptor_number);
434 DEC_S (hv, 3, ISO_639_language_code);
435
436 len2 = decode_field (8); end2 = dec_ofs + (len2 << 3);
437 av2 = newAV ();
438 HVS (hv, items, newRV_noinc ((SV *)av2));
439
440 while (dec_ofs < end2)
441 {
442 AV *av3 = newAV ();
443 len2 = decode_field (8); av_push (av3, text2sv (dec_data + (dec_ofs >> 3), len2)), dec_ofs += len << 3;
444 len2 = decode_field (8); av_push (av3, text2sv (dec_data + (dec_ofs >> 3), len2)), dec_ofs += len << 3;
445
446 av_push (av2, newRV_noinc ((SV *)av3));
447 }
448
449 len2 = decode_field (8); DEC_T (hv, len2, text);
450 break;
451
452 case DT_content:
453 DEC_S (hv, len, content);
454 break;
455
456 case DT_private_data_specifier:
457 DEC_I (hv, 32, private_data_specifier);
458 break;
459
460 default:
461 fprintf (stderr, "UNKXXX %x\n", type);//D
462 case 0:
463 case 0x80:
464 case 0x81:
465 case 0x82:
466 case 0x83:
467 case 0x84:
468 case 0x85:
469 case 0x8d:
470 case 0x8e:
471 case 0xb2:
472 DEC_S (hv, len, raw_data);
473 break;
474 }
475
476 dec_ofs = end; // re-sync, in case of problems
477 }
478
479 return av;
480 }
481
482 MODULE = Linux::DVB PACKAGE = Linux::DVB
483
484 PROTOTYPES: DISABLE
485
486 void
487 _consts ()
488 PPCODE:
489 const struct consts *c;
490 for (c = consts;
491 c < consts + sizeof (consts) / sizeof (consts[0]);
492 c++)
493 {
494 XPUSHs (sv_2mortal (newSVpv (c->name, 0)));
495 XPUSHs (sv_2mortal (newSViv (c->value)));
496 }
497
498 MODULE = Linux::DVB PACKAGE = Linux::DVB::Frontend
499
500 SV *
501 _frontend_info (int fd)
502 CODE:
503 struct dvb_frontend_info fi;
504 HV *hv;
505
506 if (ioctl (fd, FE_GET_INFO, &fi) < 0)
507 XSRETURN_UNDEF;
508
509 hv = newHV ();
510 HVS_S (hv, fi, name);
511 HVS_I (hv, fi, type);
512 HVS_I (hv, fi, type);
513 HVS_I (hv, fi, frequency_min);
514 HVS_I (hv, fi, frequency_max);
515 HVS_I (hv, fi, frequency_stepsize);
516 HVS_I (hv, fi, frequency_tolerance);
517 HVS_I (hv, fi, symbol_rate_min);
518 HVS_I (hv, fi, symbol_rate_max);
519 HVS_I (hv, fi, symbol_rate_tolerance);
520 HVS_I (hv, fi, notifier_delay);
521 HVS_I (hv, fi, caps);
522
523 RETVAL = (SV *)newRV_noinc ((SV *)hv);
524 OUTPUT:
525 RETVAL
526
527 long
528 _read_status (int fd)
529 CODE:
530 fe_status_t st;
531
532 if (ioctl (fd, FE_READ_STATUS, &st) < 0)
533 XSRETURN_UNDEF;
534
535 RETVAL = st;
536 OUTPUT:
537 RETVAL
538
539 U32
540 _read_ber (int fd)
541 CODE:
542 uint32_t ber;
543 if (ioctl (fd, FE_READ_BER, &ber) < 0)
544 XSRETURN_UNDEF;
545
546 RETVAL = ber;
547 OUTPUT:
548 RETVAL
549
550 U32
551 _read_snr (int fd)
552 CODE:
553 uint32_t ber;
554 if (ioctl (fd, FE_READ_SNR, &ber) < 0)
555 XSRETURN_UNDEF;
556
557 RETVAL = ber;
558 OUTPUT:
559 RETVAL
560
561
562 I16
563 _signal_strength (int fd)
564 CODE:
565 int16_t st;
566 if (ioctl (fd, FE_READ_SIGNAL_STRENGTH, &st) < 0)
567 XSRETURN_UNDEF;
568
569 RETVAL = st;
570 OUTPUT:
571 RETVAL
572
573
574 U32
575 _uncorrected_blocks (int fd)
576 CODE:
577 uint32_t ubl;
578 if (ioctl (fd, FE_READ_UNCORRECTED_BLOCKS, &ubl) < 0)
579 XSRETURN_UNDEF;
580
581 RETVAL = ubl;
582 OUTPUT:
583 RETVAL
584
585 SV *
586 _get (int fd, int type)
587 CODE:
588 struct dvb_frontend_parameters p;
589 HV *hv;
590
591 if (ioctl (fd, FE_GET_FRONTEND, &p) < 0)
592 XSRETURN_UNDEF;
593
594 hv = newHV ();
595 set_parameters (hv, &p, type);
596 RETVAL = (SV *)newRV_noinc ((SV *)hv);
597 OUTPUT:
598 RETVAL
599
600 SV *
601 _event (int fd, int type)
602 CODE:
603 struct dvb_frontend_event e;
604 HV *hv;
605
606 if (ioctl (fd, FE_GET_EVENT, &e) < 0)
607 XSRETURN_UNDEF;
608
609 hv = newHV ();
610 HVS_I (hv, e, status);
611 set_parameters (hv, &e.parameters, type);
612 RETVAL = (SV *)newRV_noinc ((SV *)hv);
613 OUTPUT:
614 RETVAL
615
616 MODULE = Linux::DVB PACKAGE = Linux::DVB::Demux
617
618 int
619 _start (int fd)
620 ALIAS:
621 _stop = 1
622 CODE:
623 if (ioctl (fd, ix ? DMX_STOP : DMX_START, 0) < 0)
624 XSRETURN_UNDEF;
625
626 RETVAL = 1;
627 OUTPUT:
628 RETVAL
629
630 int
631 _filter (int fd, U16 pid, SV *filter, SV *mask, U32 timeout = 0, U32 flags = DMX_CHECK_CRC)
632 CODE:
633 struct dmx_sct_filter_params p;
634 STRLEN l;
635 char *s;
636
637 memset (&p.filter, 0, sizeof (p.filter));
638
639 p.pid = pid;
640 s = SvPVbyte (filter, l); if (l > DMX_FILTER_SIZE) l = DMX_FILTER_SIZE; memcpy (p.filter.filter, s, l);
641 s = SvPVbyte (mask , l); if (l > DMX_FILTER_SIZE) l = DMX_FILTER_SIZE; memcpy (p.filter.mask , s, l);
642 p.timeout = timeout;
643 p.flags = flags;
644 if (ioctl (fd, DMX_SET_FILTER, &p) < 0)
645 XSRETURN_UNDEF;
646
647 RETVAL = 1;
648 OUTPUT:
649 RETVAL
650
651 int
652 _pes_filter (int fd, U16 pid, long input, long output, long type, U32 flags = 0)
653 CODE:
654 struct dmx_pes_filter_params p;
655
656 p.pid = pid;
657 p.input = input;
658 p.output = output;
659 p.pes_type = type;
660 p.flags = flags;
661 if (ioctl (fd, DMX_SET_PES_FILTER, &p) < 0)
662 XSRETURN_UNDEF;
663
664 RETVAL = 1;
665 OUTPUT:
666 RETVAL
667
668 int
669 _buffer (int fd, unsigned long size)
670 CODE:
671
672 if (ioctl (fd, DMX_SET_BUFFER_SIZE, size) < 0)
673 XSRETURN_UNDEF;
674
675 RETVAL = 1;
676 OUTPUT:
677 RETVAL
678
679 MODULE = Linux::DVB PACKAGE = Linux::DVB::Decode PREFIX = decode_
680
681 void
682 set (SV *data)
683 CODE:
684
685 int
686 len ()
687 CODE:
688 RETVAL = (dec_ofs + 7) >> 3;
689 OUTPUT:
690 RETVAL
691
692 U32
693 field (int bits)
694
695 SV *
696 si (SV *stream)
697 CODE:
698 HV *hv = newHV ();
699
700 U8 table_id;
701 U16 length;
702 long end;
703
704 decode_set (stream);
705
706 do {
707 DEC_I (hv, 8, table_id);
708 table_id = dec_field;
709 } while (table_id == 0xff);
710
711 DEC_I (hv, 1, section_syntax_indicator);
712 decode_field (1);
713 decode_field (2);
714
715 length = decode_field (12);
716 end = dec_ofs + (length << 3);
717
718 switch (table_id)
719 {
720 case SCT_EIT_PRESENT:
721 case SCT_EIT_PRESENT_OTHER:
722 case SCT_EIT_SCHEDULE0...SCT_EIT_SCHEDULE15: //GCC
723 case SCT_EIT_SCHEDULE_OTHER0...SCT_EIT_SCHEDULE_OTHER15: //GCC
724 DEC_I (hv, 16, service_id);
725 decode_field (2);
726 DEC_I (hv, 5, version_number);
727 DEC_I (hv, 1, current_next_indicator);
728 DEC_I (hv, 8, section_number);
729 DEC_I (hv, 8, last_section_number);
730 DEC_I (hv, 16, transport_stream_id);
731 DEC_I (hv, 16, original_network_id);
732 DEC_I (hv, 8, segment_last_section_number);
733 DEC_I (hv, 8, last_table_id);
734
735 AV *events = newAV ();
736 HVS (hv, events, newRV_noinc ((SV *)events));
737
738 while (end - dec_ofs > 32)
739 {
740 long dll;
741 AV *desc;
742 HV *ev = newHV ();
743 av_push (events, newRV_noinc ((SV *)ev));
744
745 DEC_I (ev, 16, event_id);
746 DEC_I (ev, 16, start_time_mjd);
747 DEC_I (ev, 24, start_time_hms);
748 DEC_I (ev, 24, duration);
749 DEC_I (ev, 3, running_status);
750 DEC_I (ev, 1, free_CA_mode);
751
752 dll = dec_ofs + (decode_field (12) << 3);
753
754 desc = decode_descriptors (dll);
755 HVS (ev, descriptors, newRV_noinc ((SV *)desc));
756 }
757
758 decode_field (32); // skip CRC
759
760 break;
761
762 case SCT_SDT:
763 case SCT_SDT_OTHER:
764 DEC_I (hv, 16, transport_stream_id);
765 decode_field (2);
766 DEC_I (hv, 5, version_number);
767 DEC_I (hv, 1, current_next_indicator);
768 DEC_I (hv, 8, section_number);
769 DEC_I (hv, 8, last_section_number);
770 DEC_I (hv, 16, original_network_id);
771 decode_field (8);
772
773 AV *services = newAV ();
774 HVS (hv, services, newRV_noinc ((SV *)services));
775
776 while (end - dec_ofs > 32)
777 {
778 HV *ev = newHV ();
779 U32 dll;
780 AV *desc;
781 av_push (services, newRV_noinc ((SV *)ev));
782
783 DEC_I (ev, 16, service_id);
784 decode_field (6);
785 DEC_I (ev, 1, EIT_schedule_flags);
786 DEC_I (ev, 1, EIT_present_following_flag);
787 DEC_I (ev, 3, running_status);
788 DEC_I (ev, 1, free_CA_mode);
789
790 dll = dec_ofs + (decode_field (12) << 3);
791
792 desc = decode_descriptors (dll);
793 HVS (ev, descriptors, newRV_noinc ((SV *)desc));
794 }
795
796 decode_field (32); // skip CRC
797 break;
798
799 default:
800 DEC_S (hv, length, raw_data);
801 break;
802 }
803
804 if (decode_overflow)
805 {
806 SvREFCNT_dec (hv);
807 XSRETURN_UNDEF;
808 }
809
810 sv_chop (stream, SvPVX (stream) + ((dec_ofs + 7) >> 3));
811
812 RETVAL = (SV *)newRV_noinc ((SV *)hv);
813 OUTPUT:
814 RETVAL
815