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