Support fast channel change.
[vuplus_dvbapp] / lib / service / servicedvb.cpp
index 1bd8e65..c3abb81 100755 (executable)
@@ -19,6 +19,8 @@
 #include <lib/base/nconfig.h> // access to python config
 #include <lib/base/httpstream.h>
 
+#include <lib/service/servicedvbfcc.h>
+
                /* for subtitles */
 #include <lib/gui/esubtitle.h>
 
@@ -28,6 +30,8 @@
 #include <byteswap.h>
 #include <netinet/in.h>
 
+#include <lib/dvb/fcc.h>
+
 #ifndef BYTE_ORDER
 #error no byte order defined!
 #endif
@@ -814,11 +818,15 @@ RESULT eDVBServiceList::setListName(const std::string &name)
 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
 {
        ePtr<eDVBService> service;
+
        int r = lookupService(service, ref);
        if (r)
                service = 0;
                // check resources...
-       ptr = new eDVBServicePlay(ref, service);
+       if (eFCCServiceManager::checkAvailable(ref))
+               ptr = new eDVBServiceFCCPlay(ref, service);
+       else
+               ptr = new eDVBServicePlay(ref, service);
        return 0;
 }
 
@@ -933,17 +941,19 @@ RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServ
        return 0;
 }
 
-eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
+eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service, bool connect_event):
        m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
 {
        m_is_primary = 1;
        m_is_stream = m_reference.path.substr(0, 7) == "http://";
        m_is_pvr = (!m_reference.path.empty() && !m_is_stream);
-       
+
        m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
        m_skipmode = m_fastforward = m_slowmotion = 0;
-       
-       CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
+
+       if (connect_event)
+               CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
+
        CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
        CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
 
@@ -956,6 +966,8 @@ eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *serv
 
        m_subtitle_sync_timer = eTimer::create(eApp);
 
+       m_current_video_pid_type = 0;
+
        CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
 }
 
@@ -1324,7 +1336,18 @@ RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
        {
                eDebug("setting cue skipmode to %d", skipmode);
                if (m_cue)
-                       m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
+               {
+                       long long _skipmode = skipmode;
+                       if (m_current_video_pid_type == eDVBServicePMTHandler::videoStream::vtH265_HEVC)
+                       {
+                               if (ratio < 0)
+                                       _skipmode = skipmode * 3;
+                               else
+                                       _skipmode = skipmode * 4;
+                       }
+
+                       m_cue->setSkipmode(_skipmode * 90000); /* convert to 90000 per second */
+               }
        }
 
        m_skipmode = skipmode;
@@ -1716,12 +1739,21 @@ int eDVBServicePlay::getInfo(int w)
        case sAudioPID:
                if (m_dvb_service)
                {
-                       int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
+                       int apid = m_dvb_service->getCacheEntry(eDVBService::cMPEGAPID);
                        if (apid != -1)
                                return apid;
                        apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
                        if (apid != -1)
                                return apid;
+                       apid = m_dvb_service->getCacheEntry(eDVBService::cDDPPID);
+                       if (apid != -1)
+                               return apid;
+                       apid = m_dvb_service->getCacheEntry(eDVBService::cAACHEAPID);
+                       if (apid != -1)
+                               return apid;
+                       apid = m_dvb_service->getCacheEntry(eDVBService::cAACAPID);
+                       if (apid != -1)
+                               return apid;
                }
                if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
        case sPCRPID:
@@ -1953,23 +1985,17 @@ int eDVBServicePlay::selectAudioStream(int i)
                                    case the real default is not yet available.)
                        */
        if (m_dvb_service && ((i != -1)
-               || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
+               || ((m_dvb_service->getCacheEntry(eDVBService::cMPEGAPID) == -1)
+               && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1)
+               && (m_dvb_service->getCacheEntry(eDVBService::cDDPPID)==-1)
+               && (m_dvb_service->getCacheEntry(eDVBService::cAACHEAPID)==-1)
+               && (m_dvb_service->getCacheEntry(eDVBService::cAACAPID)==-1))))
        {
-               if (apidtype == eDVBAudio::aMPEG)
-               {
-                       m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
-                       m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
-               }
-               else if (apidtype == eDVBAudio::aAC3)
-               {
-                       m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
-                       m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
-               }
-               else
-               {
-                       m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
-                       m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
-               }
+               m_dvb_service->setCacheEntry(eDVBService::cMPEGAPID, apidtype == eDVBAudio::aMPEG ? apid : -1);
+               m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apidtype == eDVBAudio::aAC3 ? apid : -1);
+               m_dvb_service->setCacheEntry(eDVBService::cDDPPID, apidtype == eDVBAudio::aDDP ? apid : -1);
+               m_dvb_service->setCacheEntry(eDVBService::cAACHEAPID, apidtype == eDVBAudio::aAACHE ? apid : -1);
+               m_dvb_service->setCacheEntry(eDVBService::cAACAPID, apidtype == eDVBAudio::aAAC ? apid : -1);
        }
 
        h.resetCachedProgram();
