decoder: switch off audio in trickmodes
[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, int type)
53 {       
54         if ((m_fd < 0) || (m_fd_demux < 0))
55                 return -1;
56         dmx_pes_filter_params pes;
57
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         
74         int bypass = 0;
75         
76         switch (type)
77         {
78         case aMPEG:
79                 bypass = 1;
80                 break;
81         case aAC3:
82                 bypass = 0;
83                 break;
84                 /*
85         case aDTS:
86                 bypass = 2;
87                 break;
88                 */
89         }
90         
91         if (::ioctl(m_fd, AUDIO_SET_BYPASS_MODE, bypass) < 0)
92                 eWarning("audio: AUDIO_SET_BYPASS_MODE: %m");
93         
94         if (::ioctl(m_fd, AUDIO_PLAY) < 0)
95                 eWarning("audio: AUDIO_PLAY: %m");
96         return 0;
97 }
98         
99 void eDVBAudio::stop()
100 {
101         if (::ioctl(m_fd, AUDIO_STOP) < 0)
102                 eWarning("audio: AUDIO_STOP: %m");
103 #if HAVE_DVB_API_VERSION > 2
104         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
105                 eWarning("audio: DMX_STOP: %m");
106 #endif
107 }
108         
109 #if HAVE_DVB_API_VERSION < 3
110 void eDVBAudio::stopPid()
111 {
112         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
113                 eWarning("audio: DMX_STOP: %m");
114 }
115 #endif
116
117 void eDVBAudio::flush()
118 {
119         if (::ioctl(m_fd, AUDIO_CLEAR_BUFFER) < 0)
120                 eDebug("audio: AUDIO_CLEAR_BUFFER: %m");
121 }
122
123 void eDVBAudio::freeze()
124 {
125         if (::ioctl(m_fd, AUDIO_PAUSE) < 0)
126                 eDebug("video: AUDIO_PAUSE: %m");
127 }
128
129 void eDVBAudio::unfreeze()
130 {
131         if (::ioctl(m_fd, AUDIO_CONTINUE) < 0)
132                 eDebug("video: AUDIO_CONTINUE: %m");
133 }
134         
135 eDVBAudio::~eDVBAudio()
136 {
137         if (m_fd >= 0)
138                 ::close(m_fd);
139         if (m_fd_demux >= 0)
140                 ::close(m_fd_demux);
141 }
142
143 DEFINE_REF(eDVBVideo);
144
145 eDVBVideo::eDVBVideo(eDVBDemux *demux, int dev): m_demux(demux)
146 {
147         char filename[128];
148 #if HAVE_DVB_API_VERSION < 3
149         sprintf(filename, "/dev/dvb/card%d/video%d", demux->adapter, dev);
150 #else
151         sprintf(filename, "/dev/dvb/adapter%d/video%d", demux->adapter, dev);
152 #endif
153         m_fd = ::open(filename, O_RDWR);
154         if (m_fd < 0)
155                 eWarning("%s: %m", filename);
156 #if HAVE_DVB_API_VERSION < 3
157         sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
158 #else
159         sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
160 #endif
161         m_fd_demux = ::open(filename, O_RDWR);
162         if (m_fd_demux < 0)
163                 eWarning("%s: %m", filename);
164 }
165         
166 int eDVBVideo::startPid(int pid)
167 {       
168         if ((m_fd < 0) || (m_fd_demux < 0))
169                 return -1;
170         dmx_pes_filter_params pes;
171
172         pes.pid      = pid;
173         pes.input    = DMX_IN_FRONTEND;
174         pes.output   = DMX_OUT_DECODER;
175         pes.pes_type = DMX_PES_VIDEO;
176         pes.flags    = 0;
177         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
178         {
179                 eWarning("video: DMX_SET_PES_FILTER: %m");
180                 return -errno;
181         }
182         if (::ioctl(m_fd_demux, DMX_START) < 0)
183         {
184                 eWarning("video: DMX_START: %m");
185                 return -errno;
186         }
187         if (::ioctl(m_fd, VIDEO_PLAY) < 0)
188                 eWarning("video: VIDEO_PLAY: %m");
189         return 0;
190 }
191         
192 void eDVBVideo::stop()
193 {
194 #if HAVE_DVB_API_VERSION > 2
195         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
196                 eWarning("video: DMX_STOP: %m");
197 #endif
198         eDebug("VIDEO_STOP");
199         if (::ioctl(m_fd, VIDEO_STOP, 1) < 0)
200                 eWarning("video: VIDEO_STOP: %m");
201 }
202
203 #if HAVE_DVB_API_VERSION < 3
204 void eDVBVideo::stopPid()
205 {
206         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
207                 eWarning("video: DMX_STOP: %m");
208 }
209 #endif
210
211 void eDVBVideo::flush()
212 {
213         if (::ioctl(m_fd, VIDEO_CLEAR_BUFFER) < 0)
214                 eDebug("video: VIDEO_CLEAR_BUFFER: %m");
215 }
216         
217 void eDVBVideo::freeze()
218 {
219         if (::ioctl(m_fd, VIDEO_FREEZE) < 0)
220                 eDebug("video: VIDEO_FREEZE: %m");
221 }
222         
223 void eDVBVideo::unfreeze()
224 {
225         if (::ioctl(m_fd, VIDEO_CONTINUE) < 0)
226                 eDebug("video: VIDEO_CONTINUE: %m");
227 }
228         
229 int eDVBVideo::setSlowMotion(int repeat)
230 {
231         m_is_slow_motion = repeat;
232         return ::ioctl(m_fd, VIDEO_SLOWMOTION, repeat);
233 }
234
235 int eDVBVideo::setFastForward(int skip)
236 {
237         m_is_fast_forward = skip;
238         return ::ioctl(m_fd, VIDEO_FAST_FORWARD, skip);
239 }
240         
241 eDVBVideo::~eDVBVideo()
242 {
243         if (m_is_slow_motion)
244                 setSlowMotion(0);
245         if (m_is_fast_forward)
246                 setFastForward(0);
247         if (m_fd >= 0)
248                 ::close(m_fd);
249         if (m_fd_demux >= 0)
250                 ::close(m_fd_demux);
251 }
252
253 DEFINE_REF(eDVBPCR);
254
255 eDVBPCR::eDVBPCR(eDVBDemux *demux): m_demux(demux)
256 {
257         char filename[128];
258 #if HAVE_DVB_API_VERSION < 3
259         sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
260 #else
261         sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
262 #endif
263         m_fd_demux = ::open(filename, O_RDWR);
264         if (m_fd_demux < 0)
265                 eWarning("%s: %m", filename);
266 }
267
268 int eDVBPCR::startPid(int pid)
269 {
270         if (m_fd_demux < 0)
271                 return -1;
272         dmx_pes_filter_params pes;
273
274         pes.pid      = pid;
275         pes.input    = DMX_IN_FRONTEND;
276         pes.output   = DMX_OUT_DECODER;
277         pes.pes_type = DMX_PES_PCR;
278         pes.flags    = 0;
279         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
280         {
281                 eWarning("video: DMX_SET_PES_FILTER: %m");
282                 return -errno;
283         }
284         if (::ioctl(m_fd_demux, DMX_START) < 0)
285         {
286                 eWarning("video: DMX_START: %m");
287                 return -errno;
288         }
289         return 0;
290 }
291
292 void eDVBPCR::stop()
293 {
294         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
295                 eWarning("video: DMX_STOP: %m");
296 }
297
298 eDVBPCR::~eDVBPCR()
299 {
300         if (m_fd_demux >= 0)
301                 ::close(m_fd_demux);
302 }
303
304 DEFINE_REF(eTSMPEGDecoder);
305
306 int eTSMPEGDecoder::setState()
307 {
308         int res = 0;
309         
310         int noaudio = m_is_sm || m_is_ff || m_is_trickmode;
311         
312         if ((noaudio && m_audio) || (!m_audio && !noaudio))
313                 m_changed |= changeAudio;
314         
315 #if HAVE_DVB_API_VERSION < 3
316         if (m_changed & changeAudio && m_audio)
317                 m_audio->stopPid();
318         if (m_changed & changeVideo && m_video)
319                 m_video->stopPid();
320         if (m_changed & changePCR && m_pcr)
321         {
322                 m_pcr->stop();
323                 m_pcr=0;
324         }
325         if (m_changed & changeAudio && m_audio)
326         {
327                 m_audio->stop();
328                 m_audio=0;
329         }
330         if (m_changed & changeVideo && m_video)
331         {
332                 m_video->stop();
333                 m_video=0;
334         }
335         if (m_changed & changePCR)
336         {
337                 m_pcr = new eDVBPCR(m_demux);
338                 if (m_pcr->startPid(m_pcrpid))
339                 {
340                         eWarning("pcr: startpid failed!");
341                         res = -1;
342                 }
343                 m_changed &= ~changePCR;
344         }
345         if (m_changed & changeVideo)
346         {
347                 m_video = new eDVBVideo(m_demux, 0);
348                 if (m_video->startPid(m_vpid))
349                 {
350                         eWarning("video: startpid failed!");
351                         res = -1;
352                 }
353                 m_changed &= ~changeVideo;
354         }
355         if (m_changed & changeAudio)
356         {
357                 m_audio = new eDVBAudio(m_demux, 0);
358                 if (m_audio->startPid(m_apid, m_atype))
359                 {
360                         eWarning("audio: startpid failed!");
361                         res = -1;
362                 }
363                 m_changed &= ~changeAudio;
364         }
365 #else
366         if (m_changed & changeVideo)
367         {
368                 eDebug("VIDEO CHANGED (to %04x)", m_vpid);
369                 if (m_video)
370                 {       
371                         eDebug("STOP");
372                         m_video->stop();
373                 }
374                 m_video = 0;
375                 if ((m_vpid >= 0) && (m_vpid < 0x1FFF))
376                 {
377                         eDebug("new video");
378                         m_video = new eDVBVideo(m_demux, 0);
379                         if (m_video->startPid(m_vpid))
380                         {
381                                 eWarning("video: startpid failed!");
382                                 res = -1;
383                         }
384                 }
385                 m_changed &= ~changeVideo;
386         }
387         if (m_changed & changePCR)
388         {
389                 if (m_pcr)
390                         m_pcr->stop();
391                 m_pcr = 0;
392                 if ((m_pcrpid >= 0) && (m_pcrpid < 0x1FFF))
393                 {
394                         m_pcr = new eDVBPCR(m_demux);
395                         if (m_pcr->startPid(m_pcrpid))
396                         {
397                                 eWarning("pcr: startpid failed!");
398                                 res = -1;
399                         }
400                 }
401                 m_changed &= ~changePCR;
402         }
403         if (m_changed & changeAudio)
404         {
405                 if (m_audio)
406                         m_audio->stop();
407                 m_audio = 0;
408                 if ((m_apid >= 0) && (m_apid < 0x1FFF) && !noaudio)
409                 {
410                         m_audio = new eDVBAudio(m_demux, 0);
411                         if (m_audio->startPid(m_apid, m_atype))
412                         {
413                                 eWarning("audio: startpid failed!");
414                                 res = -1;
415                         }
416                 }
417                 m_changed &= ~changeAudio;
418         }
419 #endif
420         return res;
421 }
422
423 eTSMPEGDecoder::eTSMPEGDecoder(eDVBDemux *demux, int decoder): m_demux(demux), m_changed(0)
424 {
425         demux->connectEvent(slot(*this, &eTSMPEGDecoder::demux_event), m_demux_event);
426         m_is_ff = m_is_sm = m_is_trickmode = 0;
427 }
428
429 eTSMPEGDecoder::~eTSMPEGDecoder()
430 {
431         m_vpid = m_apid = m_pcrpid = pidNone;
432         m_changed = -1;
433         setState();
434 }
435
436 RESULT eTSMPEGDecoder::setVideoPID(int vpid)
437 {
438         if (m_vpid != vpid)
439         {
440                 m_changed |= changeVideo;
441                 m_vpid = vpid;
442         }
443         return 0;
444 }
445
446 RESULT eTSMPEGDecoder::setAudioPID(int apid, int type)
447 {
448         if ((m_apid != apid) || (m_atype != type))
449         {
450                 m_changed |= changeAudio;
451                 m_atype = type;
452                 m_apid = apid;
453         }
454         return 0;
455 }
456
457 RESULT eTSMPEGDecoder::setSyncPCR(int pcrpid)
458 {
459         if (m_pcrpid != pcrpid)
460         {
461                 m_changed |= changePCR;
462                 m_pcrpid = pcrpid;
463         }
464         return 0;
465 }
466
467 RESULT eTSMPEGDecoder::setSyncMaster(int who)
468 {
469         return -1;
470 }
471
472 RESULT eTSMPEGDecoder::start()
473 {
474         return setState();
475 }
476
477 RESULT eTSMPEGDecoder::freeze(int cont)
478 {
479         if (m_video)
480                 m_video->freeze();
481
482         if (m_audio)
483                 m_audio->freeze();
484         
485         return 0;
486 }
487
488 RESULT eTSMPEGDecoder::unfreeze()
489 {
490         if (m_video)
491                 m_video->unfreeze();
492
493         if (m_audio)
494                 m_audio->unfreeze();
495         
496         return 0;
497 }
498
499 RESULT eTSMPEGDecoder::setSinglePictureMode(int when)
500 {
501         return -1;
502 }
503
504 RESULT eTSMPEGDecoder::setPictureSkipMode(int what)
505 {
506         return -1;
507 }
508
509 RESULT eTSMPEGDecoder::setFastForward(int frames_to_skip)
510 {
511         m_is_ff = frames_to_skip != 0;
512         
513         setState();
514         
515         if (m_video)
516                 return m_video->setFastForward(frames_to_skip);
517         else
518                 return -1;
519 }
520
521 RESULT eTSMPEGDecoder::setSlowMotion(int repeat)
522 {
523         m_is_sm = repeat != 0;
524         
525         setState();
526         
527         if (m_video)
528                 return m_video->setSlowMotion(repeat);
529         else
530                 return -1;
531 }
532
533 RESULT eTSMPEGDecoder::setZoom(int what)
534 {
535         return -1;
536 }
537
538 RESULT eTSMPEGDecoder::flush()
539 {
540         if (m_audio)
541                 m_audio->flush();
542         if (m_video)
543                 m_video->flush();
544         return 0;
545 }
546
547 void eTSMPEGDecoder::demux_event(int event)
548 {
549         switch (event)
550         {
551         case eDVBDemux::evtFlush:
552                 flush();
553                 break;
554         default:
555                 break;
556         }
557 }
558
559 RESULT eTSMPEGDecoder::setTrickmode(int what)
560 {
561         m_is_trickmode = what;
562         setState();
563         return 0;
564 }