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