add basic support for repeated timers (doesn't work yet)
[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 void eDVBAudio::flush()
97 {
98         if (::ioctl(m_fd, AUDIO_CLEAR_BUFFER) < 0)
99                 eDebug("audio: AUDIO_CLEAR_BUFFER: %m");
100 }
101
102 void eDVBAudio::freeze()
103 {
104         if (::ioctl(m_fd, AUDIO_PAUSE) < 0)
105                 eDebug("video: AUDIO_PAUSE: %m");
106 }
107         
108 void eDVBAudio::unfreeze()
109 {
110         if (::ioctl(m_fd, AUDIO_CONTINUE) < 0)
111                 eDebug("video: AUDIO_CONTINUE: %m");
112 }
113         
114 eDVBAudio::~eDVBAudio()
115 {
116         if (m_fd >= 0)
117                 ::close(m_fd);
118         if (m_fd_demux >= 0)
119                 ::close(m_fd_demux);
120 }
121
122 DEFINE_REF(eDVBVideo);
123
124 eDVBVideo::eDVBVideo(eDVBDemux *demux, int dev): m_demux(demux)
125 {
126         char filename[128];
127 #if HAVE_DVB_API_VERSION < 3
128         sprintf(filename, "/dev/dvb/card%d/video%d", demux->adapter, dev);
129 #else
130         sprintf(filename, "/dev/dvb/adapter%d/video%d", demux->adapter, dev);
131 #endif
132         m_fd = ::open(filename, O_RDWR);
133         if (m_fd < 0)
134                 eWarning("%s: %m", filename);
135 #if HAVE_DVB_API_VERSION < 3
136         sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
137 #else
138         sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
139 #endif
140         m_fd_demux = ::open(filename, O_RDWR);
141         if (m_fd_demux < 0)
142                 eWarning("%s: %m", filename);
143 }
144         
145 int eDVBVideo::startPid(int pid)
146 {       
147         eDebug("setting video pid to %x", pid);
148         if ((m_fd < 0) || (m_fd_demux < 0))
149                 return -1;
150         dmx_pes_filter_params pes;
151         
152         pes.pid      = pid;
153         pes.input    = DMX_IN_FRONTEND;
154         pes.output   = DMX_OUT_DECODER;
155         pes.pes_type = DMX_PES_VIDEO;
156         pes.flags    = 0;
157         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
158         {
159                 eWarning("video: DMX_SET_PES_FILTER: %m");
160                 return -errno;
161         }
162         if (::ioctl(m_fd_demux, DMX_START) < 0)
163         {
164                 eWarning("video: DMX_START: %m");
165                 return -errno;
166         }
167         if (::ioctl(m_fd, VIDEO_PLAY) < 0)
168                 eWarning("video: VIDEO_PLAY: %m");
169         else
170                 eDebug("video ok");
171         return 0;
172 }
173         
174 void eDVBVideo::stop()
175 {
176         if (::ioctl(m_fd, VIDEO_STOP) < 0)
177                 eWarning("video: VIDEO_STOP: %m");
178 #if HAVE_DVB_API_VERSION > 2
179         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
180                 eWarning("video: DMX_STOP: %m");
181 #endif
182 }
183
184 #if HAVE_DVB_API_VERSION < 3
185 void eDVBVideo::stopPid()
186 {
187         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
188                 eWarning("video: DMX_STOP: %m");
189 }
190 #endif
191
192 void eDVBVideo::flush()
193 {
194         if (::ioctl(m_fd, VIDEO_CLEAR_BUFFER) < 0)
195                 eDebug("video: VIDEO_CLEAR_BUFFER: %m");
196 }
197         
198 void eDVBVideo::freeze()
199 {
200         if (::ioctl(m_fd, VIDEO_FREEZE) < 0)
201                 eDebug("video: VIDEO_FREEZE: %m");
202 }
203         
204 void eDVBVideo::unfreeze()
205 {
206         if (::ioctl(m_fd, VIDEO_CONTINUE) < 0)
207                 eDebug("video: VIDEO_CONTINUE: %m");
208 }
209         
210 eDVBVideo::~eDVBVideo()
211 {
212         if (m_fd >= 0)
213                 ::close(m_fd);
214         if (m_fd_demux >= 0)
215                 ::close(m_fd_demux);
216 }
217
218 DEFINE_REF(eDVBPCR);
219
220 eDVBPCR::eDVBPCR(eDVBDemux *demux): m_demux(demux)
221 {
222         char filename[128];
223 #if HAVE_DVB_API_VERSION < 3
224         sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
225 #else
226         sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
227 #endif
228         m_fd_demux = ::open(filename, O_RDWR);
229         if (m_fd_demux < 0)
230                 eWarning("%s: %m", filename);
231 }
232
233 int eDVBPCR::startPid(int pid)
234 {
235         eDebug("setting pcr pid to %x", pid);
236         if (m_fd_demux < 0)
237                 return -1;
238         dmx_pes_filter_params pes;
239
240         pes.pid      = pid;
241         pes.input    = DMX_IN_FRONTEND;
242         pes.output   = DMX_OUT_DECODER;
243         pes.pes_type = DMX_PES_PCR;
244         pes.flags    = 0;
245         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
246         {
247                 eWarning("video: DMX_SET_PES_FILTER: %m");
248                 return -errno;
249         }
250         if (::ioctl(m_fd_demux, DMX_START) < 0)
251         {
252                 eWarning("video: DMX_START: %m");
253                 return -errno;
254         }
255         return 0;
256 }
257
258 void eDVBPCR::stop()
259 {
260         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
261                 eWarning("video: DMX_STOP: %m");
262 }
263
264 eDVBPCR::~eDVBPCR()
265 {
266         if (m_fd_demux >= 0)
267                 ::close(m_fd_demux);
268 }
269
270 DEFINE_REF(eTSMPEGDecoder);
271
272 int eTSMPEGDecoder::setState()
273 {
274         int res = 0;
275         eDebug("changed %x", m_changed);
276 #if HAVE_DVB_API_VERSION < 3
277         if (m_changed & changeAudio && m_audio)
278                 m_audio->stopPid();
279         if (m_changed & changeVideo && m_video)
280                 m_video->stopPid();
281         if (m_changed & changePCR && m_pcr)
282         {
283                 m_pcr->stop();
284                 m_pcr=0;
285         }
286         if (m_changed & changeAudio && m_audio)
287         {
288                 m_audio->stop();
289                 m_audio=0;
290         }
291         if (m_changed & changeVideo && m_video)
292         {
293                 m_video->stop();
294                 m_video=0;
295         }
296         if (m_changed & changePCR)
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                 m_changed &= ~changePCR;
305         }
306         if (m_changed & changeVideo)
307         {
308                 m_video = new eDVBVideo(m_demux, 0);
309                 if (m_video->startPid(m_vpid))
310                 {
311                         eWarning("video: startpid failed!");
312                         res = -1;
313                 }
314                 m_changed &= ~changeVideo;
315         }
316         if (m_changed & changeAudio)
317         {
318                 m_audio = new eDVBAudio(m_demux, 0);
319                 if (m_audio->startPid(m_apid))
320                 {
321                         eWarning("audio: startpid failed!");
322                         res = -1;
323                 }
324                 m_changed &= ~changeAudio;
325         }
326 #else
327         if (m_changed & changePCR)
328         {
329                 if (m_pcr)
330                         m_pcr->stop();
331                 m_pcr = 0;
332                 if ((m_pcrpid >= 0) && (m_pcrpid < 0x1FFF))
333                 {
334                         m_pcr = new eDVBPCR(m_demux);
335                         if (m_pcr->startPid(m_pcrpid))
336                         {
337                                 eWarning("video: startpid failed!");
338                                 res = -1;
339                         }
340                 }
341                 m_changed &= ~changePCR;
342         }
343         if (m_changed & changeVideo)
344         {
345                 if (m_video)
346                         m_video->stop();
347                 m_video = 0;
348                 if ((m_vpid >= 0) && (m_vpid < 0x1FFF))
349                 {
350                         m_video = new eDVBVideo(m_demux, 0);
351                         if (m_video->startPid(m_vpid))
352                         {
353                                 eWarning("video: startpid failed!");
354                                 res = -1;
355                         }
356                 }
357                 m_changed &= ~changeVideo;
358         }
359         if (m_changed & changeAudio)
360         {
361                 if (m_audio)
362                         m_audio->stop();
363                 m_audio = 0;
364                 if ((m_apid >= 0) && (m_apid < 0x1FFF))
365                 {
366                         m_audio = new eDVBAudio(m_demux, 0);
367                         if (m_audio->startPid(m_apid))
368                         {
369                                 eWarning("audio: startpid failed!");
370                                 res = -1;
371                         }
372                 }
373                 m_changed &= ~changeAudio;
374         }
375 #endif
376         return res;
377 }
378
379 eTSMPEGDecoder::eTSMPEGDecoder(eDVBDemux *demux, int decoder): m_demux(demux), m_changed(0)
380 {
381         demux->connectEvent(slot(*this, &eTSMPEGDecoder::demux_event), m_demux_event);
382 }
383
384 eTSMPEGDecoder::~eTSMPEGDecoder()
385 {
386         m_vpid = m_apid = m_pcrpid = pidNone;
387         m_changed = -1;
388         setState();
389 }
390
391 RESULT eTSMPEGDecoder::setVideoPID(int vpid)
392 {
393         if (m_vpid != vpid)
394         {
395                 m_changed |= changeVideo;
396                 m_vpid = vpid;
397         }
398         return 0;
399 }
400
401 RESULT eTSMPEGDecoder::setAudioPID(int apid, int type)
402 {
403         if ((m_apid != apid) || (m_atype != type))
404         {
405                 m_changed |= changeAudio;
406                 m_atype = type;
407                 m_apid = apid;
408         }
409         return 0;
410 }
411
412 RESULT eTSMPEGDecoder::setSyncPCR(int pcrpid)
413 {
414         if (m_pcrpid != pcrpid)
415         {
416                 m_changed |= changePCR;
417                 m_pcrpid = pcrpid;
418         }
419         return 0;
420 }
421
422 RESULT eTSMPEGDecoder::setSyncMaster(int who)
423 {
424         return -1;
425 }
426
427 RESULT eTSMPEGDecoder::start()
428 {
429         return setState();
430 }
431
432 RESULT eTSMPEGDecoder::freeze(int cont)
433 {
434         if (m_video)
435                 m_video->freeze();
436
437         if (m_audio)
438                 m_audio->freeze();
439         
440         return 0;
441 }
442
443 RESULT eTSMPEGDecoder::unfreeze()
444 {
445         if (m_video)
446                 m_video->unfreeze();
447
448         if (m_audio)
449                 m_audio->unfreeze();
450         
451         return 0;
452 }
453
454 RESULT eTSMPEGDecoder::setSinglePictureMode(int when)
455 {
456         return -1;
457 }
458
459 RESULT eTSMPEGDecoder::setPictureSkipMode(int what)
460 {
461         return -1;
462 }
463
464 RESULT eTSMPEGDecoder::setSlowMotion(int repeat)
465 {
466         return -1;
467 }
468
469 RESULT eTSMPEGDecoder::setZoom(int what)
470 {
471         return -1;
472 }
473
474 RESULT eTSMPEGDecoder::flush()
475 {
476         if (m_audio)
477                 m_audio->flush();
478         if (m_video)
479                 m_video->flush();
480         return 0;
481 }
482
483 void eTSMPEGDecoder::demux_event(int event)
484 {
485         switch (event)
486         {
487         case eDVBDemux::evtFlush:
488                 flush();
489                 break;
490         default:
491                 break;
492         }
493 }