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