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