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

# User Rev Content
1 root 1.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 root 1.2 SCT_NIT = 0x40,//TODO
18 root 1.1 SCT_NIT_OTHER = 0x41,
19     SCT_SDT = 0x42,
20     SCT_SDT_OTHER = 0x46,
21 root 1.2 SCT_BAT = 0x4a,//TODO
22 root 1.1 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 root 1.2 DT_service = 0x48,
43     DT_country_availability = 0x49,
44     DT_linkage = 0x4a,
45 root 1.1 DT_short_event = 0x4d,
46 root 1.2 DT_extended_event = 0x4e, //NYI
47 root 1.1 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 root 1.2
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 root 1.1 };
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 root 1.2 #define HVS(hv,name,sv) hv_store (hv, #name, sizeof (#name) - 1, (sv), 0)
245 root 1.1
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 root 1.2 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 root 1.1
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 root 1.2 U8 type, len, len2;
357     AV *av2;
358     long end, end2;
359 root 1.1
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 root 1.2 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 root 1.1 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 root 1.2 DEC_T (hv, (end - dec_ofs) >> 3, text);
423 root 1.1 break;
424    
425     case DT_short_event:
426     DEC_S (hv, 3, ISO_639_language_code);
427 root 1.2 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 root 1.1 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 root 1.2
460 root 1.1 default:
461     fprintf (stderr, "UNKXXX %x\n", type);//D
462     case 0:
463     case 0x80:
464     case 0x81:
465     case 0x82:
466 root 1.2 case 0x83:
467 root 1.1 case 0x84:
468     case 0x85:
469 root 1.2 case 0x8d:
470     case 0x8e:
471     case 0xb2:
472 root 1.1 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 root 1.2 HVS (hv, events, newRV_noinc ((SV *)events));
737 root 1.1
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 root 1.2 HVS (ev, descriptors, newRV_noinc ((SV *)desc));
756 root 1.1 }
757    
758     decode_field (32); // skip CRC
759    
760     break;
761 root 1.2
762 root 1.1 case SCT_SDT:
763     case SCT_SDT_OTHER:
764 root 1.2 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 root 1.1
773 root 1.2 AV *services = newAV ();
774     HVS (hv, services, newRV_noinc ((SV *)services));
775 root 1.1
776     while (end - dec_ofs > 32)
777     {
778     HV *ev = newHV ();
779     U32 dll;
780 root 1.2 AV *desc;
781     av_push (services, newRV_noinc ((SV *)ev));
782 root 1.1
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 root 1.2 dll = dec_ofs + (decode_field (12) << 3);
791 root 1.1
792 root 1.2 desc = decode_descriptors (dll);
793     HVS (ev, descriptors, newRV_noinc ((SV *)desc));
794 root 1.1 }
795    
796     decode_field (32); // skip CRC
797     break;
798 root 1.2
799 root 1.1 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