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