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