- add iSeekableService, implement it for serviceDvb
[enigma2.git] / lib / dvb / decoder.cpp
1 #include <config.h>
2 #include <lib/base/eerror.h>
3 #include <lib/dvb/decoder.h>
4 #if HAVE_DVB_API_VERSION < 3 
5 #define audioStatus audio_status
6 #define videoStatus video_status
7 #define pesType pes_type
8 #define playState play_state
9 #define audioStreamSource_t audio_stream_source_t
10 #define videoStreamSource_t video_stream_source_t
11 #define streamSource stream_source
12 #define dmxPesFilterParams dmx_pes_filter_params
13 #define DMX_PES_VIDEO DMX_PES_VIDEO0
14 #define DMX_PES_AUDIO DMX_PES_AUDIO0
15 #include <ost/dmx.h>
16 #include <ost/video.h>
17 #include <ost/audio.h>
18 #else
19 #include <linux/dvb/audio.h>
20 #include <linux/dvb/video.h>
21 #include <linux/dvb/dmx.h>
22 #endif
23
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <sys/ioctl.h>
27 #include <errno.h>
28
29 DEFINE_REF(eDVBAudio);
30
31 eDVBAudio::eDVBAudio(eDVBDemux *demux, int dev): m_demux(demux)
32 {
33         char filename[128];
34 #if HAVE_DVB_API_VERSION < 3
35         sprintf(filename, "/dev/dvb/card%d/audio%d", demux->adapter, dev);      
36 #else
37         sprintf(filename, "/dev/dvb/adapter%d/audio%d", demux->adapter, dev);
38 #endif
39         m_fd = ::open(filename, O_RDWR);
40         if (m_fd < 0)
41                 eWarning("%s: %m", filename);
42 #if HAVE_DVB_API_VERSION < 3
43         sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
44 #else
45         sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
46 #endif  
47         m_fd_demux = ::open(filename, O_RDWR);
48         if (m_fd_demux < 0)
49                 eWarning("%s: %m", filename);
50 }
51         
52 int eDVBAudio::startPid(int pid)
53 {       
54         eDebug("setting audio pid to %x", pid);
55         if ((m_fd < 0) || (m_fd_demux < 0))
56                 return -1;
57         dmx_pes_filter_params pes;
58         pes.pid      = pid;
59         pes.input    = DMX_IN_FRONTEND;
60         pes.output   = DMX_OUT_DECODER;
61         pes.pes_type = DMX_PES_AUDIO;  // DMX_PES_AUDIO0
62         pes.flags    = 0;
63         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
64         {
65                 eWarning("audio: DMX_SET_PES_FILTER: %m");
66                 return -errno;
67         }
68         if (::ioctl(m_fd_demux, DMX_START) < 0)
69         {
70                 eWarning("audio: DMX_START: %m");
71                 return -errno;
72         }
73         if (::ioctl(m_fd, AUDIO_PLAY) < 0)
74                 eWarning("audio: AUDIO_PLAY: %m");
75         return 0;
76 }
77         
78 void eDVBAudio::stop()
79 {
80         if (::ioctl(m_fd, AUDIO_STOP) < 0)
81                 eWarning("audio: AUDIO_STOP: %m");
82 #if HAVE_DVB_API_VERSION > 2
83         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
84                 eWarning("audio: DMX_STOP: %m");
85 #endif
86 }
87         
88 #if HAVE_DVB_API_VERSION < 3
89 void eDVBAudio::stopPid()
90 {
91         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
92                 eWarning("audio: DMX_STOP: %m");
93 }
94 #endif
95         
96 eDVBAudio::~eDVBAudio()
97 {
98         if (m_fd >= 0)
99                 ::close(m_fd);
100         if (m_fd_demux >= 0)
101                 ::close(m_fd_demux);
102 }
103
104 DEFINE_REF(eDVBVideo);
105
106 eDVBVideo::eDVBVideo(eDVBDemux *demux, int dev): m_demux(demux)
107 {
108         char filename[128];
109 #if HAVE_DVB_API_VERSION < 3
110         sprintf(filename, "/dev/dvb/card%d/video%d", demux->adapter, dev);
111 #else
112         sprintf(filename, "/dev/dvb/adapter%d/video%d", demux->adapter, dev);
113 #endif
114         m_fd = ::open(filename, O_RDWR);
115         if (m_fd < 0)
116                 eWarning("%s: %m", filename);
117 #if HAVE_DVB_API_VERSION < 3
118         sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
119 #else
120         sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
121 #endif
122         m_fd_demux = ::open(filename, O_RDWR);
123         if (m_fd_demux < 0)
124                 eWarning("%s: %m", filename);
125 }
126         
127 int eDVBVideo::startPid(int pid)
128 {       
129         eDebug("setting video pid to %x", pid);
130         if ((m_fd < 0) || (m_fd_demux < 0))
131                 return -1;
132         dmx_pes_filter_params pes;
133         
134         pes.pid      = pid;
135         pes.input    = DMX_IN_FRONTEND;
136         pes.output   = DMX_OUT_DECODER;
137         pes.pes_type = DMX_PES_VIDEO;
138         pes.flags    = 0;
139         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
140         {
141                 eWarning("video: DMX_SET_PES_FILTER: %m");
142                 return -errno;
143         }
144         if (::ioctl(m_fd_demux, DMX_START) < 0)
145         {
146                 eWarning("video: DMX_START: %m");
147                 return -errno;
148         }
149         if (::ioctl(m_fd, VIDEO_PLAY) < 0)
150                 eWarning("video: VIDEO_PLAY: %m");
151         else
152                 eDebug("video ok");
153         return 0;
154 }
155         
156 void eDVBVideo::stop()
157 {
158         if (::ioctl(m_fd, VIDEO_STOP) < 0)
159                 eWarning("video: VIDEO_STOP: %m");
160 #if HAVE_DVB_API_VERSION > 2
161         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
162                 eWarning("video: DMX_STOP: %m");
163 #endif
164 }
165
166 #if HAVE_DVB_API_VERSION < 3
167 void eDVBVideo::stopPid()
168 {
169         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
170                 eWarning("video: DMX_STOP: %m");
171 }
172 #endif
173
174 eDVBVideo::~eDVBVideo()
175 {
176         if (m_fd >= 0)
177                 ::close(m_fd);
178         if (m_fd_demux >= 0)
179                 ::close(m_fd_demux);
180 }
181
182 DEFINE_REF(eDVBPCR);
183
184 eDVBPCR::eDVBPCR(eDVBDemux *demux): m_demux(demux)
185 {
186         char filename[128];
187 #if HAVE_DVB_API_VERSION < 3
188         sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
189 #else
190         sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
191 #endif
192         m_fd_demux = ::open(filename, O_RDWR);
193         if (m_fd_demux < 0)
194                 eWarning("%s: %m", filename);
195 }
196
197 int eDVBPCR::startPid(int pid)
198 {
199         eDebug("setting pcr pid to %x", pid);
200         if (m_fd_demux < 0)
201                 return -1;
202         dmx_pes_filter_params pes;
203
204         pes.pid      = pid;
205         pes.input    = DMX_IN_FRONTEND;
206         pes.output   = DMX_OUT_DECODER;
207         pes.pes_type = DMX_PES_PCR;
208         pes.flags    = 0;
209         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
210         {
211                 eWarning("video: DMX_SET_PES_FILTER: %m");
212                 return -errno;
213         }
214         if (::ioctl(m_fd_demux, DMX_START) < 0)
215         {
216                 eWarning("video: DMX_START: %m");
217                 return -errno;
218         }
219         return 0;
220 }
221
222 void eDVBPCR::stop()
223 {
224         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
225                 eWarning("video: DMX_STOP: %m");
226 }
227
228 eDVBPCR::~eDVBPCR()
229 {
230         if (m_fd_demux >= 0)
231                 ::close(m_fd_demux);
232 }
233
234 DEFINE_REF(eTSMPEGDecoder);
235
236 int eTSMPEGDecoder::setState()
237 {
238         int res = 0;
239         eDebug("changed %x", m_changed);
240 #if HAVE_DVB_API_VERSION < 3
241         if (m_changed & changeAudio && m_audio)
242                 m_audio->stopPid();
243         if (m_changed & changeVideo && m_video)
244                 m_video->stopPid();
245         if (m_changed & changePCR && m_pcr)
246         {
247                 m_pcr->stop();
248                 m_pcr=0;
249         }
250         if (m_changed & changeAudio && m_audio)
251         {
252                 m_audio->stop();
253                 m_audio=0;
254         }
255         if (m_changed & changeVideo && m_video)
256         {
257                 m_video->stop();
258                 m_video=0;
259         }
260         if (m_changed & changePCR)
261         {
262                 m_pcr = new eDVBPCR(m_demux);
263                 if (m_pcr->startPid(m_pcrpid))
264                 {
265                         eWarning("video: startpid failed!");
266                         res = -1;
267                 }
268                 m_changed &= ~changePCR;
269         }
270         if (m_changed & changeVideo)
271         {
272                 m_video = new eDVBVideo(m_demux, 0);
273                 if (m_video->startPid(m_vpid))
274                 {
275                         eWarning("video: startpid failed!");
276                         res = -1;
277                 }
278                 m_changed &= ~changeVideo;
279         }
280         if (m_changed & changeAudio)
281         {
282                 m_audio = new eDVBAudio(m_demux, 0);
283                 if (m_audio->startPid(m_apid))
284                 {
285                         eWarning("audio: startpid failed!");
286                         res = -1;
287                 }
288                 m_changed &= ~changeAudio;
289         }
290 #else
291         if (m_changed & changePCR)
292         {
293                 if (m_pcr)
294                         m_pcr->stop();
295                 m_pcr = 0;
296                 if ((m_pcrpid >= 0) && (m_pcrpid < 0x1FFF))
297                 {
298                         m_pcr = new eDVBPCR(m_demux);
299                         if (m_pcr->startPid(m_pcrpid))
300                         {
301                                 eWarning("video: startpid failed!");
302                                 res = -1;
303                         }
304                 }
305                 m_changed &= ~changePCR;
306         }
307         if (m_changed & changeVideo)
308         {
309                 if (m_video)
310                         m_video->stop();
311                 m_video = 0;
312                 m_video = new eDVBVideo(m_demux, 0);
313                 if (m_video->startPid(m_vpid))
314                 {
315                         eWarning("video: startpid failed!");
316                         res = -1;
317                 }
318                 m_changed &= ~changeVideo;
319         }
320         if (m_changed & changeAudio)
321         {
322                 if (m_audio)
323                         m_audio->stop();
324                 m_audio = 0;
325                 m_audio = new eDVBAudio(m_demux, 0);
326                 if (m_audio->startPid(m_apid))
327                 {
328                         eWarning("audio: startpid failed!");
329                         res = -1;
330                 }
331                 m_changed &= ~changeAudio;
332         }
333 #endif
334         return res;
335 }
336
337 eTSMPEGDecoder::eTSMPEGDecoder(eDVBDemux *demux, int decoder): m_demux(demux), m_changed(0)
338 {
339 }
340
341 eTSMPEGDecoder::~eTSMPEGDecoder()
342 {
343         m_vpid = m_apid = m_pcrpid = pidNone;
344         m_changed = -1;
345         setState();
346 }
347
348 RESULT eTSMPEGDecoder::setVideoPID(int vpid)
349 {
350         if (m_vpid != vpid)
351         {
352                 m_changed |= changeVideo;
353                 m_vpid = vpid;
354         }
355         return 0;
356 }
357
358 RESULT eTSMPEGDecoder::setAudioPID(int apid, int type)
359 {
360         if ((m_apid != apid) || (m_atype != type))
361         {
362                 m_changed |= changeAudio;
363                 m_atype = type;
364                 m_apid = apid;
365         }
366         return 0;
367 }
368
369 RESULT eTSMPEGDecoder::setSyncPCR(int pcrpid)
370 {
371         if (m_pcrpid != pcrpid)
372         {
373                 m_changed |= changePCR;
374                 m_pcrpid = pcrpid;
375         }
376         return 0;
377 }
378
379 RESULT eTSMPEGDecoder::setSyncMaster(int who)
380 {
381         return -1;
382 }
383
384 RESULT eTSMPEGDecoder::start()
385 {
386         return setState();
387 }
388
389 RESULT eTSMPEGDecoder::freeze(int cont)
390 {
391         return -1;
392 }
393
394 RESULT eTSMPEGDecoder::unfreeze()
395 {
396         return -1;
397 }
398
399 RESULT eTSMPEGDecoder::setSinglePictureMode(int when)
400 {
401         return -1;
402 }
403
404 RESULT eTSMPEGDecoder::setPictureSkipMode(int what)
405 {
406         return -1;
407 }
408
409 RESULT eTSMPEGDecoder::setSlowMotion(int repeat)
410 {
411         return -1;
412 }
413
414 RESULT eTSMPEGDecoder::setZoom(int what)
415 {
416         return -1;
417 }