Merge branch 'bug_621_caid_info' into experimental
[vuplus_dvbapp] / lib / dvb / decoder.cpp
1 #include <lib/base/ebase.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_VIDEO0 DMX_PES_VIDEO
14 #define DMX_PES_AUDIO0 DMX_PES_AUDIO
15 #define DMX_PES_PCR0 DMX_PES_PCR
16 #define DMX_PES_TELETEXT0 DMX_PES_TELETEXT
17 #define DMX_PES_VIDEO1 DMX_PES_VIDEO
18 #define DMX_PES_AUDIO1 DMX_PES_AUDIO
19 #define DMX_PES_PCR1 DMX_PES_PCR
20 #define DMX_PES_TELETEXT1 DMX_PES_TELETEXT
21 #include <ost/dmx.h>
22 #include <ost/video.h>
23 #include <ost/audio.h>
24 #else
25 #include <linux/dvb/audio.h>
26 #include <linux/dvb/video.h>
27 #include <linux/dvb/dmx.h>
28 #endif
29
30 #include <unistd.h>
31 #include <fcntl.h>
32 #include <sys/ioctl.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <errno.h>
36
37         /* these are quite new... */
38 #ifndef AUDIO_GET_PTS
39 #define AUDIO_GET_PTS              _IOR('o', 19, __u64)
40 #define VIDEO_GET_PTS              _IOR('o', 57, __u64)
41 #endif
42
43 DEFINE_REF(eDVBAudio);
44
45 eDVBAudio::eDVBAudio(eDVBDemux *demux, int dev)
46         :m_demux(demux), m_dev(dev)
47 {
48         char filename[128];
49 #if HAVE_DVB_API_VERSION < 3
50         sprintf(filename, "/dev/dvb/card%d/audio%d", demux->adapter, dev);
51 #else
52         sprintf(filename, "/dev/dvb/adapter%d/audio%d", demux->adapter, dev);
53 #endif
54         m_fd = ::open(filename, O_RDWR);
55         if (m_fd < 0)
56                 eWarning("%s: %m", filename);
57 #if HAVE_DVB_API_VERSION < 3
58         sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
59 #else
60         sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
61 #endif
62         m_fd_demux = ::open(filename, O_RDWR);
63         if (m_fd_demux < 0)
64                 eWarning("%s: %m", filename);
65 }
66
67 #if HAVE_DVB_API_VERSION < 3
68 int eDVBAudio::setPid(int pid, int type)
69 {
70         if ((m_fd < 0) || (m_fd_demux < 0))
71                 return -1;
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                 eDebug("failed (%m)");
92
93         dmx_pes_filter_params pes;
94
95         pes.pid      = pid;
96         pes.input    = DMX_IN_FRONTEND;
97         pes.output   = DMX_OUT_DECODER;
98         pes.pes_type = m_dev ? DMX_PES_AUDIO1 : DMX_PES_AUDIO0; /* FIXME */
99         pes.flags    = 0;
100         eDebugNoNewLine("DMX_SET_PES_FILTER(0x%02x) - audio - ", pid);
101         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
102         {
103                 eDebug("failed (%m)");
104                 return -errno;
105         }
106         eDebug("ok");
107
108         return 0;
109 }
110
111 int eDVBAudio::startPid()
112 {
113         eDebugNoNewLine("DEMUX_START - audio - ");
114         if (::ioctl(m_fd_demux, DMX_START) < 0)
115         {
116                 eDebug("failed (%m)");
117                 return -errno;
118         }
119         eDebug("ok");
120         return 0;
121 }
122
123 int eDVBAudio::start()
124 {
125         eDebugNoNewLine("AUDIO_PLAY - ");
126         if (::ioctl(m_fd, AUDIO_PLAY) < 0)
127         {
128                 eDebug("failed (%m)");
129                 return -errno;
130         }
131         eDebug("ok");
132         return 0;
133 }
134
135 int eDVBAudio::stopPid()
136 {
137         eDebugNoNewLine("DEMUX_STOP - audio - ");
138         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
139         {
140                 eDebug("failed (%m)");
141                 return -errno;
142         }
143         eDebug("ok");
144         return 0;
145 }
146
147 int eDVBAudio::setAVSync(int val)
148 {
149         eDebugNoNewLine("AUDIO_SET_AV_SYNC - ");
150         if (::ioctl(m_fd, AUDIO_SET_AV_SYNC, val) < 0)
151         {
152                 eDebug("failed (%m)");
153                 return -errno;
154         }
155         eDebug("ok");
156         return 0;
157 }
158 #else
159 int eDVBAudio::startPid(int pid, int type)
160 {
161         if ((m_fd < 0) || (m_fd_demux < 0))
162                 return -1;
163         dmx_pes_filter_params pes;
164
165         pes.pid      = pid;
166         pes.input    = DMX_IN_FRONTEND;
167         pes.output   = DMX_OUT_DECODER;
168         pes.pes_type = m_dev ? DMX_PES_AUDIO1 : DMX_PES_AUDIO0; /* FIXME */
169         pes.flags    = 0;
170         eDebugNoNewLine("DMX_SET_PES_FILTER(0x%02x) - audio - ", pid);
171         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
172         {
173                 eDebug("failed (%m)");
174                 return -errno;
175         }
176         eDebug("ok");
177         eDebugNoNewLine("DEMUX_START - audio - ");
178         if (::ioctl(m_fd_demux, DMX_START) < 0)
179         {
180                 eDebug("failed (%m)");
181                 return -errno;
182         }
183         eDebug("ok");
184         int bypass = 0;
185
186         switch (type)
187         {
188         case aMPEG:
189                 bypass = 1;
190                 break;
191         case aAC3:
192                 bypass = 0;
193                 break;
194         case aDTS:
195                 bypass = 2;
196                 break;
197         case aAAC:
198                 bypass = 8;
199                 break;
200         case aAACHE:
201                 bypass = 9;
202                 break;
203         case aLPCM:
204                 bypass = 6;
205                 break;
206         case aDTSHD:
207                 bypass = 0x10;
208                 break;
209         }
210
211         eDebugNoNewLine("AUDIO_SET_BYPASS(%d) - ", bypass);
212         if (::ioctl(m_fd, AUDIO_SET_BYPASS_MODE, bypass) < 0)
213                 eDebug("failed (%m)");
214         else
215                 eDebug("ok");
216         freeze();  // why freeze here?!? this is a problem when only a pid change is requested... because of the unfreeze logic in Decoder::setState
217         eDebugNoNewLine("AUDIO_PLAY - ");
218         if (::ioctl(m_fd, AUDIO_PLAY) < 0)
219                 eDebug("failed (%m)");
220         else
221                 eDebug("ok");
222         return 0;
223 }
224 #endif
225
226 void eDVBAudio::stop()
227 {
228         eDebugNoNewLine("AUDIO_STOP - ");
229         if (::ioctl(m_fd, AUDIO_STOP) < 0)
230                 eDebug("failed (%m)");
231         else
232                 eDebug("ok");
233 #if HAVE_DVB_API_VERSION > 2
234         eDebugNoNewLine("DEMUX_STOP - audio - ");
235         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
236                 eDebug("failed (%m)");
237         else
238                 eDebug("ok");
239 #endif
240 }
241
242 void eDVBAudio::flush()
243 {
244         eDebugNoNewLine("AUDIO_CLEAR_BUFFER - ");
245         if (::ioctl(m_fd, AUDIO_CLEAR_BUFFER) < 0)
246                 eDebug("failed (%m)");
247         else
248                 eDebug("ok");
249 }
250
251 void eDVBAudio::freeze()
252 {
253         eDebugNoNewLine("AUDIO_PAUSE - ");
254         if (::ioctl(m_fd, AUDIO_PAUSE) < 0)
255                 eDebug("failed (%m)");
256         else
257                 eDebug("ok");
258 }
259
260 void eDVBAudio::unfreeze()
261 {
262         eDebugNoNewLine("AUDIO_CONTINUE - ");
263         if (::ioctl(m_fd, AUDIO_CONTINUE) < 0)
264                 eDebug("failed (%m)");
265         else
266                 eDebug("ok");
267 }
268
269 void eDVBAudio::setChannel(int channel)
270 {
271         int val = AUDIO_STEREO;
272         switch (channel)
273         {
274         case aMonoLeft: val = AUDIO_MONO_LEFT; break;
275         case aMonoRight: val = AUDIO_MONO_RIGHT; break;
276         default: break;
277         }
278         eDebugNoNewLine("AUDIO_CHANNEL_SELECT(%d) - ", val);
279         if (::ioctl(m_fd, AUDIO_CHANNEL_SELECT, val) < 0)
280                 eDebug("failed (%m)");
281         else
282                 eDebug("ok");
283 }
284
285 int eDVBAudio::getPTS(pts_t &now)
286 {
287         if (::ioctl(m_fd, AUDIO_GET_PTS, &now) < 0)
288                 eDebug("AUDIO_GET_PTS failed (%m)");
289         return 0;
290 }
291
292 eDVBAudio::~eDVBAudio()
293 {
294         unfreeze();  // why unfreeze here... but not unfreeze video in ~eDVBVideo ?!?
295         if (m_fd >= 0)
296                 ::close(m_fd);
297         if (m_fd_demux >= 0)
298                 ::close(m_fd_demux);
299 }
300
301 DEFINE_REF(eDVBVideo);
302
303 eDVBVideo::eDVBVideo(eDVBDemux *demux, int dev)
304         : m_demux(demux), m_dev(dev),
305         m_width(-1), m_height(-1), m_framerate(-1), m_aspect(-1), m_progressive(-1)
306 {
307         char filename[128];
308 #if HAVE_DVB_API_VERSION < 3
309         sprintf(filename, "/dev/dvb/card%d/video%d", demux->adapter, dev);
310         m_fd_video = ::open("/dev/video", O_RDWR);
311         if (m_fd_video < 0)
312                 eWarning("/dev/video: %m");
313 #else
314         sprintf(filename, "/dev/dvb/adapter%d/video%d", demux->adapter, dev);
315 #endif
316         m_fd = ::open(filename, O_RDWR);
317         if (m_fd < 0)
318                 eWarning("%s: %m", filename);
319         else
320         {
321                 m_sn = eSocketNotifier::create(eApp, m_fd, eSocketNotifier::Priority);
322                 CONNECT(m_sn->activated, eDVBVideo::video_event);
323         }
324         eDebug("Video Device: %s", filename);
325 #if HAVE_DVB_API_VERSION < 3
326         sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
327 #else
328         sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
329 #endif
330         m_fd_demux = ::open(filename, O_RDWR);
331         if (m_fd_demux < 0)
332                 eWarning("%s: %m", filename);
333         eDebug("demux device: %s", filename);
334 }
335
336 // not finally values i think.. !!
337 #define VIDEO_STREAMTYPE_MPEG2 0
338 #define VIDEO_STREAMTYPE_MPEG4_H264 1
339 #define VIDEO_STREAMTYPE_VC1 3
340 #define VIDEO_STREAMTYPE_MPEG4_Part2 4
341 #define VIDEO_STREAMTYPE_VC1_SM 5
342 #define VIDEO_STREAMTYPE_MPEG1 6
343
344 #if HAVE_DVB_API_VERSION < 3
345 int eDVBVideo::setPid(int pid)
346 {
347         if ((m_fd < 0) || (m_fd_demux < 0))
348                 return -1;
349         dmx_pes_filter_params pes;
350
351         pes.pid      = pid;
352         pes.input    = DMX_IN_FRONTEND;
353         pes.output   = DMX_OUT_DECODER;
354         pes.pes_type = m_dev ? DMX_PES_VIDEO1 : DMX_PES_VIDEO0; /* FIXME */
355         pes.flags    = 0;
356         eDebugNoNewLine("DMX_SET_PES_FILTER(0x%02x) - video - ", pid);
357         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
358         {
359                 eDebug("failed (%m)");
360                 return -errno;
361         }
362         eDebug("ok");
363         return 0;
364 }
365
366 int eDVBVideo::startPid()
367 {
368         eDebugNoNewLine("DEMUX_START - video - ");
369         if (::ioctl(m_fd_demux, DMX_START) < 0)
370         {
371                 eDebug("failed (%m)");
372                 return -errno;
373         }
374         eDebug("ok");
375         return 0;
376 }
377
378 int eDVBVideo::start()
379 {
380         eDebugNoNewLine("VIDEO_PLAY - ");
381         if (::ioctl(m_fd, VIDEO_PLAY) < 0)
382         {
383                 eDebug("failed (%m)");
384                 return -errno;
385         }
386         eDebug("ok");
387         return 0;
388 }
389
390 int eDVBVideo::stopPid()
391 {
392         eDebugNoNewLine("DEMUX_STOP - video - ");
393         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
394         {
395                 eDebug("failed (%m)");
396                 return -errno;
397         }
398         eDebug("ok");
399         return 0;
400 }
401 #else
402 int eDVBVideo::startPid(int pid, int type)
403 {
404         int streamtype = VIDEO_STREAMTYPE_MPEG2;
405
406         if ((m_fd < 0) || (m_fd_demux < 0))
407                 return -1;
408         dmx_pes_filter_params pes;
409
410         switch(type)
411         {
412         default:
413         case MPEG2:
414                 break;
415         case MPEG4_H264:
416                 streamtype = VIDEO_STREAMTYPE_MPEG4_H264;
417                 break;
418         case MPEG1:
419                 streamtype = VIDEO_STREAMTYPE_MPEG1;
420                 break;
421         case MPEG4_Part2:
422                 streamtype = VIDEO_STREAMTYPE_MPEG4_Part2;
423                 break;
424         case VC1:
425                 streamtype = VIDEO_STREAMTYPE_VC1;
426                 break;
427         case VC1_SM:
428                 streamtype = VIDEO_STREAMTYPE_VC1_SM;
429                 break;
430         }
431
432         eDebugNoNewLine("VIDEO_SET_STREAMTYPE %d - ", streamtype);
433         if (::ioctl(m_fd, VIDEO_SET_STREAMTYPE, streamtype) < 0)
434                 eDebug("failed (%m)");
435         else
436                 eDebug("ok");
437
438         pes.pid      = pid;
439         pes.input    = DMX_IN_FRONTEND;
440         pes.output   = DMX_OUT_DECODER;
441         pes.pes_type = m_dev ? DMX_PES_VIDEO1 : DMX_PES_VIDEO0; /* FIXME */
442         pes.flags    = 0;
443         eDebugNoNewLine("DMX_SET_PES_FILTER(0x%02x) - video - ", pid);
444         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
445         {
446                 eDebug("failed (%m)");
447                 return -errno;
448         }
449         eDebug("ok");
450         eDebugNoNewLine("DEMUX_START - video - ");
451         if (::ioctl(m_fd_demux, DMX_START) < 0)
452         {
453                 eDebug("failed (%m)");
454                 return -errno;
455         }
456         eDebug("ok");
457         freeze();  // why freeze here?!? this is a problem when only a pid change is requested... because of the unfreeze logic in Decoder::setState
458         eDebugNoNewLine("VIDEO_PLAY - ");
459         if (::ioctl(m_fd, VIDEO_PLAY) < 0)
460                 eDebug("failed (%m)");
461         else
462                 eDebug("ok");
463         return 0;
464 }
465 #endif
466
467 void eDVBVideo::stop()
468 {
469 #if HAVE_DVB_API_VERSION > 2
470         eDebugNoNewLine("DEMUX_STOP - video - ");
471         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
472                 eDebug("failed (%m)");
473         else
474                 eDebug("ok");
475 #endif
476         eDebugNoNewLine("VIDEO_STOP - ");
477         if (::ioctl(m_fd, VIDEO_STOP, 1) < 0)
478                 eDebug("failed (%m)");
479         else
480                 eDebug("ok");
481 }
482
483 void eDVBVideo::flush()
484 {
485         eDebugNoNewLine("VIDEO_CLEAR_BUFFER - ");
486         if (::ioctl(m_fd, VIDEO_CLEAR_BUFFER) < 0)
487                 eDebug("failed (%m)");
488         else
489                 eDebug("ok");
490 }
491
492 void eDVBVideo::freeze()
493 {
494         eDebugNoNewLine("VIDEO_FREEZE - ");
495         if (::ioctl(m_fd, VIDEO_FREEZE) < 0)
496                 eDebug("failed (%m)");
497         else
498                 eDebug("ok");
499 }
500
501 void eDVBVideo::unfreeze()
502 {
503         eDebugNoNewLine("VIDEO_CONTINUE - ");
504         if (::ioctl(m_fd, VIDEO_CONTINUE) < 0)
505                 eDebug("failed (%m)");
506         else
507                 eDebug("ok");
508 }
509
510 int eDVBVideo::setSlowMotion(int repeat)
511 {
512         eDebugNoNewLine("VIDEO_SLOWMOTION(%d) - ", repeat);
513         int ret = ::ioctl(m_fd, VIDEO_SLOWMOTION, repeat);
514         if (ret < 0)
515                 eDebug("failed(%m)");
516         else
517                 eDebug("ok");
518         return ret;
519 }
520
521 int eDVBVideo::setFastForward(int skip)
522 {
523         eDebugNoNewLine("VIDEO_FAST_FORWARD(%d) - ", skip);
524         int ret = ::ioctl(m_fd, VIDEO_FAST_FORWARD, skip);
525         if (ret < 0)
526                 eDebug("failed(%m)");
527         else
528                 eDebug("ok");
529         return ret;
530 }
531
532 int eDVBVideo::getPTS(pts_t &now)
533 {
534 #if HAVE_DVB_API_VERSION < 3
535         #define VIDEO_GET_PTS_OLD           _IOR('o', 1, unsigned int*)
536         unsigned int pts;
537         int ret = ::ioctl(m_fd_video, VIDEO_GET_PTS_OLD, &pts);
538         now = pts;
539         now *= 2;
540 #else
541         int ret = ::ioctl(m_fd, VIDEO_GET_PTS, &now);
542 #endif
543         if (ret < 0)
544                 eDebug("VIDEO_GET_PTS failed(%m)");
545         return ret;
546 }
547
548 eDVBVideo::~eDVBVideo()
549 {
550         if (m_fd >= 0)
551                 ::close(m_fd);
552         if (m_fd_demux >= 0)
553                 ::close(m_fd_demux);
554 #if HAVE_DVB_API_VERSION < 3
555         if (m_fd_video >= 0)
556                 ::close(m_fd_video);
557 #endif
558 }
559
560 void eDVBVideo::video_event(int)
561 {
562 #if HAVE_DVB_API_VERSION >= 3
563         struct video_event evt;
564         eDebugNoNewLine("VIDEO_GET_EVENT - ");
565         if (::ioctl(m_fd, VIDEO_GET_EVENT, &evt) < 0)
566                 eDebug("failed (%m)");
567         else
568         {
569                 eDebug("ok");
570                 if (evt.type == VIDEO_EVENT_SIZE_CHANGED)
571                 {
572                         struct iTSMPEGDecoder::videoEvent event;
573                         event.type = iTSMPEGDecoder::videoEvent::eventSizeChanged;
574                         m_aspect = event.aspect = evt.u.size.aspect_ratio == 0 ? 2 : 3;  // convert dvb api to etsi
575                         m_height = event.height = evt.u.size.h;
576                         m_width = event.width = evt.u.size.w;
577                         /* emit */ m_event(event);
578                 }
579                 else if (evt.type == VIDEO_EVENT_FRAME_RATE_CHANGED)
580                 {
581                         struct iTSMPEGDecoder::videoEvent event;
582                         event.type = iTSMPEGDecoder::videoEvent::eventFrameRateChanged;
583                         m_framerate = event.framerate = evt.u.frame_rate;
584                         /* emit */ m_event(event);
585                 }
586                 else if (evt.type == 16 /*VIDEO_EVENT_PROGRESSIVE_CHANGED*/)
587                 {
588                         struct iTSMPEGDecoder::videoEvent event;
589                         event.type = iTSMPEGDecoder::videoEvent::eventProgressiveChanged;
590                         m_progressive = event.progressive = evt.u.frame_rate;
591                         /* emit */ m_event(event);
592                 }
593                 else
594                         eDebug("unhandled DVBAPI Video Event %d", evt.type);
595         }
596 #else
597 #warning "FIXMEE!! Video Events not implemented for old api"
598 #endif
599 }
600
601 RESULT eDVBVideo::connectEvent(const Slot1<void, struct iTSMPEGDecoder::videoEvent> &event, ePtr<eConnection> &conn)
602 {
603         conn = new eConnection(this, m_event.connect(event));
604         return 0;
605 }
606
607 static int readMpegProc(const char *str, int decoder)
608 {
609         int val = -1;
610         char tmp[64];
611         sprintf(tmp, "/proc/stb/vmpeg/%d/%s", decoder, str);
612         FILE *f = fopen(tmp, "r");
613         if (f)
614         {
615                 fscanf(f, "%x", &val);
616                 fclose(f);
617         }
618         return val;
619 }
620
621 static int readApiSize(int fd, int &xres, int &yres, int &aspect)
622 {
623 #if HAVE_DVB_API_VERSION >= 3
624         video_size_t size;
625         if (!::ioctl(fd, VIDEO_GET_SIZE, &size))
626         {
627                 xres = size.w;
628                 yres = size.h;
629                 aspect = size.aspect_ratio == 0 ? 2 : 3;  // convert dvb api to etsi
630                 return 0;
631         }
632 //      eDebug("VIDEO_GET_SIZE failed (%m)");
633 #endif
634         return -1;
635 }
636
637 static int readApiFrameRate(int fd, int &framerate)
638 {
639 #if HAVE_DVB_API_VERSION >= 3
640         unsigned int frate;
641         if (!::ioctl(fd, VIDEO_GET_FRAME_RATE, &frate))
642         {
643                 framerate = frate;      
644                 return 0;
645         }
646 //      eDebug("VIDEO_GET_FRAME_RATE failed (%m)");
647 #endif
648         return -1;
649 }
650
651 int eDVBVideo::getWidth()
652 {
653         if (m_width == -1)
654                 readApiSize(m_fd, m_width, m_height, m_aspect);
655         if (m_width == -1)
656                 m_width = readMpegProc("xres", m_dev);
657         return m_width;
658 }
659
660 int eDVBVideo::getHeight()
661 {
662         if (m_height == -1)
663                 readApiSize(m_fd, m_width, m_height, m_aspect);
664         if (m_height == -1)
665                 m_height = readMpegProc("yres", m_dev);
666         return m_height;
667 }
668
669 int eDVBVideo::getAspect()
670 {
671         if (m_aspect == -1)
672                 readApiSize(m_fd, m_width, m_height, m_aspect);
673         if (m_aspect == -1)
674                 m_aspect = readMpegProc("aspect", m_dev);
675         return m_aspect;
676 }
677
678 int eDVBVideo::getProgressive()
679 {
680         if (m_progressive == -1)
681                 m_progressive = readMpegProc("progressive", m_dev);
682         return m_progressive;
683 }
684
685 int eDVBVideo::getFrameRate()
686 {
687         if (m_framerate == -1)
688                 readApiFrameRate(m_fd, m_framerate);
689         if (m_framerate == -1)
690                 m_framerate = readMpegProc("framerate", m_dev);
691         return m_framerate;
692 }
693
694 DEFINE_REF(eDVBPCR);
695
696 eDVBPCR::eDVBPCR(eDVBDemux *demux, int dev): m_demux(demux), m_dev(dev)
697 {
698         char filename[128];
699 #if HAVE_DVB_API_VERSION < 3
700         sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
701 #else
702         sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
703 #endif
704         m_fd_demux = ::open(filename, O_RDWR);
705         if (m_fd_demux < 0)
706                 eWarning("%s: %m", filename);
707 }
708
709 #if HAVE_DVB_API_VERSION < 3
710 int eDVBPCR::setPid(int pid)
711 {
712         if (m_fd_demux < 0)
713                 return -1;
714         dmx_pes_filter_params pes;
715
716         pes.pid      = pid;
717         pes.input    = DMX_IN_FRONTEND;
718         pes.output   = DMX_OUT_DECODER;
719         pes.pes_type = DMX_PES_PCR;
720         pes.flags    = 0;
721
722         eDebugNoNewLine("DMX_SET_PES_FILTER(0x%02x) - pcr - ", pid);
723         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
724         {
725                 eDebug("failed (%m)");
726                 return -errno;
727         }
728         eDebug("ok");
729         return 0;
730 }
731
732 int eDVBPCR::startPid()
733 {
734         if (m_fd_demux < 0)
735                 return -1;
736         eDebugNoNewLine("DEMUX_START - pcr - ");
737         if (::ioctl(m_fd_demux, DMX_START) < 0)
738         {
739                 eDebug("failed (%m)");
740                 return -errno;
741         }
742         eDebug("ok");
743         return 0;
744 }
745 #else
746 int eDVBPCR::startPid(int pid)
747 {
748         if (m_fd_demux < 0)
749                 return -1;
750         dmx_pes_filter_params pes;
751
752         pes.pid      = pid;
753         pes.input    = DMX_IN_FRONTEND;
754         pes.output   = DMX_OUT_DECODER;
755         pes.pes_type = m_dev ? DMX_PES_PCR1 : DMX_PES_PCR0; /* FIXME */
756         pes.flags    = 0;
757         eDebugNoNewLine("DMX_SET_PES_FILTER(0x%02x) - pcr - ", pid);
758         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
759         {
760                 eDebug("failed (%m)");
761                 return -errno;
762         }
763         eDebug("ok");
764         eDebugNoNewLine("DEMUX_START - pcr - ");
765         if (::ioctl(m_fd_demux, DMX_START) < 0)
766         {
767                 eDebug("failed (%m)");
768                 return -errno;
769         }
770         eDebug("ok");
771         return 0;
772 }
773 #endif
774
775 void eDVBPCR::stop()
776 {
777         eDebugNoNewLine("DEMUX_STOP - pcr - ");
778         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
779                 eDebug("failed(%m)");
780         else
781                 eDebug("ok");
782 }
783
784 eDVBPCR::~eDVBPCR()
785 {
786         if (m_fd_demux >= 0)
787                 ::close(m_fd_demux);
788 }
789
790 DEFINE_REF(eDVBTText);
791
792 eDVBTText::eDVBTText(eDVBDemux *demux, int dev)
793     :m_demux(demux), m_dev(dev)
794 {
795         char filename[128];
796 #if HAVE_DVB_API_VERSION < 3
797         sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
798 #else
799         sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
800 #endif
801         m_fd_demux = ::open(filename, O_RDWR);
802         if (m_fd_demux < 0)
803                 eWarning("%s: %m", filename);
804 }
805
806 int eDVBTText::startPid(int pid)
807 {
808         if (m_fd_demux < 0)
809                 return -1;
810         dmx_pes_filter_params pes;
811
812         pes.pid      = pid;
813         pes.input    = DMX_IN_FRONTEND;
814         pes.output   = DMX_OUT_DECODER;
815         pes.pes_type = m_dev ? DMX_PES_TELETEXT1 : DMX_PES_TELETEXT0; // FIXME
816         pes.flags    = 0;
817
818         eDebugNoNewLine("DMX_SET_PES_FILTER(0x%02x) - ttx - ", pid);
819         if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
820         {
821                 eDebug("failed(%m)");
822                 return -errno;
823         }
824         eDebug("ok");
825         eDebugNoNewLine("DEMUX_START - ttx - ");
826         if (::ioctl(m_fd_demux, DMX_START) < 0)
827         {
828                 eDebug("failed(%m)");
829                 return -errno;
830         }
831         eDebug("ok");
832         return 0;
833 }
834
835 void eDVBTText::stop()
836 {
837         eDebugNoNewLine("DEMUX_STOP - ttx - ");
838         if (::ioctl(m_fd_demux, DMX_STOP) < 0)
839                 eDebug("failed(%m)");
840         else
841                 eDebug("ok");
842 }
843
844 eDVBTText::~eDVBTText()
845 {
846         if (m_fd_demux >= 0)
847                 ::close(m_fd_demux);
848 }
849
850 DEFINE_REF(eTSMPEGDecoder);
851
852 int eTSMPEGDecoder::setState()
853 {
854         int res = 0;
855
856         int noaudio = (m_state != statePlay) && (m_state != statePause);
857         int nott = noaudio; /* actually same conditions */
858
859         if ((noaudio && m_audio) || (!m_audio && !noaudio))
860                 m_changed |= changeAudio | changeState;
861
862         if ((nott && m_text) || (!m_text && !nott))
863                 m_changed |= changeText | changeState;
864
865         const char *decoder_states[] = {"stop", "pause", "play", "decoderfastforward", "trickmode", "slowmotion"};
866         eDebug("decoder state: %s, vpid=%d, apid=%d", decoder_states[m_state], m_vpid, m_apid);
867
868         int changed = m_changed;
869 #if HAVE_DVB_API_VERSION < 3
870         bool checkAVSync = m_changed & (changeAudio|changeVideo|changePCR);
871         if (m_changed & changeAudio && m_audio)
872                 m_audio->stopPid();
873         if (m_changed & changeVideo && m_video)
874                 m_video->stopPid();
875         if (m_changed & changePCR && m_pcr)
876         {
877                 m_pcr->stop();
878                 m_pcr=0;
879                 if (!(m_pcrpid >= 0 && m_pcrpid < 0x1ff))
880                         m_changed &= ~changePCR;
881         }
882         if (m_changed & changeAudio && m_audio)
883         {
884                 m_audio->stop();
885                 m_audio=0;
886                 if (!(m_apid >= 0 && m_apid < 0x1ff))
887                         m_changed &= ~changeAudio;
888         }
889         if (m_changed & changeVideo && m_video)
890         {
891                 m_video->stop();
892                 m_video=0;
893                 m_video_event_conn=0;
894                 if (!(m_vpid >= 0 && m_vpid < 0x1ff))
895                         m_changed &= ~changeVideo;
896         }
897         if (m_changed & changeVideo)
898         {
899                 m_video = new eDVBVideo(m_demux, m_decoder);
900                 m_video->connectEvent(slot(*this, &eTSMPEGDecoder::video_event), m_video_event_conn);
901                 if (m_video->setPid(m_vpid))
902                         res -1;
903         }
904         if (m_changed & changePCR)
905         {
906                 m_pcr = new eDVBPCR(m_demux, m_decoder);
907                 if (m_pcr->setPid(m_pcrpid))
908                         res = -1;
909         }
910         if (m_changed & changeAudio)
911         {
912                 m_audio = new eDVBAudio(m_demux, m_decoder);
913                 if (m_audio->setPid(m_apid, m_atype))
914                         res = -1;
915         }
916         if (m_changed & changePCR)
917         {
918                 if (m_pcr->startPid())
919                         res = -1;
920                 m_changed &= ~changePCR;
921         }
922         else if (checkAVSync && m_audio && m_video)
923         {
924                 if (m_audio->setAVSync(1))
925                         res = -1;
926         }
927         if (m_changed & changeVideo)
928         {
929                 if (m_video->startPid() || m_video->start())
930                         res = -1;
931                 m_changed &= ~changeVideo;
932         }
933         if (m_changed & changeAudio)
934         {
935                 if (m_audio->start() || m_audio->startPid())
936                         res = -1;
937                 m_changed &= ~changeAudio;
938         }
939 #else
940         if (m_changed & changePCR)
941         {
942                 if (m_pcr)
943                         m_pcr->stop();
944                 m_pcr = 0;
945         }
946         if (m_changed & changeVideo)
947         {
948                 if (m_video)
949                 {
950                         m_video->stop();
951                         m_video = 0;
952                         m_video_event_conn = 0;
953                 }
954         }
955         if (m_changed & changeAudio)
956         {
957                 if (m_audio)
958                         m_audio->stop();
959                 m_audio = 0;
960         }
961         if (m_changed & changeText)
962         {
963                 if (m_text)
964                         m_text->stop();
965                 m_text = 0;
966         }
967         if (m_changed & changePCR)
968         {
969                 if ((m_pcrpid >= 0) && (m_pcrpid < 0x1FFF))
970                 {
971                         m_pcr = new eDVBPCR(m_demux, m_decoder);
972                         if (m_pcr->startPid(m_pcrpid))
973                                 res = -1;
974                 }
975                 m_changed &= ~changePCR;
976         }
977         if (m_changed & changeAudio)
978         {
979                 if ((m_apid >= 0) && (m_apid < 0x1FFF) && !noaudio)
980                 {
981                         m_audio = new eDVBAudio(m_demux, m_decoder);
982                         if (m_audio->startPid(m_apid, m_atype))
983                                 res = -1;
984                 }
985                 m_changed &= ~changeAudio;
986         }
987         if (m_changed & changeVideo)
988         {
989                 if ((m_vpid >= 0) && (m_vpid < 0x1FFF))
990                 {
991                         m_video = new eDVBVideo(m_demux, m_decoder);
992                         m_video->connectEvent(slot(*this, &eTSMPEGDecoder::video_event), m_video_event_conn);
993                         if (m_video->startPid(m_vpid, m_vtype))
994                                 res = -1;
995                 }
996                 m_changed &= ~changeVideo;
997         }
998         if (m_changed & changeText)
999         {
1000                 if ((m_textpid >= 0) && (m_textpid < 0x1FFF) && !nott)
1001                 {
1002                         m_text = new eDVBTText(m_demux, m_decoder);
1003                         if (m_text->startPid(m_textpid))
1004                                 res = -1;
1005                 }
1006                 m_changed &= ~changeText;
1007         }
1008 #endif
1009
1010         if (changed & (changeState|changeVideo|changeAudio))
1011         {
1012                                         /* play, slowmotion, fast-forward */
1013                 int state_table[6][4] = 
1014                         {
1015                                 /* [stateStop] =                 */ {0, 0, 0},
1016                                 /* [statePause] =                */ {0, 0, 0},
1017                                 /* [statePlay] =                 */ {1, 0, 0},
1018                                 /* [stateDecoderFastForward] =   */ {1, 0, m_ff_sm_ratio},
1019                                 /* [stateHighspeedFastForward] = */ {1, 0, 1},
1020                                 /* [stateSlowMotion] =           */ {1, m_ff_sm_ratio, 0}
1021                         };
1022                 int *s = state_table[m_state];
1023                 if (changed & (changeState|changeVideo) && m_video)
1024                 {
1025                         m_video->setSlowMotion(s[1]);
1026                         m_video->setFastForward(s[2]);
1027                         if (s[0])
1028                                 m_video->unfreeze();
1029                         else
1030                                 m_video->freeze();
1031                 }
1032                 if (changed & (changeState|changeAudio) && m_audio)
1033                 {
1034                         if (s[0])
1035                                 m_audio->unfreeze();
1036                         else
1037                                 m_audio->freeze();
1038                 }
1039                 m_changed &= ~changeState;
1040         }
1041
1042         if (changed && !m_video && m_audio && m_radio_pic.length())
1043                 showSinglePic(m_radio_pic.c_str());
1044
1045         return res;
1046 }
1047
1048 int eTSMPEGDecoder::m_pcm_delay=-1,
1049         eTSMPEGDecoder::m_ac3_delay=-1;
1050
1051 RESULT eTSMPEGDecoder::setHwPCMDelay(int delay)
1052 {
1053         if (delay != m_pcm_delay )
1054         {
1055                 FILE *fp = fopen("/proc/stb/audio/audio_delay_pcm", "w");
1056                 if (fp)
1057                 {
1058                         fprintf(fp, "%x", delay*90);
1059                         fclose(fp);
1060                         m_pcm_delay = delay;
1061                         return 0;
1062                 }
1063         }
1064         return -1;
1065 }
1066
1067 RESULT eTSMPEGDecoder::setHwAC3Delay(int delay)
1068 {
1069         if ( delay != m_ac3_delay )
1070         {
1071                 FILE *fp = fopen("/proc/stb/audio/audio_delay_bitstream", "w");
1072                 if (fp)
1073                 {
1074                         fprintf(fp, "%x", delay*90);
1075                         fclose(fp);
1076                         m_ac3_delay = delay;
1077                         return 0;
1078                 }
1079         }
1080         return -1;
1081 }
1082
1083
1084 RESULT eTSMPEGDecoder::setPCMDelay(int delay)
1085 {
1086         return m_decoder == 0 ? setHwPCMDelay(delay) : -1;
1087 }
1088
1089 RESULT eTSMPEGDecoder::setAC3Delay(int delay)
1090 {
1091         return m_decoder == 0 ? setHwAC3Delay(delay) : -1;
1092 }
1093
1094 eTSMPEGDecoder::eTSMPEGDecoder(eDVBDemux *demux, int decoder)
1095         : m_demux(demux), 
1096                 m_vpid(-1), m_vtype(-1), m_apid(-1), m_atype(-1), m_pcrpid(-1), m_textpid(-1),
1097                 m_changed(0), m_decoder(decoder), m_video_clip_fd(-1), m_showSinglePicTimer(eTimer::create(eApp))
1098 {
1099         demux->connectEvent(slot(*this, &eTSMPEGDecoder::demux_event), m_demux_event_conn);
1100         CONNECT(m_showSinglePicTimer->timeout, eTSMPEGDecoder::finishShowSinglePic);
1101         m_state = stateStop;
1102 }
1103
1104 eTSMPEGDecoder::~eTSMPEGDecoder()
1105 {
1106         finishShowSinglePic();
1107         m_vpid = m_apid = m_pcrpid = m_textpid = pidNone;
1108         m_changed = -1;
1109         setState();
1110 }
1111
1112 RESULT eTSMPEGDecoder::setVideoPID(int vpid, int type)
1113 {
1114         if ((m_vpid != vpid) || (m_vtype != type))
1115         {
1116                 m_changed |= changeVideo;
1117                 m_vpid = vpid;
1118                 m_vtype = type;
1119         }
1120         return 0;
1121 }
1122
1123 RESULT eTSMPEGDecoder::setAudioPID(int apid, int type)
1124 {
1125         if ((m_apid != apid) || (m_atype != type))
1126         {
1127                 m_changed |= changeAudio;
1128                 m_atype = type;
1129                 m_apid = apid;
1130         }
1131         return 0;
1132 }
1133
1134 int eTSMPEGDecoder::m_audio_channel = -1;
1135
1136 RESULT eTSMPEGDecoder::setAudioChannel(int channel)
1137 {
1138         if (channel == -1)
1139                 channel = ac_stereo;
1140         if (m_decoder == 0 && m_audio_channel != channel)
1141         {
1142                 if (m_audio)
1143                 {
1144                         m_audio->setChannel(channel);
1145                         m_audio_channel=channel;
1146                 }
1147                 else
1148                         eDebug("eTSMPEGDecoder::setAudioChannel but no audio decoder exist");
1149         }
1150         return 0;
1151 }
1152
1153 int eTSMPEGDecoder::getAudioChannel()
1154 {
1155         return m_audio_channel == -1 ? ac_stereo : m_audio_channel;
1156 }
1157
1158 RESULT eTSMPEGDecoder::setSyncPCR(int pcrpid)
1159 {
1160         if (m_pcrpid != pcrpid)
1161         {
1162                 m_changed |= changePCR;
1163                 m_pcrpid = pcrpid;
1164         }
1165         return 0;
1166 }
1167
1168 RESULT eTSMPEGDecoder::setTextPID(int textpid)
1169 {
1170         if (m_textpid != textpid)
1171         {
1172                 m_changed |= changeText;
1173                 m_textpid = textpid;
1174         }
1175         return 0;
1176 }
1177
1178 RESULT eTSMPEGDecoder::setSyncMaster(int who)
1179 {
1180         return -1;
1181 }
1182
1183 RESULT eTSMPEGDecoder::set()
1184 {
1185         return setState();
1186 }
1187
1188 RESULT eTSMPEGDecoder::play()
1189 {
1190         if (m_state == statePlay)
1191         {
1192                 if (!m_changed)
1193                         return 0;
1194         } else  
1195         {
1196                 m_state = statePlay;
1197                 m_changed |= changeState;
1198         }
1199         return setState();
1200 }
1201
1202 RESULT eTSMPEGDecoder::pause()
1203 {
1204         if (m_state == statePause)
1205                 return 0;
1206         m_state = statePause;
1207         m_changed |= changeState;
1208         return setState();
1209 }
1210
1211 RESULT eTSMPEGDecoder::setFastForward(int frames_to_skip)
1212 {
1213         if ((m_state == stateDecoderFastForward) && (m_ff_sm_ratio == frames_to_skip))
1214                 return 0;
1215
1216         m_state = stateDecoderFastForward;
1217         m_ff_sm_ratio = frames_to_skip;
1218         m_changed |= changeState;
1219         return setState();
1220
1221 //              return m_video->setFastForward(frames_to_skip);
1222 }
1223
1224 RESULT eTSMPEGDecoder::setSlowMotion(int repeat)
1225 {
1226         if ((m_state == stateSlowMotion) && (m_ff_sm_ratio == repeat))
1227                 return 0;
1228
1229         m_state = stateSlowMotion;
1230         m_ff_sm_ratio = repeat;
1231         m_changed |= changeState;
1232         return setState();
1233 }
1234
1235 RESULT eTSMPEGDecoder::setTrickmode()
1236 {
1237         if (m_state == stateTrickmode)
1238                 return 0;
1239
1240         m_state = stateTrickmode;
1241         m_changed |= changeState;
1242         return setState();
1243 }
1244
1245 RESULT eTSMPEGDecoder::flush()
1246 {
1247         if (m_audio)
1248                 m_audio->flush();
1249         if (m_video)
1250                 m_video->flush();
1251         return 0;
1252 }
1253
1254 void eTSMPEGDecoder::demux_event(int event)
1255 {
1256         switch (event)
1257         {
1258         case eDVBDemux::evtFlush:
1259                 flush();
1260                 break;
1261         default:
1262                 break;
1263         }
1264 }
1265
1266 RESULT eTSMPEGDecoder::getPTS(int what, pts_t &pts)
1267 {
1268         if (what == 0) /* auto */
1269                 what = m_video ? 1 : 2;
1270
1271         if (what == 1) /* video */
1272         {
1273                 if (m_video)
1274                         return m_video->getPTS(pts);
1275                 else
1276                         return -1;
1277         }
1278
1279         if (what == 2) /* audio */
1280         {
1281                 if (m_audio)
1282                         return m_audio->getPTS(pts);
1283                 else
1284                         return -1;
1285         }
1286
1287         return -1;
1288 }
1289
1290 RESULT eTSMPEGDecoder::setRadioPic(const std::string &filename)
1291 {
1292         m_radio_pic = filename;
1293         return 0;
1294 }
1295
1296 RESULT eTSMPEGDecoder::showSinglePic(const char *filename)
1297 {
1298         if (m_decoder == 0)
1299         {
1300                 eDebug("showSinglePic %s", filename);
1301                 int f = open(filename, O_RDONLY);
1302                 if (f >= 0)
1303                 {
1304                         struct stat s;
1305                         fstat(f, &s);
1306                         if (m_video_clip_fd == -1)
1307                                 m_video_clip_fd = open("/dev/dvb/adapter0/video0", O_WRONLY|O_NONBLOCK);
1308                         if (m_video_clip_fd >= 0)
1309                         {
1310                                 bool seq_end_avail = false;
1311                                 size_t pos=0;
1312                                 unsigned char pes_header[] = { 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x80, 0x00, 0x00 };
1313                                 unsigned char seq_end[] = { 0x00, 0x00, 0x01, 0xB7 };
1314                                 unsigned char iframe[s.st_size];
1315                                 unsigned char stuffing[8192];
1316                                 int streamtype = VIDEO_STREAMTYPE_MPEG2;
1317                                 memset(stuffing, 0, 8192);
1318                                 read(f, iframe, s.st_size);
1319                                 if (ioctl(m_video_clip_fd, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY) < 0)
1320                                         eDebug("VIDEO_SELECT_SOURCE MEMORY failed (%m)");
1321                                 if (ioctl(m_video_clip_fd, VIDEO_SET_STREAMTYPE, streamtype) < 0)
1322                                         eDebug("VIDEO_SET_STREAMTYPE failed(%m)");
1323                                 if (ioctl(m_video_clip_fd, VIDEO_PLAY) < 0)
1324                                         eDebug("VIDEO_PLAY failed (%m)");
1325                                 if (ioctl(m_video_clip_fd, VIDEO_CONTINUE) < 0)
1326                                         eDebug("video: VIDEO_CONTINUE: %m");
1327                                 if (ioctl(m_video_clip_fd, VIDEO_CLEAR_BUFFER) < 0)
1328                                         eDebug("video: VIDEO_CLEAR_BUFFER: %m");
1329                                 while(pos <= (s.st_size-4) && !(seq_end_avail = (!iframe[pos] && !iframe[pos+1] && iframe[pos+2] == 1 && iframe[pos+3] == 0xB7)))
1330                                         ++pos;
1331                                 if ((iframe[3] >> 4) != 0xE) // no pes header
1332                                         write(m_video_clip_fd, pes_header, sizeof(pes_header));
1333                                 else
1334                                         iframe[4] = iframe[5] = 0x00;
1335                                 write(m_video_clip_fd, iframe, s.st_size);
1336                                 if (!seq_end_avail)
1337                                         write(m_video_clip_fd, seq_end, sizeof(seq_end));
1338                                 write(m_video_clip_fd, stuffing, 8192);
1339                                 m_showSinglePicTimer->start(150, true);
1340                         }
1341                         close(f);
1342                 }
1343                 else
1344                 {
1345                         eDebug("couldnt open %s", filename);
1346                         return -1;
1347                 }
1348         }
1349         else
1350         {
1351                 eDebug("only show single pics on first decoder");
1352                 return -1;
1353         }
1354         return 0;
1355 }
1356
1357 void eTSMPEGDecoder::finishShowSinglePic()
1358 {
1359         if (m_video_clip_fd >= 0)
1360         {
1361                 if (ioctl(m_video_clip_fd, VIDEO_STOP, 0) < 0)
1362                         eDebug("VIDEO_STOP failed (%m)");
1363                 if (ioctl(m_video_clip_fd, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX) < 0)
1364                                 eDebug("VIDEO_SELECT_SOURCE DEMUX failed (%m)");
1365                 close(m_video_clip_fd);
1366                 m_video_clip_fd = -1;
1367         }
1368 }
1369
1370 RESULT eTSMPEGDecoder::connectVideoEvent(const Slot1<void, struct videoEvent> &event, ePtr<eConnection> &conn)
1371 {
1372         conn = new eConnection(this, m_video_event.connect(event));
1373         return 0;
1374 }
1375
1376 void eTSMPEGDecoder::video_event(struct videoEvent event)
1377 {
1378         /* emit */ m_video_event(event);
1379 }
1380
1381 int eTSMPEGDecoder::getVideoWidth()
1382 {
1383         if (m_video)
1384                 return m_video->getWidth();
1385         return -1;
1386 }
1387
1388 int eTSMPEGDecoder::getVideoHeight()
1389 {
1390         if (m_video)
1391                 return m_video->getHeight();
1392         return -1;
1393 }
1394
1395 int eTSMPEGDecoder::getVideoProgressive()
1396 {
1397         if (m_video)
1398                 return m_video->getProgressive();
1399         return -1;
1400 }
1401
1402 int eTSMPEGDecoder::getVideoFrameRate()
1403 {
1404         if (m_video)
1405                 return m_video->getFrameRate();
1406         return -1;
1407 }
1408
1409 int eTSMPEGDecoder::getVideoAspect()
1410 {
1411         if (m_video)
1412                 return m_video->getAspect();
1413         return -1;
1414 }