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