cable scan works now
[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)
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 = DMX_PES_AUDIO;  // DMX_PES_AUDIO0
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)
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 #if HAVE_DVB_API_VERSION < 3
167         sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
168 #else
169         sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
170 #endif
171         m_fd_demux = ::open(filename, O_RDWR);
172         if (m_fd_demux < 0)
173                 eWarning("%s: %m", filename);
174 }
175         
176 int eDVBVideo::startPid(int pid)
177 {       
178         if ((m_fd < 0) || (m_fd_demux < 0))
179                 return -1;
180         dmx_pes_filter_params pes;
181
182         pes.pid      = pid;
183         pes.input    = DMX_IN_FRONTEND;
184         pes.output   = DMX_OUT_DECODER;
185         pes.pes_type = DMX_PES_VIDEO;
186         pes.flags    = 0;
187         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
188         {
189                 eWarning("video: DMX_SET_PES_FILTER: %m");
190                 return -errno;
191         }
192         if (::ioctl(m_fd_demux, DMX_START) < 0)
193         {
194                 eWarning("video: DMX_START: %m");
195                 return -errno;
196         }
197         if (::ioctl(m_fd, VIDEO_PLAY) < 0)
198                 eWarning("video: VIDEO_PLAY: %m");
199         return 0;
200 }
201         
202 void eDVBVideo::stop()
203 {
204 #if HAVE_DVB_API_VERSION > 2
205         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
206                 eWarning("video: DMX_STOP: %m");
207 #endif
208         eDebug("VIDEO_STOP");
209         if (::ioctl(m_fd, VIDEO_STOP, 1) < 0)
210                 eWarning("video: VIDEO_STOP: %m");
211 }
212
213 #if HAVE_DVB_API_VERSION < 3
214 void eDVBVideo::stopPid()
215 {
216         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
217                 eWarning("video: DMX_STOP: %m");
218 }
219 #endif
220
221 void eDVBVideo::flush()
222 {
223         if (::ioctl(m_fd, VIDEO_CLEAR_BUFFER) < 0)
224                 eDebug("video: VIDEO_CLEAR_BUFFER: %m");
225 }
226         
227 void eDVBVideo::freeze()
228 {
229         if (::ioctl(m_fd, VIDEO_FREEZE) < 0)
230                 eDebug("video: VIDEO_FREEZE: %m");
231 }
232         
233 void eDVBVideo::unfreeze()
234 {
235         if (::ioctl(m_fd, VIDEO_CONTINUE) < 0)
236                 eDebug("video: VIDEO_CONTINUE: %m");
237 }
238         
239 int eDVBVideo::setSlowMotion(int repeat)
240 {
241         m_is_slow_motion = repeat;
242         return ::ioctl(m_fd, VIDEO_SLOWMOTION, repeat);
243 }
244
245 int eDVBVideo::setFastForward(int skip)
246 {
247         m_is_fast_forward = skip;
248         return ::ioctl(m_fd, VIDEO_FAST_FORWARD, skip);
249 }
250
251 int eDVBVideo::getPTS(pts_t &now)
252 {
253         return ::ioctl(m_fd, VIDEO_GET_PTS, &now);
254 }
255         
256 eDVBVideo::~eDVBVideo()
257 {
258         if (m_is_slow_motion)
259                 setSlowMotion(0);
260         if (m_is_fast_forward)
261                 setFastForward(0);
262         if (m_fd >= 0)
263                 ::close(m_fd);
264         if (m_fd_demux >= 0)
265                 ::close(m_fd_demux);
266 }
267
268 DEFINE_REF(eDVBPCR);
269
270 eDVBPCR::eDVBPCR(eDVBDemux *demux): m_demux(demux)
271 {
272         char filename[128];
273 #if HAVE_DVB_API_VERSION < 3
274         sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
275 #else
276         sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
277 #endif
278         m_fd_demux = ::open(filename, O_RDWR);
279         if (m_fd_demux < 0)
280                 eWarning("%s: %m", filename);
281 }
282
283 int eDVBPCR::startPid(int pid)
284 {
285         if (m_fd_demux < 0)
286                 return -1;
287         dmx_pes_filter_params pes;
288
289         pes.pid      = pid;
290         pes.input    = DMX_IN_FRONTEND;
291         pes.output   = DMX_OUT_DECODER;
292         pes.pes_type = DMX_PES_PCR;
293         pes.flags    = 0;
294         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
295         {
296                 eWarning("video: DMX_SET_PES_FILTER: %m");
297                 return -errno;
298         }
299         if (::ioctl(m_fd_demux, DMX_START) < 0)
300         {
301                 eWarning("video: DMX_START: %m");
302                 return -errno;
303         }
304         return 0;
305 }
306
307 void eDVBPCR::stop()
308 {
309         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
310                 eWarning("video: DMX_STOP: %m");
311 }
312
313 eDVBPCR::~eDVBPCR()
314 {
315         if (m_fd_demux >= 0)
316                 ::close(m_fd_demux);
317 }
318
319 DEFINE_REF(eDVBTText);
320
321 eDVBTText::eDVBTText(eDVBDemux *demux): m_demux(demux)
322 {
323         char filename[128];
324 #if HAVE_DVB_API_VERSION < 3
325         sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
326 #else
327         sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
328 #endif
329         m_fd_demux = ::open(filename, O_RDWR);
330         if (m_fd_demux < 0)
331                 eWarning("%s: %m", filename);
332 }
333
334 int eDVBTText::startPid(int pid)
335 {
336         if (m_fd_demux < 0)
337                 return -1;
338         dmx_pes_filter_params pes;
339
340         pes.pid      = pid;
341         pes.input    = DMX_IN_FRONTEND;
342         pes.output   = DMX_OUT_DECODER;
343         pes.pes_type = DMX_PES_TELETEXT;
344         pes.flags    = 0;
345         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
346         {
347                 eWarning("video: DMX_SET_PES_FILTER: %m");
348                 return -errno;
349         }
350         if (::ioctl(m_fd_demux, DMX_START) < 0)
351         {
352                 eWarning("video: DMX_START: %m");
353                 return -errno;
354         }
355         return 0;
356 }
357
358 void eDVBTText::stop()
359 {
360         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
361                 eWarning("video: DMX_STOP: %m");
362 }
363
364 eDVBTText::~eDVBTText()
365 {
366         if (m_fd_demux >= 0)
367                 ::close(m_fd_demux);
368 }
369
370 DEFINE_REF(eTSMPEGDecoder);
371
372 int eTSMPEGDecoder::setState()
373 {
374         int res = 0;
375         
376         int noaudio = m_is_sm || m_is_ff || m_is_trickmode;
377         int nott = noaudio; /* actually same conditions */
378
379         if ((noaudio && m_audio) || (!m_audio && !noaudio))
380                 m_changed |= changeAudio;
381         
382         if ((nott && m_text) || (!m_text && !nott))
383                 m_changed |= changeText;
384         
385 #if HAVE_DVB_API_VERSION < 3
386         if (m_changed & changeAudio && m_audio)
387                 m_audio->stopPid();
388         if (m_changed & changeVideo && m_video)
389                 m_video->stopPid();
390         if (m_changed & changePCR && m_pcr)
391         {
392                 m_pcr->stop();
393                 m_pcr=0;
394         }
395         if (m_changed & changeAudio && m_audio)
396         {
397                 m_audio->stop();
398                 m_audio=0;
399         }
400         if (m_changed & changeVideo && m_video)
401         {
402                 m_video->stop();
403                 m_video=0;
404         }
405         if (m_changed & changePCR)
406         {
407                 m_pcr = new eDVBPCR(m_demux);
408                 if (m_pcr->startPid(m_pcrpid))
409                 {
410                         eWarning("pcr: startpid failed!");
411                         res = -1;
412                 }
413                 m_changed &= ~changePCR;
414         }
415         if (m_changed & changeVideo)
416         {
417                 m_video = new eDVBVideo(m_demux, 0);
418                 if (m_video->startPid(m_vpid))
419                 {
420                         eWarning("video: startpid failed!");
421                         res = -1;
422                 }
423                 m_changed &= ~changeVideo;
424         }
425         if (m_changed & changeAudio)
426         {
427                 m_audio = new eDVBAudio(m_demux, 0);
428                 if (m_audio->startPid(m_apid, m_atype))
429                 {
430                         eWarning("audio: startpid failed!");
431                         res = -1;
432                 }
433                 m_changed &= ~changeAudio;
434         }
435 #else
436         if (m_changed & changePCR)
437         {
438                 if (m_pcr)
439                         m_pcr->stop();
440                 m_pcr = 0;
441                 if ((m_pcrpid >= 0) && (m_pcrpid < 0x1FFF))
442                 {
443                         m_pcr = new eDVBPCR(m_demux);
444                         if (m_pcr->startPid(m_pcrpid))
445                         {
446                                 eWarning("pcr: startpid failed!");
447                                 res = -1;
448                         }
449                 }
450                 m_changed &= ~changePCR;
451         }
452         if (m_changed & changeVideo)
453         {
454                 eDebug("VIDEO CHANGED (to %04x)", m_vpid);
455                 if (m_video)
456                 {       
457                         eDebug("STOP");
458                         m_video->stop();
459                 }
460                 m_video = 0;
461                 if ((m_vpid >= 0) && (m_vpid < 0x1FFF))
462                 {
463                         eDebug("new video");
464                         m_video = new eDVBVideo(m_demux, 0);
465                         if (m_video->startPid(m_vpid))
466                         {
467                                 eWarning("video: startpid failed!");
468                                 res = -1;
469                         }
470                 }
471                 m_changed &= ~changeVideo;
472         }
473         if (m_changed & changeAudio)
474         {
475                 if (m_audio)
476                         m_audio->stop();
477                 m_audio = 0;
478                 if ((m_apid >= 0) && (m_apid < 0x1FFF) && !noaudio)
479                 {
480                         m_audio = new eDVBAudio(m_demux, 0);
481                         if (m_audio->startPid(m_apid, m_atype))
482                         {
483                                 eWarning("audio: startpid failed!");
484                                 res = -1;
485                         }
486                 }
487                 m_changed &= ~changeAudio;
488         }
489         if (m_changed & changeText)
490         {
491                 if (m_text)
492                         m_text->stop();
493                 m_text = 0;
494                 if ((m_textpid >= 0) && (m_textpid < 0x1FFF) && !nott)
495                 {
496                         m_text = new eDVBTText(m_demux);
497                         if (m_text->startPid(m_textpid))
498                         {
499                                 eWarning("text: startpid failed!");
500                                 res = -1;
501                         }
502                 }
503                 m_changed &= ~changeText;
504         }
505 #endif
506         return res;
507 }
508
509 eTSMPEGDecoder::eTSMPEGDecoder(eDVBDemux *demux, int decoder): m_demux(demux), m_changed(0)
510 {
511         demux->connectEvent(slot(*this, &eTSMPEGDecoder::demux_event), m_demux_event);
512         m_is_ff = m_is_sm = m_is_trickmode = 0;
513 }
514
515 eTSMPEGDecoder::~eTSMPEGDecoder()
516 {
517         m_vpid = m_apid = m_pcrpid = pidNone;
518         m_changed = -1;
519         setState();
520 }
521
522 RESULT eTSMPEGDecoder::setVideoPID(int vpid)
523 {
524         if (m_vpid != vpid)
525         {
526                 m_changed |= changeVideo;
527                 m_vpid = vpid;
528         }
529         return 0;
530 }
531
532 RESULT eTSMPEGDecoder::setAudioPID(int apid, int type)
533 {
534         if ((m_apid != apid) || (m_atype != type))
535         {
536                 m_changed |= changeAudio;
537                 m_atype = type;
538                 m_apid = apid;
539         }
540         return 0;
541 }
542
543 RESULT eTSMPEGDecoder::setSyncPCR(int pcrpid)
544 {
545         if (m_pcrpid != pcrpid)
546         {
547                 m_changed |= changePCR;
548                 m_pcrpid = pcrpid;
549         }
550         return 0;
551 }
552
553 RESULT eTSMPEGDecoder::setTextPID(int textpid)
554 {
555         if (m_textpid != textpid)
556         {
557                 m_changed |= changeText;
558                 m_textpid = textpid;
559         }
560         return 0;
561 }
562
563 RESULT eTSMPEGDecoder::setSyncMaster(int who)
564 {
565         return -1;
566 }
567
568 RESULT eTSMPEGDecoder::start()
569 {
570         return setState();
571 }
572
573 RESULT eTSMPEGDecoder::freeze(int cont)
574 {
575         if (m_video)
576                 m_video->freeze();
577
578         if (m_audio)
579                 m_audio->freeze();
580         
581         return 0;
582 }
583
584 RESULT eTSMPEGDecoder::unfreeze()
585 {
586         if (m_video)
587                 m_video->unfreeze();
588
589         if (m_audio)
590                 m_audio->unfreeze();
591         
592         return 0;
593 }
594
595 RESULT eTSMPEGDecoder::setSinglePictureMode(int when)
596 {
597         return -1;
598 }
599
600 RESULT eTSMPEGDecoder::setPictureSkipMode(int what)
601 {
602         return -1;
603 }
604
605 RESULT eTSMPEGDecoder::setFastForward(int frames_to_skip)
606 {
607         m_is_ff = frames_to_skip != 0;
608         
609         setState();
610         
611         if (m_video)
612                 return m_video->setFastForward(frames_to_skip);
613         else
614                 return -1;
615 }
616
617 RESULT eTSMPEGDecoder::setSlowMotion(int repeat)
618 {
619         m_is_sm = repeat != 0;
620         
621         setState();
622         
623         if (m_video)
624                 return m_video->setSlowMotion(repeat);
625         else
626                 return -1;
627 }
628
629 RESULT eTSMPEGDecoder::setZoom(int what)
630 {
631         return -1;
632 }
633
634 RESULT eTSMPEGDecoder::flush()
635 {
636         if (m_audio)
637                 m_audio->flush();
638         if (m_video)
639                 m_video->flush();
640         return 0;
641 }
642
643 void eTSMPEGDecoder::demux_event(int event)
644 {
645         switch (event)
646         {
647         case eDVBDemux::evtFlush:
648                 flush();
649                 break;
650         default:
651                 break;
652         }
653 }
654
655 RESULT eTSMPEGDecoder::setTrickmode(int what)
656 {
657         m_is_trickmode = what;
658         setState();
659         return 0;
660 }
661
662 RESULT eTSMPEGDecoder::getPTS(int what, pts_t &pts)
663 {
664         if (what == 0) /* auto */
665                 what = m_video ? 1 : 2;
666
667         if (what == 1) /* video */
668         {
669                 if (m_video)
670                         return m_video->getPTS(pts);
671                 else
672                         return -1;
673         }
674
675         if (what == 2) /* audio */
676         {
677                 if (m_audio)
678                         return m_audio->getPTS(pts);
679                 else
680                         return -1;
681         }
682
683         return -1;
684 }