@@ -2215,6 +2241,8 @@ RESULT eDVBServicePlay::startTimeshift()
        }
                
        m_record->setTargetFD(m_timeshift_fd);
+       m_record->setTargetFilename(m_timeshift_file.c_str());
+       m_record->enableAccessPoints(false);
 
        m_timeshift_enabled = 1;
        
@@ -2240,6 +2268,11 @@ RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
        close(m_timeshift_fd);
        eDebug("remove timeshift file");
        eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
+
+       {
+               std::string timeshift_file_sc = m_timeshift_file + ".sc";
+               eBackgroundFileEraser::getInstance()->erase(timeshift_file_sc.c_str());
+       }
        
        return 0;
 }
@@ -2336,6 +2369,8 @@ void eDVBServicePlay::updateTimeshiftPids()
                return;
        else
        {
+               int timing_pid = -1;
+               int timing_pid_type = -1;
                std::set<int> pids_to_record;
                pids_to_record.insert(0); // PAT
                if (program.pmtPid != -1)
@@ -2347,12 +2382,28 @@ void eDVBServicePlay::updateTimeshiftPids()
                for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
                        i(program.videoStreams.begin()); 
                        i != program.videoStreams.end(); ++i)
+               {
                        pids_to_record.insert(i->pid);
 
+                       if (timing_pid == -1)
+                       {
+                               timing_pid = i->pid;
+                               timing_pid_type = i->type;
+                       }
+               }
+
                for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
                        i(program.audioStreams.begin()); 
                        i != program.audioStreams.end(); ++i)
-                               pids_to_record.insert(i->pid);
+               {
+                       pids_to_record.insert(i->pid);
+
+                       if (timing_pid == -1)
+                       {
+                               timing_pid = i->pid;
+                               timing_pid_type = -1;
+                       }
+               }
 
                for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
                        i(program.subtitleStreams.begin());
@@ -2376,6 +2427,9 @@ void eDVBServicePlay::updateTimeshiftPids()
 
                for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
                        m_record->removePID(*i);
+
+               if (timing_pid != -1)
+                       m_record->setTimingPID(timing_pid, timing_pid_type);
        }
 }
 
@@ -2591,9 +2645,11 @@ void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
                setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
 
                m_decoder->setVideoPID(vpid, vpidtype);
+               m_current_video_pid_type = vpidtype;
                selectAudioStream();
 
-               if (!(m_is_pvr || m_is_stream || m_timeshift_active || !m_is_primary))
+               //if (!(m_is_pvr || m_is_stream || m_timeshift_active || !m_is_primary))
+               if (!(m_is_pvr || m_is_stream || m_timeshift_active))
                        m_decoder->setSyncPCR(pcrpid);
                else
                        m_decoder->setSyncPCR(-1);
@@ -3005,11 +3061,30 @@ void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
 {
        if (m_subtitle_widget)
        {
+               int subtitledelay = 0;
                pts_t pos = 0;
                if (m_decoder)
                        m_decoder->getPTS(0, pos);
+               if (m_is_pvr || m_timeshift_enabled)
+               {
+                       eDebug("Subtitle in recording/timeshift");
+                       subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_noPTSrecordingdelay", 315000);
+               }
+               else
+               {
+                       /* check the setting for subtitle delay in live playback, either with pos, or without pos */
+                       subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_bad_timing_delay", 0);
+               }
+
                eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
-               m_subtitle_pages.push_back(page);
+               eDVBTeletextSubtitlePage tmppage = page;
+               tmppage.m_have_pts = true;
+
+               if (abs(tmppage.m_pts - pos) > 20*90000)
+                       tmppage.m_pts = pos; // fix abnormal pos diffs
+
+               tmppage.m_pts += subtitledelay;
+               m_subtitle_pages.push_back(tmppage);
                checkSubtitleTiming();
        }
 }
@@ -3093,7 +3168,29 @@ void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
                if (m_decoder)
                        m_decoder->getPTS(0, pos);
                eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
-               m_dvb_subtitle_pages.push_back(p);
+               if ( abs(pos-p.m_show_time)>1800000 && (m_is_pvr || m_timeshift_enabled))
+               {
+                       eDebug("[eDVBServicePlay] Subtitle without PTS and recording");
+                       int subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_noPTSrecordingdelay", 315000);
+
+                       eDVBSubtitlePage tmppage;
+                       tmppage = p;
+                       tmppage.m_show_time = pos + subtitledelay;
+                       m_dvb_subtitle_pages.push_back(tmppage);
+               }
+               else
+               {
+                       int subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_bad_timing_delay", 0);
+                       if (subtitledelay != 0)
+                       {
+                               eDVBSubtitlePage tmppage;
+                               tmppage = p;
+                               tmppage.m_show_time += subtitledelay;
+                               m_dvb_subtitle_pages.push_back(tmppage);
+                       }
+                       else
+                               m_dvb_subtitle_pages.push_back(p);
+               }
                checkSubtitleTiming();
        }
 }