Support turbo2.
[vuplus_dvbapp] / lib / service / servicedvbfcc.cpp
1 #include <lib/service/servicedvbfcc.h>
2 #include <lib/components/file_eraser.h>
3 #include <lib/dvb/decoder.h>
4 #include <lib/base/nconfig.h>
5
6 eDVBServiceFCCPlay::eDVBServiceFCCPlay(const eServiceReference &ref, eDVBService *service)
7         :eDVBServicePlay(ref, service, false), m_fcc_flag(0), m_fcc_mode(fcc_mode_preparing), m_fcc_mustplay(false),
8                 m_pmtVersion(-1), m_normal_decoding(false)
9 {
10         CONNECT(m_service_handler.serviceEvent, eDVBServiceFCCPlay::serviceEvent);
11 }
12
13 eDVBServiceFCCPlay::~eDVBServiceFCCPlay()
14 {
15 }
16
17 void eDVBServiceFCCPlay::serviceEvent(int event)
18 {
19         if (!m_is_primary) // PIP mode
20         {
21                 eDVBServicePlay::serviceEvent(event);
22                 return;
23         }
24
25         m_tune_state = event;
26
27         switch (event)
28         {
29                 case eDVBServicePMTHandler::eventTuned:
30                 {
31                         eDVBServicePlay::serviceEvent(event);
32                         pushbackFCCEvents(evTunedIn);
33                         break;
34                 }
35                 case eDVBServicePMTHandler::eventNoResources:
36                 case eDVBServicePMTHandler::eventNoPAT:
37                 case eDVBServicePMTHandler::eventNoPATEntry:
38                 case eDVBServicePMTHandler::eventNoPMT:
39                 case eDVBServicePMTHandler::eventTuneFailed:
40                 case eDVBServicePMTHandler::eventMisconfiguration:
41                 {
42                         eDVBServicePlay::serviceEvent(event);
43                         pushbackFCCEvents(evTuneFailed);
44                         break;
45                 }
46                 case eDVBServicePMTHandler::eventChannelAllocated:
47                 {
48                         bool is_usb_tuner = checkUsbTuner();
49                         bool fcc_state_decoding = getFCCStateDecoding();
50                         int slotId = getFrontendInfo(iDVBFrontend_ENUMS::frontendNumber);
51
52                         if (is_usb_tuner)
53                         {
54                                 if (fcc_state_decoding)
55                                 {
56                                         m_normal_decoding = true;
57                                         setNormalDecoding();
58                                 }
59                                 else
60                                 {
61                                         eDVBServicePlay::serviceEvent(eDVBServicePMTHandler::eventTuneFailed);
62                                         pushbackFCCEvents(evTuneFailed);
63                                 }
64                         }
65                         break;
66                 }
67                 case eDVBServicePMTHandler::eventNewProgramInfo:
68                 {
69                         if (m_fcc_flag & fcc_tune_failed)
70                                 return;
71
72                         eDebug("eventNewProgramInfo %d %d %d", m_timeshift_enabled, m_timeshift_active, m_normal_decoding);
73                         if (m_normal_decoding)
74                         {
75                                 eDVBServicePlay::serviceEvent(event);
76                         }
77                         else
78                         {
79                                 if (m_timeshift_enabled)
80                                 updateTimeshiftPids();
81
82                                 if (!m_timeshift_active)
83                                         processNewProgramInfo();
84
85                                 if (!m_timeshift_active)
86                                 {
87                                         m_event((iPlayableService*)this, evUpdatedInfo);
88                                         pushbackFCCEvents(evUpdatedInfo);
89                                 }
90                         }
91                         break;
92                 }
93                 case eDVBServicePMTHandler::eventPreStart:
94                 case eDVBServicePMTHandler::eventEOF:
95                 case eDVBServicePMTHandler::eventSOF:
96                 {
97                         eDVBServicePlay::serviceEvent(event);
98                         break;
99                 }
100                 case eDVBServicePMTHandler::eventHBBTVInfo:
101                 {
102                         eDVBServicePlay::serviceEvent(event);
103                         pushbackFCCEvents(evHBBTVInfo);
104                         break;
105                 }
106         }
107 }
108
109 RESULT eDVBServiceFCCPlay::start()
110 {
111         if (!m_is_primary) // PIP mode
112         {
113                 eDVBServicePlay::start();
114                 return 0;
115         }
116
117         if (m_fcc_flag & fcc_start) // already started
118         {
119                 changeFCCMode();
120         }
121         else
122         {
123                 m_fcc_flag |= fcc_start;
124                 pushbackFCCEvents(evStart);
125
126                 /* disable CA Interfaces on fcc_mode_preparing */
127                 m_service_handler.setCaDisable(true);
128                 eDVBServicePlay::start();
129         }
130         return 0;
131 }
132
133 void eDVBServiceFCCPlay::pushbackFCCEvents(int event)
134 {
135         if (event == evTuneFailed)
136                 m_fcc_flag |= fcc_tune_failed;
137         m_fcc_events.push_back(event);
138 }
139
140 void eDVBServiceFCCPlay::popFCCEvents()
141 {
142         m_fcc_events.unique(); // remove duplicate evUpdatedInfo
143         for (std::list<int>::iterator it = m_fcc_events.begin(); it != m_fcc_events.end(); ++it)
144         {
145                 if (*it == evUpdatedInfo)
146                 {
147                         updateFCCDecoder();
148                         break;
149                 }
150         }
151
152         /* add CaHandler */
153         m_service_handler.addCaHandler();
154
155         /* send events */
156         for (std::list<int>::iterator it = m_fcc_events.begin(); it != m_fcc_events.end(); ++it)
157         {
158                 int event = *it;
159                 m_event((iPlayableService*)this, event);
160         }
161 }
162
163 void eDVBServiceFCCPlay::changeFCCMode()
164 {
165         if (m_fcc_mode == fcc_mode_decoding)
166         {
167                 eDebug("[eDVBServiceFCCPlay::changeFCCMode][%s] disable FCC decoding.", m_reference.toString().c_str());
168                 m_fcc_mode = fcc_mode_preparing;
169
170                 /* stop timeshift */
171                 eDVBServicePlay::stopTimeshift();
172
173                 /* remove CaHandler */
174                 m_service_handler.removeCaHandler();
175
176                 if (m_fcc_flag & fcc_tune_failed)
177                         m_event((iPlayableService*)this, evTuneFailed);
178
179                 else if (m_fcc_flag & fcc_failed)
180                         m_event((iPlayableService*)this, evFccFailed);
181
182                 FCCDecoderStop();
183         }
184         else
185         {
186                 eDebug("[eDVBServiceFCCPlay::changeFCCMode][%s] enable FCC decoding.", m_reference.toString().c_str());
187                 m_fcc_mode = fcc_mode_decoding;
188                 popFCCEvents();
189         }
190 }
191
192 void eDVBServiceFCCPlay::processNewProgramInfo(bool toLive)
193 {
194         updateFCCDecoder(toLive);
195
196         if (m_fcc_flag & fcc_failed)
197         {
198                 m_event((iPlayableService*)this, evFccFailed);
199         }
200 }
201
202 void eDVBServiceFCCPlay::updateFCCDecoder(bool sendSeekableStateChanged)
203 {
204         eDebug("[eDVBServiceFCCPlay::updateFCCDecoder][%s]", m_reference.toString().c_str());
205         int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
206         bool isProgramInfoCached = false;
207         bool pmtVersionChanged = false;
208
209         eDVBServicePMTHandler &h = m_service_handler;
210
211         eDVBServicePMTHandler::program program;
212         if (h.getProgramInfo(program))
213                 eDebug("getting program info failed.");
214         else
215         {
216                 eDebugNoNewLine("have %zd video stream(s)", program.videoStreams.size());
217                 if (!program.videoStreams.empty())
218                 {
219                         eDebugNoNewLine(" (");
220                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
221                                 i(program.videoStreams.begin());
222                                 i != program.videoStreams.end(); ++i)
223                         {
224                                 if (vpid == -1)
225                                 {
226                                         vpid = i->pid;
227                                         vpidtype = i->type;
228                                 }
229                                 if (i != program.videoStreams.begin())
230                                         eDebugNoNewLine(", ");
231                                 eDebugNoNewLine("%04x", i->pid);
232                         }
233                         eDebugNoNewLine(")");
234                 }
235                 eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
236                 if (!program.audioStreams.empty())
237                 {
238                         eDebugNoNewLine(" (");
239                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
240                                 i(program.audioStreams.begin());
241                                 i != program.audioStreams.end(); ++i)
242                         {
243                                 if (i != program.audioStreams.begin())
244                                         eDebugNoNewLine(", ");
245                                 eDebugNoNewLine("%04x", i->pid);
246                         }
247                         eDebugNoNewLine(")");
248                 }
249                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
250                 pcrpid = program.pcrPid;
251                 eDebugNoNewLine(", and the text pid is %04x", program.textPid);
252                 tpid = program.textPid;
253                 eDebug(" %s", program.isCached ? "(Cached)":"");
254                 isProgramInfoCached = program.isCached;
255                 if (m_pmtVersion != program.pmtVersion)
256                 {
257                         if (m_pmtVersion != -1)
258                                 pmtVersionChanged = true;
259                         m_pmtVersion = program.pmtVersion;
260                         //eDebug("[eDVBServiceFCCPlay::updateFCCDecoder] pmt version : %d", m_pmtVersion);
261                 }
262         }
263
264         if (!m_decoder)
265         {
266                 h.getDecodeDemux(m_decode_demux);
267                 if (m_decode_demux)
268                 {
269                         m_decode_demux->getMPEGDecoder(m_decoder, m_decoder_index);
270                         if (m_decoder)
271                                 m_decoder->connectVideoEvent(slot(*this, &eDVBServiceFCCPlay::video_event), m_video_event_connection);
272                 }
273                 m_fcc_mustplay = true;
274         }
275
276         if (m_decoder)
277         {
278                 if (!((m_fcc_flag & fcc_ready)||(m_fcc_flag & fcc_novideo)))
279                 {
280                         if (vpid == -1)
281                         {
282                                 if (!isProgramInfoCached)
283                                         m_fcc_flag |= fcc_novideo;
284                         }
285                         else if ((vpidtype == -1) || (pcrpid== -1))
286                         {
287                                 if (!isProgramInfoCached)
288                                         m_fcc_flag |= fcc_failed;
289                         }
290                         else if (!m_decoder->prepareFCC(m_decode_demux->getSource(), vpid, vpidtype, pcrpid))
291                                 m_fcc_flag |= fcc_ready;
292                         else
293                                 m_fcc_flag |= fcc_failed;
294                 }
295                 else if (pmtVersionChanged)
296                 {
297                         m_decoder->fccUpdatePids(m_decode_demux->getSource(), vpid, vpidtype, pcrpid);
298                         m_fcc_flag &=~fcc_decoding;
299                 }
300         }
301
302         if (m_fcc_mode != fcc_mode_decoding)
303                 return;
304
305         /* fcc_mode_decoding */
306         if (!(m_fcc_flag & fcc_ready) && !(m_fcc_flag & fcc_novideo))
307         {
308                 eDebug("[eDVBServiceFCCPlay::updateFCCDecoder] fcc is not ready.");
309                 return;
310         }
311
312         if (m_decode_demux)
313         {
314                 if (m_is_primary)
315                 {
316                         m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
317                         m_teletext_parser->connectNewPage(slot(*this, &eDVBServiceFCCPlay::newSubtitlePage), m_new_subtitle_page_connection);
318                         m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
319                         m_subtitle_parser->connectNewPage(slot(*this, &eDVBServiceFCCPlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
320                         if (m_timeshift_changed)
321                         {
322                                 ePyObject subs = getCachedSubtitle();
323                                 if (subs != Py_None)
324                                 {
325                                         int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
326                                             pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
327                                             comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
328                                             anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
329                                         if (type == 0) // dvb
330                                                 m_subtitle_parser->start(pid, comp_page, anc_page);
331                                         else if (type == 1) // ttx
332                                                 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
333                                 }
334                                 Py_DECREF(subs);
335                         }
336                 }
337         }
338
339         m_timeshift_changed = 0;
340
341         if (m_decoder)
342         {
343                 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
344
345                 if (m_dvb_service)
346                 {
347                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
348                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
349                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
350                 }
351                 else // subservice
352                 {
353                         eServiceReferenceDVB ref;
354                         m_service_handler.getServiceReference(ref);
355                         eServiceReferenceDVB parent = ref.getParentServiceReference();
356                         if (!parent)
357                                 parent = ref;
358                         if (parent)
359                         {
360                                 ePtr<eDVBResourceManager> res_mgr;
361                                 if (!eDVBResourceManager::getInstance(res_mgr))
362                                 {
363                                         ePtr<iDVBChannelList> db;
364                                         if (!res_mgr->getChannelList(db))
365                                         {
366                                                 ePtr<eDVBService> origService;
367                                                 if (!db->getService(parent, origService))
368                                                 {
369                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
370                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
371                                                 }
372                                         }
373                                 }
374                         }
375                 }
376
377                 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
378                 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
379
380                 m_decoder->setVideoPID(vpid, vpidtype);
381                 selectAudioStream();
382
383                 if (!(m_is_pvr || m_is_stream || m_timeshift_active))
384                         m_decoder->setSyncPCR(pcrpid);
385                 else
386                         m_decoder->setSyncPCR(-1);
387
388                 if (m_is_primary)
389                 {
390                         m_decoder->setTextPID(tpid);
391                         m_teletext_parser->start(program.textPid);
392                 }
393
394                 if (vpid > 0 && vpid < 0x2000)
395                         ;
396                 else
397                 {
398                         std::string radio_pic;
399                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
400                                 m_decoder->setRadioPic(radio_pic);
401                 }
402
403                 /* fcc stop and decoder start */
404                 if (!(m_fcc_flag & fcc_novideo))
405                 {
406                         if (m_fcc_flag & fcc_decoding)
407                                 ;
408                         else if(!m_decoder->fccDecoderStart())
409                                 m_fcc_flag |= fcc_decoding;
410                 }
411
412                 if (m_fcc_mustplay)
413                 {
414                         m_fcc_mustplay = false;
415                         m_decoder->play();
416                 }
417                 else
418                 {
419                         m_decoder->set();
420                 }
421
422                 m_decoder->setAudioChannel(achannel);
423
424                 /* don't worry about non-existing services, nor pvr services */
425                 if (m_dvb_service)
426                 {
427                                 /* (audio pid will be set in selectAudioTrack */
428                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
429                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
430                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
431                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
432                 }
433                 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
434                         sendSeekableStateChanged = true;
435         }
436         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
437
438         if (sendSeekableStateChanged)
439                 m_event((iPlayableService*)this, evSeekableStatusChanged);
440 }
441
442 void eDVBServiceFCCPlay::FCCDecoderStop()
443 {
444         eDebug("[eDVBServiceFCCPlay::FCCDecoderStop][%s]", m_reference.toString().c_str());
445
446         if (m_decoder)
447         {
448                 m_teletext_parser = 0;
449                 m_new_subtitle_page_connection = 0;
450                 m_subtitle_parser = 0;
451                 m_new_dvb_subtitle_page_connection = 0;
452
453                 if (m_fcc_flag & fcc_ready)
454                 {
455                         m_decoder->fccDecoderStop();
456                         m_fcc_flag &=~fcc_decoding;
457                 }
458                 else if (m_fcc_flag & fcc_novideo)
459                 {
460                         m_video_event_connection = 0;
461                         m_decoder = 0;
462                 }
463         }
464 }
465
466 void eDVBServiceFCCPlay::switchToLive()
467 {
468         if (!m_timeshift_active)
469                 return;
470
471         eDebug("eDVBServiceFCCPlay::SwitchToLive");
472
473         resetTimeshift(0);
474
475         m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
476
477         /* free the timeshift service handler, we need the resources */
478         m_service_handler_timeshift.free();
479
480         m_fcc_flag &=~fcc_ready;
481         m_fcc_flag &=~fcc_decoding;
482         processNewProgramInfo(true);
483 }
484
485 bool eDVBServiceFCCPlay::checkUsbTuner()
486 {
487         return (bool)getFrontendInfo(iDVBFrontend_ENUMS::isUsbTuner);
488 }
489
490 bool eDVBServiceFCCPlay::getFCCStateDecoding()
491 {
492         eFCCServiceManager *fcc_service_mgr = eFCCServiceManager::getInstance();
493         return fcc_service_mgr->isStateDecoding((iPlayableService*)this);
494 }
495
496 void eDVBServiceFCCPlay::setNormalDecoding()
497 {
498         eFCCServiceManager *fcc_service_mgr = eFCCServiceManager::getInstance();
499         return fcc_service_mgr->setNormalDecoding((iPlayableService*)this);
500 }
501
502 DEFINE_REF(eDVBServiceFCCPlay)
503