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