8e21dcad49887926bd41b961cddb5b1881f43b4d
[enigma2.git] / lib / dvb / decoder.cpp
1 #include <lib/base/eerror.h>
2 #include <lib/dvb/decoder.h>
3 #if HAVE_DVB_API_VERSION < 3 
4 #define audioStatus audio_status
5 #define videoStatus video_status
6 #define pesType pes_type
7 #define playState play_state
8 #define audioStreamSource_t audio_stream_source_t
9 #define videoStreamSource_t video_stream_source_t
10 #define streamSource stream_source
11 #define dmxPesFilterParams dmx_pes_filter_params
12 #define DMX_PES_VIDEO DMX_PES_VIDEO0
13 #define DMX_PES_AUDIO DMX_PES_AUDIO0
14 #include <ost/dmx.h>
15 #include <ost/video.h>
16 #include <ost/audio.h>
17 #else
18 #include <linux/dvb/audio.h>
19 #include <linux/dvb/video.h>
20 #include <linux/dvb/dmx.h>
21 #endif
22
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <sys/ioctl.h>
26 #include <errno.h>
27
28 DEFINE_REF(eDVBAudio);
29
30 eDVBAudio::eDVBAudio(eDVBDemux *demux, int dev): m_demux(demux)
31 {
32         char filename[128];
33 #if HAVE_DVB_API_VERSION < 3
34         sprintf(filename, "/dev/dvb/card%d/audio%d", demux->adapter, dev);      
35 #else
36         sprintf(filename, "/dev/dvb/adapter%d/audio%d", demux->adapter, dev);
37 #endif
38         m_fd = ::open(filename, O_RDWR);
39         if (m_fd < 0)
40                 eWarning("%s: %m", filename);
41 #if HAVE_DVB_API_VERSION < 3
42         sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
43 #else
44         sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
45 #endif  
46         m_fd_demux = ::open(filename, O_RDWR);
47         if (m_fd_demux < 0)
48                 eWarning("%s: %m", filename);
49 }
50         
51 int eDVBAudio::startPid(int pid, int type)
52 {       
53         if ((m_fd < 0) || (m_fd_demux < 0))
54                 return -1;
55         dmx_pes_filter_params pes;
56
57         pes.pid      = pid;
58         pes.input    = DMX_IN_FRONTEND;
59         pes.output   = DMX_OUT_DECODER;
60         pes.pes_type = DMX_PES_AUDIO;  // DMX_PES_AUDIO0
61         pes.flags    = 0;
62         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
63         {
64                 eWarning("audio: DMX_SET_PES_FILTER: %m");
65                 return -errno;
66         }
67         if (::ioctl(m_fd_demux, DMX_START) < 0)
68         {
69                 eWarning("audio: DMX_START: %m");
70                 return -errno;
71         }
72         
73         int bypass = 0;
74         
75         switch (type)
76         {
77         case aMPEG:
78                 bypass = 1;
79                 break;
80         case aAC3:
81                 bypass = 0;
82                 break;
83                 /*
84         case aDTS:
85                 bypass = 2;
86                 break;
87                 */
88         }
89         
90         if (::ioctl(m_fd, AUDIO_SET_BYPASS_MODE, bypass) < 0)
91                 eWarning("audio: AUDIO_SET_BYPASS_MODE: %m");
92         
93         if (::ioctl(m_fd, AUDIO_PLAY) < 0)
94                 eWarning("audio: AUDIO_PLAY: %m");
95         return 0;
96 }
97         
98 void eDVBAudio::stop()
99 {
100         if (::ioctl(m_fd, AUDIO_STOP) < 0)
101                 eWarning("audio: AUDIO_STOP: %m");
102 #if HAVE_DVB_API_VERSION > 2
103         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
104                 eWarning("audio: DMX_STOP: %m");
105 #endif
106 }
107         
108 #if HAVE_DVB_API_VERSION < 3
109 void eDVBAudio::stopPid()
110 {
111         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
112                 eWarning("audio: DMX_STOP: %m");
113 }
114 #endif
115
116 void eDVBAudio::flush()
117 {
118         if (::ioctl(m_fd, AUDIO_CLEAR_BUFFER) < 0)
119                 eDebug("audio: AUDIO_CLEAR_BUFFER: %m");
120 }
121
122 void eDVBAudio::freeze()
123 {
124         if (::ioctl(m_fd, AUDIO_PAUSE) < 0)
125                 eDebug("video: AUDIO_PAUSE: %m");
126 }
127
128 void eDVBAudio::unfreeze()
129 {
130         if (::ioctl(m_fd, AUDIO_CONTINUE) < 0)
131                 eDebug("video: AUDIO_CONTINUE: %m");
132 }
133         
134 eDVBAudio::~eDVBAudio()
135 {
136         if (m_fd >= 0)
137                 ::close(m_fd);
138         if (m_fd_demux >= 0)
139                 ::close(m_fd_demux);
140 }
141
142 DEFINE_REF(eDVBVideo);
143
144 eDVBVideo::eDVBVideo(eDVBDemux *demux, int dev): m_demux(demux)
145 {
146         char filename[128];
147 #if HAVE_DVB_API_VERSION < 3
148         sprintf(filename, "/dev/dvb/card%d/video%d", demux->adapter, dev);
149 #else
150         sprintf(filename, "/dev/dvb/adapter%d/video%d", demux->adapter, dev);
151 #endif
152         m_fd = ::open(filename, O_RDWR);
153         if (m_fd < 0)
154                 eWarning("%s: %m", filename);
155 #if HAVE_DVB_API_VERSION < 3
156         sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
157 #else
158         sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
159 #endif
160         m_fd_demux = ::open(filename, O_RDWR);
161         if (m_fd_demux < 0)
162                 eWarning("%s: %m", filename);
163 }
164         
165 int eDVBVideo::startPid(int pid)
166 {       
167         if ((m_fd < 0) || (m_fd_demux < 0))
168                 return -1;
169         dmx_pes_filter_params pes;
170
171         pes.pid      = pid;
172         pes.input    = DMX_IN_FRONTEND;
173         pes.output   = DMX_OUT_DECODER;
174         pes.pes_type = DMX_PES_VIDEO;
175         pes.flags    = 0;
176         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
177         {
178                 eWarning("video: DMX_SET_PES_FILTER: %m");
179                 return -errno;
180         }
181         if (::ioctl(m_fd_demux, DMX_START) < 0)
182         {
183                 eWarning("video: DMX_START: %m");
184                 return -errno;
185         }
186         if (::ioctl(m_fd, VIDEO_PLAY) < 0)
187                 eWarning("video: VIDEO_PLAY: %m");
188         return 0;
189 }
190         
191 void eDVBVideo::stop()
192 {
193 #if HAVE_DVB_API_VERSION > 2
194         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
195                 eWarning("video: DMX_STOP: %m");
196 #endif
197         eDebug("VIDEO_STOP");
198         if (::ioctl(m_fd, VIDEO_STOP, 1) < 0)
199                 eWarning("video: VIDEO_STOP: %m");
200 }
201
202 #if HAVE_DVB_API_VERSION < 3
203 void eDVBVideo::stopPid()
204 {
205         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
206                 eWarning("video: DMX_STOP: %m");
207 }
208 #endif
209
210 void eDVBVideo::flush()
211 {
212         if (::ioctl(m_fd, VIDEO_CLEAR_BUFFER) < 0)
213                 eDebug("video: VIDEO_CLEAR_BUFFER: %m");
214 }
215         
216 void eDVBVideo::freeze()
217 {
218         if (::ioctl(m_fd, VIDEO_FREEZE) < 0)
219                 eDebug("video: VIDEO_FREEZE: %m");
220 }
221         
222 void eDVBVideo::unfreeze()
223 {
224         if (::ioctl(m_fd, VIDEO_CONTINUE) < 0)
225                 eDebug("video: VIDEO_CONTINUE: %m");
226 }
227         
228 int eDVBVideo::setSlowMotion(int repeat)
229 {
230         m_is_slow_motion = repeat;
231         return ::ioctl(m_fd, VIDEO_SLOWMOTION, repeat);
232 }
233
234 int eDVBVideo::setFastForward(int skip)
235 {
236         m_is_fast_forward = skip;
237         return ::ioctl(m_fd, VIDEO_FAST_FORWARD, skip);
238 }
239         
240 eDVBVideo::~eDVBVideo()
241 {
242         if (m_is_slow_motion)
243                 setSlowMotion(0);
244         if (m_is_fast_forward)
245                 setFastForward(0);
246         if (m_fd >= 0)
247                 ::close(m_fd);
248         if (m_fd_demux >= 0)
249                 ::close(m_fd_demux);
250 }
251
252 DEFINE_REF(eDVBPCR);
253
254 eDVBPCR::eDVBPCR(eDVBDemux *demux): m_demux(demux)
255 {
256         char filename[128];
257 #if HAVE_DVB_API_VERSION < 3
258         sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
259 #else
260         sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
261 #endif
262         m_fd_demux = ::open(filename, O_RDWR);
263         if (m_fd_demux < 0)
264                 eWarning("%s: %m", filename);
265 }
266
267 int eDVBPCR::startPid(int pid)
268 {
269         if (m_fd_demux < 0)
270                 return -1;
271         dmx_pes_filter_params pes;
272
273         pes.pid      = pid;
274         pes.input    = DMX_IN_FRONTEND;
275         pes.output   = DMX_OUT_DECODER;
276         pes.pes_type = DMX_PES_PCR;
277         pes.flags    = 0;
278         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
279         {
280                 eWarning("video: DMX_SET_PES_FILTER: %m");
281                 return -errno;
282         }
283         if (::ioctl(m_fd_demux, DMX_START) < 0)
284         {
285                 eWarning("video: DMX_START: %m");
286                 return -errno;
287         }
288         return 0;
289 }
290
291 void eDVBPCR::stop()
292 {
293         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
294                 eWarning("video: DMX_STOP: %m");
295 }
296
297 eDVBPCR::~eDVBPCR()
298 {
299         if (m_fd_demux >= 0)
300                 ::close(m_fd_demux);
301 }
302
303 DEFINE_REF(eDVBTText);
304
305 eDVBTText::eDVBTText(eDVBDemux *demux): m_demux(demux)
306 {
307         char filename[128];
308 #if HAVE_DVB_API_VERSION < 3
309         sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
310 #else
311         sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
312 #endif
313         m_fd_demux = ::open(filename, O_RDWR);
314         if (m_fd_demux < 0)
315                 eWarning("%s: %m", filename);
316 }
317
318 int eDVBTText::startPid(int pid)
319 {
320         if (m_fd_demux < 0)
321                 return -1;
322         dmx_pes_filter_params pes;
323
324         pes.pid      = pid;
325         pes.input    = DMX_IN_FRONTEND;
326         pes.output   = DMX_OUT_DECODER;
327         pes.pes_type = DMX_PES_TELETEXT;
328         pes.flags    = 0;
329         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
330         {
331                 eWarning("video: DMX_SET_PES_FILTER: %m");
332                 return -errno;
333         }
334         if (::ioctl(m_fd_demux, DMX_START) < 0)
335         {
336                 eWarning("video: DMX_START: %m");
337                 return -errno;
338         }
339         return 0;
340 }
341
342 void eDVBTText::stop()
343 {
344         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
345                 eWarning("video: DMX_STOP: %m");
346 }
347
348 eDVBTText::~eDVBTText()
349 {
350         if (m_fd_demux >= 0)
351                 ::close(m_fd_demux);
352 }
353
354 DEFINE_REF(eTSMPEGDecoder);
355
356 int eTSMPEGDecoder::setState()
357 {
358         int res = 0;
359         
360         int noaudio = m_is_sm || m_is_ff || m_is_trickmode;
361         int nott = noaudio; /* actually same conditions */
362
363         if ((noaudio && m_audio) || (!m_audio && !noaudio))
364                 m_changed |= changeAudio;
365         
366         if ((nott && m_text) || (!m_text && !nott))
367                 m_changed |= changeText;
368         
369 #if HAVE_DVB_API_VERSION < 3
370         if (m_changed & changeAudio && m_audio)
371                 m_audio->stopPid();
372         if (m_changed & changeVideo && m_video)
373                 m_video->stopPid();
374         if (m_changed & changePCR && m_pcr)
375         {
376                 m_pcr->stop();
377                 m_pcr=0;
378         }
379         if (m_changed & changeAudio && m_audio)
380         {
381                 m_audio->stop();
382                 m_audio=0;
383         }
384         if (m_changed & changeVideo && m_video)
385         {
386                 m_video->stop();
387                 m_video=0;
388         }
389         if (m_changed & changePCR)
390         {
391                 m_pcr = new eDVBPCR(m_demux);
392                 if (m_pcr->startPid(m_pcrpid))
393                 {
394                         eWarning("pcr: startpid failed!");
395                         res = -1;
396                 }
397                 m_changed &= ~changePCR;
398         }
399         if (m_changed & changeVideo)
400         {
401                 m_video = new eDVBVideo(m_demux, 0);
402                 if (m_video->startPid(m_vpid))
403                 {
404                         eWarning("video: startpid failed!");
405                         res = -1;
406                 }
407                 m_changed &= ~changeVideo;
408         }
409         if (m_changed & changeAudio)
410         {
411                 m_audio = new eDVBAudio(m_demux, 0);
412                 if (m_audio->startPid(m_apid, m_atype))
413                 {
414                         eWarning("audio: startpid failed!");
415                         res = -1;
416                 }
417                 m_changed &= ~changeAudio;
418         }
419 #else
420         if (m_changed & changePCR)
421         {
422                 if (m_pcr)
423                         m_pcr->stop();
424                 m_pcr = 0;
425                 if ((m_pcrpid >= 0) && (m_pcrpid < 0x1FFF))
426                 {
427                         m_pcr = new eDVBPCR(m_demux);
428                         if (m_pcr->startPid(m_pcrpid))
429                         {
430                                 eWarning("pcr: startpid failed!");
431                                 res = -1;
432                         }
433                 }
434                 m_changed &= ~changePCR;
435         }
436         if (m_changed & changeVideo)
437         {
438                 eDebug("VIDEO CHANGED (to %04x)", m_vpid);
439                 if (m_video)
440                 {       
441                         eDebug("STOP");
442                         m_video->stop();
443                 }
444                 m_video = 0;
445                 if ((m_vpid >= 0) && (m_vpid < 0x1FFF))
446                 {
447                         eDebug("new video");
448                         m_video = new eDVBVideo(m_demux, 0);
449                         if (m_video->startPid(m_vpid))
450                         {
451                                 eWarning("video: startpid failed!");
452                                 res = -1;
453                         }
454                 }
455                 m_changed &= ~changeVideo;
456         }
457         if (m_changed & changeAudio)
458         {
459                 if (m_audio)
460                         m_audio->stop();
461                 m_audio = 0;
462                 if ((m_apid >= 0) && (m_apid < 0x1FFF) && !noaudio)
463                 {
464                         m_audio = new eDVBAudio(m_demux, 0);
465                         if (m_audio->startPid(m_apid, m_atype))
466                         {
467                                 eWarning("audio: startpid failed!");
468                                 res = -1;
469                         }
470                 }
471                 m_changed &= ~changeAudio;
472         }
473         if (m_changed & changeText)
474         {
475                 if (m_text)
476                         m_text->stop();
477                 m_text = 0;
478                 if ((m_textpid >= 0) && (m_textpid < 0x1FFF) && !nott)
479                 {
480                         m_text = new eDVBTText(m_demux);
481                         if (m_text->startPid(m_textpid))
482                         {
483                                 eWarning("text: startpid failed!");
484                                 res = -1;
485                         }
486                 }
487                 m_changed &= ~changeText;
488         }
489 #endif
490         return res;
491 }
492
493 eTSMPEGDecoder::eTSMPEGDecoder(eDVBDemux *demux, int decoder): m_demux(demux), m_changed(0)
494 {
495         demux->connectEvent(slot(*this, &eTSMPEGDecoder::demux_event), m_demux_event);
496         m_is_ff = m_is_sm = m_is_trickmode = 0;
497 }
498
499 eTSMPEGDecoder::~eTSMPEGDecoder()
500 {
501         m_vpid = m_apid = m_pcrpid = pidNone;
502         m_changed = -1;
503         setState();
504 }
505
506 RESULT eTSMPEGDecoder::setVideoPID(int vpid)
507 {
508         if (m_vpid != vpid)
509         {
510                 m_changed |= changeVideo;
511                 m_vpid = vpid;
512         }
513         return 0;
514 }
515
516 RESULT eTSMPEGDecoder::setAudioPID(int apid, int type)
517 {
518         if ((m_apid != apid) || (m_atype != type))
519         {
520                 m_changed |= changeAudio;
521                 m_atype = type;
522                 m_apid = apid;
523         }
524         return 0;
525 }
526
527 RESULT eTSMPEGDecoder::setSyncPCR(int pcrpid)
528 {
529         if (m_pcrpid != pcrpid)
530         {
531                 m_changed |= changePCR;
532                 m_pcrpid = pcrpid;
533         }
534         return 0;
535 }
536
537 RESULT eTSMPEGDecoder::setTextPID(int textpid)
538 {
539         if (m_textpid != textpid)
540         {
541                 m_changed |= changeText;
542                 m_textpid = textpid;
543         }
544         return 0;
545 }
546
547 RESULT eTSMPEGDecoder::setSyncMaster(int who)
548 {
549         return -1;
550 }
551
552 RESULT eTSMPEGDecoder::start()
553 {
554         return setState();
555 }
556
557 RESULT eTSMPEGDecoder::freeze(int cont)
558 {
559         if (m_video)
560                 m_video->freeze();
561
562         if (m_audio)
563                 m_audio->freeze();
564         
565         return 0;
566 }
567
568 RESULT eTSMPEGDecoder::unfreeze()
569 {
570         if (m_video)
571                 m_video->unfreeze();
572
573         if (m_audio)
574                 m_audio->unfreeze();
575         
576         return 0;
577 }
578
579 RESULT eTSMPEGDecoder::setSinglePictureMode(int when)
580 {
581         return -1;
582 }
583
584 RESULT eTSMPEGDecoder::setPictureSkipMode(int what)
585 {
586         return -1;
587 }
588
589 RESULT eTSMPEGDecoder::setFastForward(int frames_to_skip)
590 {
591         m_is_ff = frames_to_skip != 0;
592         
593         setState();
594         
595         if (m_video)
596                 return m_video->setFastForward(frames_to_skip);
597         else
598                 return -1;
599 }
600
601 RESULT eTSMPEGDecoder::setSlowMotion(int repeat)
602 {
603         m_is_sm = repeat != 0;
604         
605         setState();
606         
607         if (m_video)
608                 return m_video->setSlowMotion(repeat);
609         else
610                 return -1;
611 }
612
613 RESULT eTSMPEGDecoder::setZoom(int what)
614 {
615         return -1;
616 }
617
618 RESULT eTSMPEGDecoder::flush()
619 {
620         if (m_audio)
621                 m_audio->flush();
622         if (m_video)
623                 m_video->flush();
624         return 0;
625 }
626
627 void eTSMPEGDecoder::demux_event(int event)
628 {
629         switch (event)
630         {
631         case eDVBDemux::evtFlush:
632                 flush();
633                 break;
634         default:
635                 break;
636         }
637 }
638
639 RESULT eTSMPEGDecoder::setTrickmode(int what)
640 {
641         m_is_trickmode = what;
642         setState();
643         return 0;
644 }