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