import of enigma2
[enigma2.git] / lib / dvb / demux.cpp
1 #include <stdio.h>
2 #include <fcntl.h>
3 #include <sys/ioctl.h>
4 #include <errno.h>
5 #include <unistd.h>
6
7 #include <linux/dvb/dmx.h>
8 #include "crc32.h"
9
10 #include <lib/base/eerror.h>
11 #include <lib/dvb/idvb.h>
12 #include <lib/dvb/demux.h>
13 #include <lib/dvb/esection.h>
14 #include <lib/dvb/decoder.h>
15
16 eDVBDemux::eDVBDemux(int adapter, int demux): adapter(adapter), demux(demux), ref(0)
17 {
18 }
19
20 eDVBDemux::~eDVBDemux()
21 {
22 }
23
24 DEFINE_REF(eDVBDemux)
25
26 RESULT eDVBDemux::createSectionReader(eMainloop *context, ePtr<iDVBSectionReader> &reader)
27 {
28         RESULT res;
29         reader = new eDVBSectionReader(this, context, res);
30         if (res)
31                 reader = 0;
32         return res;
33 }
34
35 RESULT eDVBDemux::getMPEGDecoder(ePtr<iTSMPEGDecoder> &decoder)
36 {
37         decoder = new eTSMPEGDecoder(this, 0);
38         return 0;
39 }
40
41 void eDVBSectionReader::data(int)
42 {
43         __u8 data[4096]; // max. section size
44         int r;
45         r = ::read(fd, data, 4096);
46         if(r < 0)
47         {
48                 eWarning("ERROR reading section - %m\n");
49                 return;
50         }
51         if (checkcrc)
52         {
53                         // this check should never happen unless the driver is crappy!
54                 unsigned int c;
55                 if ((c = crc32((unsigned)-1, data, r)))
56                         eFatal("crc32 failed! is %x\n", c);
57         }
58         read(data);
59 }
60
61 eDVBSectionReader::eDVBSectionReader(eDVBDemux *demux, eMainloop *context, RESULT &res): ref(0), demux(demux)
62 {
63         char filename[128];
64         sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
65         fd = ::open(filename, O_RDWR);
66         
67         if (fd >= 0)
68         {
69                 notifier=new eSocketNotifier(context, fd, eSocketNotifier::Read);
70                 CONNECT(notifier->activated, eDVBSectionReader::data);
71                 res = 0;
72         } else
73         {
74                 perror(filename);
75                 res = errno;
76         }
77 }
78
79 DEFINE_REF(eDVBSectionReader)
80
81 eDVBSectionReader::~eDVBSectionReader()
82 {
83         if (notifier)
84                 delete notifier;
85         if (fd >= 0)
86                 ::close(fd);
87 }
88
89 RESULT eDVBSectionReader::start(const eDVBSectionFilterMask &mask)
90 {
91         RESULT res;
92         if (fd < 0)
93                 return -ENODEV;
94
95         dmx_sct_filter_params sct;
96         
97         sct.pid     = mask.pid;
98         sct.timeout = 0;
99         sct.flags   = DMX_IMMEDIATE_START;
100         if (mask.flags & eDVBSectionFilterMask::rfCRC)
101         {
102                 sct.flags |= DMX_CHECK_CRC;
103                 checkcrc = 1;
104         } else
105                 checkcrc = 0;
106         
107         memcpy(sct.filter.filter, mask.data, DMX_FILTER_SIZE);
108         memcpy(sct.filter.mask, mask.mask, DMX_FILTER_SIZE);
109         memcpy(sct.filter.mode, mask.mode, DMX_FILTER_SIZE);
110         
111         res = ::ioctl(fd, DMX_SET_FILTER, &sct);
112         if (!res)
113                 active = 1;
114         return res;
115 }
116
117 RESULT eDVBSectionReader::stop()
118 {
119         if (!active)
120                 return -1;
121         
122         ::ioctl(fd, DMX_STOP);
123         
124         return 0;
125 }
126
127 RESULT eDVBSectionReader::connectRead(const Slot1<void,const __u8*> &r, ePtr<eConnection> &conn)
128 {
129         conn = new eConnection(read.connect(r));
130         return 0;
131 }