fixed invalid cast of an rvalue by adding a string constructor to class eServiceRefer...
[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(eDVBVText);
305
306 eDVBVText::eDVBVText(eDVBDemux *demux): m_demux(demux)
307 {
308         char filename[128];
309 #if HAVE_DVB_API_VERSION < 3
310         sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
311 #else
312         sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
313 #endif
314         m_fd_demux = ::open(filename, O_RDWR);
315         if (m_fd_demux < 0)
316                 eWarning("%s: %m", filename);
317 }
318
319 int eDVBVText::startPid(int pid)
320 {
321         if (m_fd_demux < 0)
322                 return -1;
323         dmx_pes_filter_params pes;
324
325         pes.pid      = pid;
326         pes.input    = DMX_IN_FRONTEND;
327         pes.output   = DMX_OUT_DECODER;
328         pes.pes_type = DMX_PES_TELETEXT;
329         pes.flags    = 0;
330         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
331         {
332                 eWarning("video: DMX_SET_PES_FILTER: %m");
333                 return -errno;
334         }
335         if (::ioctl(m_fd_demux, DMX_START) < 0)
336         {
337                 eWarning("video: DMX_START: %m");
338                 return -errno;
339         }
340         return 0;
341 }
342
343 void eDVBVText::stop()
344 {
345         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
346                 eWarning("video: DMX_STOP: %m");
347 }
348
349 eDVBVText::~eDVBVText()
350 {
351         if (m_fd_demux >= 0)
352                 ::close(m_fd_demux);
353 }
354
355 DEFINE_REF(eTSMPEGDecoder);
356
357 int eTSMPEGDecoder::setState()
358 {
359         int res = 0;
360         
361         int noaudio = m_is_sm || m_is_ff || m_is_trickmode;
362         
363         if ((noaudio && m_audio) || (!m_audio && !noaudio))
364                 m_changed |= changeAudio;
365         
366 #if HAVE_DVB_API_VERSION < 3
367         if (m_changed & changeAudio && m_audio)
368                 m_audio->stopPid();
369         if (m_changed & changeVideo && m_video)
370                 m_video->stopPid();
371         if (m_changed & changePCR && m_pcr)
372         {
373                 m_pcr->stop();
374                 m_pcr=0;
375         }
376         if (m_changed & changeAudio && m_audio)
377         {
378                 m_audio->stop();
379                 m_audio=0;
380         }
381         if (m_changed & changeVideo && m_video)
382         {
383                 m_video->stop();
384                 m_video=0;
385         }
386         if (m_changed & changePCR)
387         {
388                 m_pcr = new eDVBPCR(m_demux);
389                 if (m_pcr->startPid(m_pcrpid))
390                 {
391                         eWarning("pcr: startpid failed!");
392                         res = -1;
393                 }
394                 m_changed &= ~changePCR;
395         }
396         if (m_changed & changeVideo)
397         {
398                 m_video = new eDVBVideo(m_demux, 0);
399                 if (m_video->startPid(m_vpid))
400                 {
401                         eWarning("video: startpid failed!");
402                         res = -1;
403                 }
404                 m_changed &= ~changeVideo;
405         }
406         if (m_changed & changeAudio)
407         {
408                 m_audio = new eDVBAudio(m_demux, 0);
409                 if (m_audio->startPid(m_apid, m_atype))
410                 {
411                         eWarning("audio: startpid failed!");
412                         res = -1;
413                 }
414                 m_changed &= ~changeAudio;
415         }
416 #else
417         if (m_changed & changePCR)
418         {
419                 if (m_pcr)
420                         m_pcr->stop();
421                 m_pcr = 0;
422                 if ((m_pcrpid >= 0) && (m_pcrpid < 0x1FFF))
423                 {
424                         m_pcr = new eDVBPCR(m_demux);
425                         if (m_pcr->startPid(m_pcrpid))
426                         {
427                                 eWarning("pcr: startpid failed!");
428                                 res = -1;
429                         }
430                 }
431                 m_changed &= ~changePCR;
432         }
433         if (m_changed & changeVideo)
434         {
435                 eDebug("VIDEO CHANGED (to %04x)", m_vpid);
436                 if (m_video)
437                 {       
438                         eDebug("STOP");
439                         m_video->stop();
440                 }
441                 m_video = 0;
442                 if ((m_vpid >= 0) && (m_vpid < 0x1FFF))
443                 {
444                         eDebug("new video");
445                         m_video = new eDVBVideo(m_demux, 0);
446                         if (m_video->startPid(m_vpid))
447                         {
448                                 eWarning("video: startpid failed!");
449                                 res = -1;
450                         }
451                 }
452                 m_changed &= ~changeVideo;
453         }
454         if (m_changed & changeAudio)
455         {
456                 if (m_audio)
457                         m_audio->stop();
458                 m_audio = 0;
459                 if ((m_apid >= 0) && (m_apid < 0x1FFF) && !noaudio)
460                 {
461                         m_audio = new eDVBAudio(m_demux, 0);
462                         if (m_audio->startPid(m_apid, m_atype))
463                         {
464                                 eWarning("audio: startpid failed!");
465                                 res = -1;
466                         }
467                 }
468                 m_changed &= ~changeAudio;
469         }
470         if (m_changed & changeText)
471         {
472                 if (m_text)
473                         m_text->stop();
474                 m_text = 0;
475                 if ((m_textpid >= 0) && (m_textpid < 0x1FFF))
476                 {
477                         m_text = new eDVBVText(m_demux);
478                         if (m_text->startPid(m_textpid))
479                         {
480                                 eWarning("text: startpid failed!");
481                                 res = -1;
482                         }
483                 }
484                 m_changed &= ~changeText;
485         }
486 #endif
487         return res;
488 }
489
490 eTSMPEGDecoder::eTSMPEGDecoder(eDVBDemux *demux, int decoder): m_demux(demux), m_changed(0)
491 {
492         demux->connectEvent(slot(*this, &eTSMPEGDecoder::demux_event), m_demux_event);
493         m_is_ff = m_is_sm = m_is_trickmode = 0;
494 }
495
496 eTSMPEGDecoder::~eTSMPEGDecoder()
497 {
498         m_vpid = m_apid = m_pcrpid = pidNone;
499         m_changed = -1;
500         setState();
501 }
502
503 RESULT eTSMPEGDecoder::setVideoPID(int vpid)
504 {
505         if (m_vpid != vpid)
506         {
507                 m_changed |= changeVideo;
508                 m_vpid = vpid;
509         }
510         return 0;
511 }
512
513 RESULT eTSMPEGDecoder::setAudioPID(int apid, int type)
514 {
515         if ((m_apid != apid) || (m_atype != type))
516         {
517                 m_changed |= changeAudio;
518                 m_atype = type;
519                 m_apid = apid;
520         }
521         return 0;
522 }
523
524 RESULT eTSMPEGDecoder::setSyncPCR(int pcrpid)
525 {
526         if (m_pcrpid != pcrpid)
527         {
528                 m_changed |= changePCR;
529                 m_pcrpid = pcrpid;
530         }
531         return 0;
532 }
533
534 RESULT eTSMPEGDecoder::setTextPID(int textpid)
535 {
536         if (m_textpid != textpid)
537         {
538                 m_changed |= changeText;
539                 m_textpid = textpid;
540         }
541         return 0;
542 }
543
544 RESULT eTSMPEGDecoder::setSyncMaster(int who)
545 {
546         return -1;
547 }
548
549 RESULT eTSMPEGDecoder::start()
550 {
551         return setState();
552 }
553
554 RESULT eTSMPEGDecoder::freeze(int cont)
555 {
556         if (m_video)
557                 m_video->freeze();
558
559         if (m_audio)
560                 m_audio->freeze();
561         
562         return 0;
563 }
564
565 RESULT eTSMPEGDecoder::unfreeze()
566 {
567         if (m_video)
568                 m_video->unfreeze();
569
570         if (m_audio)
571                 m_audio->unfreeze();
572         
573         return 0;
574 }
575
576 RESULT eTSMPEGDecoder::setSinglePictureMode(int when)
577 {
578         return -1;
579 }
580
581 RESULT eTSMPEGDecoder::setPictureSkipMode(int what)
582 {
583         return -1;
584 }
585
586 RESULT eTSMPEGDecoder::setFastForward(int frames_to_skip)
587 {
588         m_is_ff = frames_to_skip != 0;
589         
590         setState();
591         
592         if (m_video)
593                 return m_video->setFastForward(frames_to_skip);
594         else
595                 return -1;
596 }
597
598 RESULT eTSMPEGDecoder::setSlowMotion(int repeat)
599 {
600         m_is_sm = repeat != 0;
601         
602         setState();
603         
604         if (m_video)
605                 return m_video->setSlowMotion(repeat);
606         else
607                 return -1;
608 }
609
610 RESULT eTSMPEGDecoder::setZoom(int what)
611 {
612         return -1;
613 }
614
615 RESULT eTSMPEGDecoder::flush()
616 {
617         if (m_audio)
618                 m_audio->flush();
619         if (m_video)
620                 m_video->flush();
621         return 0;
622 }
623
624 void eTSMPEGDecoder::demux_event(int event)
625 {
626         switch (event)
627         {
628         case eDVBDemux::evtFlush:
629                 flush();
630                 break;
631         default:
632                 break;
633         }
634 }
635
636 RESULT eTSMPEGDecoder::setTrickmode(int what)
637 {
638         m_is_trickmode = what;
639         setState();
640         return 0;
641 }