X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/4e8904ef73e3ce5e275a1f5fbf369c4f9dab648e..93979892e9d66d3f31b84ac0e3399e95a77f76c2:/lib/service/servicedvb.cpp diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index 9a995e7b..f1858c9c 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -309,7 +309,9 @@ eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceR RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name) { ASSERT(ref == m_ref); - if (m_parser.m_name.size()) + if (!ref.name.empty()) + name = ref.name; + else if (!m_parser.m_name.empty()) name = m_parser.m_name; else { @@ -503,18 +505,19 @@ RESULT eDVBPVRServiceOfflineOperations::reindex() int err = f.open(m_ref.path.c_str(), 0); if (err < 0) return -1; - + + off_t offset = 0; off_t length = f.length(); unsigned char buffer[188*256*4]; while (1) { - off_t offset = f.lseek(0, SEEK_CUR); eDebug("at %08llx / %08llx (%d %%)", offset, length, (int)(offset * 100 / length)); - int r = f.read(buffer, sizeof(buffer)); + int r = f.read(offset, buffer, sizeof(buffer)); if (!r) break; if (r < 0) return r; + offset += r; parser.parseData(offset, buffer, r); } @@ -910,7 +913,7 @@ RESULT eServiceFactoryDVB::lookupService(ePtr &service, const eServ return 0; } -eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service): +eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service): m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0) { m_is_primary = 1; @@ -1021,14 +1024,18 @@ void eDVBServicePlay::serviceEvent(int event) updateTimeshiftPids(); if (!m_timeshift_active) updateDecoder(); - if (m_first_program_info && m_is_pvr) + if (m_first_program_info & 1 && m_is_pvr) { - m_first_program_info = 0; + m_first_program_info &= ~1; seekTo(0); } - m_event((iPlayableService*)this, evUpdatedInfo); + if (!m_timeshift_active) + m_event((iPlayableService*)this, evUpdatedInfo); break; } + case eDVBServicePMTHandler::eventPreStart: + loadCuesheet(); + break; case eDVBServicePMTHandler::eventEOF: m_event((iPlayableService*)this, evEOF); break; @@ -1043,17 +1050,87 @@ void eDVBServicePlay::serviceEventTimeshift(int event) switch (event) { case eDVBServicePMTHandler::eventNewProgramInfo: + eDebug("eventNewProgramInfo TS"); if (m_timeshift_active) + { updateDecoder(); + if (m_first_program_info & 2) + { + if (m_slowmotion) + { + eDebug("re-apply slowmotion after timeshift file change"); + m_decoder->setSlowMotion(m_slowmotion); + } + if (m_fastforward) + { + eDebug("re-apply skip %d, ratio %d after timeshift file change", m_skipmode, m_fastforward); + if (m_skipmode) + m_cue->setSkipmode(m_skipmode * 90000); /* convert to 90000 per second */ + if (m_fastforward != 1) + m_decoder->setFastForward(m_fastforward); + else + m_decoder->setTrickmode(); + } + else + seekTo(0); + m_first_program_info &= ~2; + } + m_event((iPlayableService*)this, evUpdatedInfo); + } break; case eDVBServicePMTHandler::eventSOF: - m_event((iPlayableService*)this, evSOF); +#if 0 + if (!m_timeshift_file_next.empty()) + { + eDebug("timeshift SOF, switch to next file"); + m_decoder->pause(); + + m_first_program_info |= 2; + + eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference; + r.path = m_timeshift_file_next; + + /* free the timeshift service handler, we need the resources */ + m_service_handler_timeshift.free(); + resetTimeshift(1); + + if (m_skipmode < 0) + m_cue->seekTo(0, -1000); + ePtr source = createTsSource(r); + m_service_handler_timeshift.tuneExt(r, 1, source, r.path.c_str(), m_cue, 0, m_dvb_service); /* use the decoder demux for everything */ + + m_event((iPlayableService*)this, evUser+1); + } + else +#endif + m_event((iPlayableService*)this, evSOF); break; case eDVBServicePMTHandler::eventEOF: if ((!m_is_paused) && (m_skipmode >= 0)) { - eDebug("timeshift EOF, so let's go live"); - switchToLive(); + if (m_timeshift_file_next.empty()) + { + eDebug("timeshift EOF, so let's go live"); + switchToLive(); + } + else + { + eDebug("timeshift EOF, switch to next file"); + + m_first_program_info |= 2; + + eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference; + r.path = m_timeshift_file_next; + + /* free the timeshift service handler, we need the resources */ + m_service_handler_timeshift.free(); + resetTimeshift(1); + + ePtr source = createTsSource(r); + m_service_handler_timeshift.tuneExt(r, 1, source, m_timeshift_file_next.c_str(), m_cue, 0, m_dvb_service); /* use the decoder demux for everything */ + + m_event((iPlayableService*)this, evUser+1); + } } break; } @@ -1080,7 +1157,8 @@ RESULT eDVBServicePlay::start() m_event(this, evStart); m_first_program_info = 1; - m_service_handler.tune(service, m_is_pvr, m_cue, false, m_dvb_service); + ePtr source = createTsSource(service); + m_service_handler.tuneExt(service, m_is_pvr, source, service.path.c_str(), m_cue, false, m_dvb_service); if (m_is_pvr) { @@ -1095,7 +1173,6 @@ RESULT eDVBServicePlay::start() m_event_handler.inject(event, 0); m_event_handler.inject(empty, 1); } - loadCuesheet(); m_event(this, evStart); } return 0; @@ -1126,11 +1203,7 @@ RESULT eDVBServicePlay::stop() if (length) { - int perc = play_position * 100LL / length; - - /* only store last play position when between 1% and 99% */ - if ((1 < perc) && (perc < 99)) - m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */ + m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */ } m_cuesheet_changed = 1; } @@ -1385,7 +1458,14 @@ RESULT eDVBServicePlay::setTrickmode(int trick) RESULT eDVBServicePlay::isCurrentlySeekable() { - return m_is_pvr || m_timeshift_active; + int ret = 0; + if (m_decoder) + { + ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible + if (m_decoder->getVideoProgressive() == -1) + ret &= ~2; + } + return ret; } RESULT eDVBServicePlay::frontendInfo(ePtr &ptr) @@ -2080,12 +2160,13 @@ RESULT eDVBServicePlay::startTimeshift() return 0; } -RESULT eDVBServicePlay::stopTimeshift() +RESULT eDVBServicePlay::stopTimeshift(bool swToLive) { if (!m_timeshift_enabled) return -1; - switchToLive(); + if (swToLive) + switchToLive(); m_timeshift_enabled = 0; @@ -2234,33 +2315,58 @@ void eDVBServicePlay::updateTimeshiftPids() } } +RESULT eDVBServicePlay::setNextPlaybackFile(const char *f) +{ + m_timeshift_file_next = f; + return 0; +} + void eDVBServicePlay::switchToLive() { if (!m_timeshift_active) return; - + eDebug("SwitchToLive"); - + + resetTimeshift(0); + + m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */ + + /* free the timeshift service handler, we need the resources */ + m_service_handler_timeshift.free(); + + updateDecoder(true); +} + +void eDVBServicePlay::resetTimeshift(int start) +{ m_cue = 0; - m_decoder = 0; m_decode_demux = 0; + m_decoder = 0; m_teletext_parser = 0; m_rds_decoder = 0; m_subtitle_parser = 0; - m_new_dvb_subtitle_page_connection = 0; m_new_subtitle_page_connection = 0; + m_new_dvb_subtitle_page_connection = 0; m_rds_decoder_event_connection = 0; m_video_event_connection = 0; - m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */ - - /* free the timeshift service handler, we need the resources */ - m_service_handler_timeshift.free(); - m_timeshift_active = 0; m_timeshift_changed = 1; + m_timeshift_file_next.clear(); - m_event((iPlayableService*)this, evSeekableStatusChanged); + if (start) + { + m_cue = new eCueSheet(); + m_timeshift_active = 1; + } + else + m_timeshift_active = 0; +} - updateDecoder(); +ePtr eDVBServicePlay::createTsSource(eServiceReferenceDVB &ref) +{ + eRawFile *f = new eRawFile(); + f->open(ref.path.c_str()); + return ePtr(f); } void eDVBServicePlay::switchToTimeshift() @@ -2268,36 +2374,25 @@ void eDVBServicePlay::switchToTimeshift() if (m_timeshift_active) return; - m_decode_demux = 0; - m_decoder = 0; - m_teletext_parser = 0; - m_rds_decoder = 0; - m_subtitle_parser = 0; - m_new_subtitle_page_connection = 0; - m_new_dvb_subtitle_page_connection = 0; - m_rds_decoder_event_connection = 0; - m_video_event_connection = 0; - - m_timeshift_active = 1; - m_timeshift_changed = 1; + resetTimeshift(1); eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference; r.path = m_timeshift_file; - m_cue = new eCueSheet(); m_cue->seekTo(0, -1000); - m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */ + + ePtr source = createTsSource(r); + m_service_handler_timeshift.tuneExt(r, 1, source, m_timeshift_file.c_str(), m_cue, 0, m_dvb_service); /* use the decoder demux for everything */ eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now."); pause(); - updateDecoder(); /* mainly to switch off PCR, and to set pause */ - - m_event((iPlayableService*)this, evSeekableStatusChanged); + updateDecoder(true); /* mainly to switch off PCR, and to set pause */ } -void eDVBServicePlay::updateDecoder() +void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged) { int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1; + bool mustPlay = false; eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler; @@ -2348,8 +2443,6 @@ void eDVBServicePlay::updateDecoder() if (!m_decoder) { h.getDecodeDemux(m_decode_demux); - if (m_timeshift_changed) - m_decoder = 0; if (m_decode_demux) { m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary); @@ -2378,17 +2471,17 @@ void eDVBServicePlay::updateDecoder() Py_DECREF(subs); } } - m_decoder->play(); /* pids will be set later */ } if (m_cue) m_cue->setDecodingDemux(m_decode_demux, m_decoder); - m_decoder->play(); /* pids will be set later. */ + mustPlay = true; } m_timeshift_changed = 0; if (m_decoder) { + bool wasSeekable = m_decoder->getVideoProgressive() != -1; if (m_dvb_service) { achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL); @@ -2421,17 +2514,8 @@ void eDVBServicePlay::updateDecoder() } } - std::string config_delay; - int config_delay_int = 0; - if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0) - config_delay_int = atoi(config_delay.c_str()); - m_decoder->setAC3Delay(ac3_delay == -1 ? config_delay_int : ac3_delay + config_delay_int); - - if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0) - config_delay_int = atoi(config_delay.c_str()); - else - config_delay_int = 0; - m_decoder->setPCMDelay(pcm_delay == -1 ? config_delay_int : pcm_delay + config_delay_int); + setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay); + setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay); m_decoder->setVideoPID(vpid, vpidtype); selectAudioStream(); @@ -2456,7 +2540,11 @@ void eDVBServicePlay::updateDecoder() m_decoder->setRadioPic(radio_pic); } - m_decoder->set(); + if (mustPlay) + m_decoder->play(); + else + m_decoder->set(); + m_decoder->setAudioChannel(achannel); /* don't worry about non-existing services, nor pvr services */ @@ -2468,8 +2556,13 @@ void eDVBServicePlay::updateDecoder() m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid); m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid); } + if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable) + sendSeekableStateChanged = true; } m_have_video_pid = (vpid > 0 && vpid < 0x2000); + + if (sendSeekableStateChanged) + m_event((iPlayableService*)this, evSeekableStatusChanged); } void eDVBServicePlay::loadCuesheet() @@ -2570,7 +2663,7 @@ void eDVBServicePlay::cutlistToCuesheet() { if (i == m_cue_entries.end()) { - if (!have_any_span) + if (!have_any_span && !in) break; out = length; } else { @@ -2600,6 +2693,7 @@ void eDVBServicePlay::cutlistToCuesheet() { have_any_span = 1; m_cue->addSourceSpan(in, out); + in = out = 0; } in = length; @@ -2955,16 +3049,28 @@ void eDVBServicePlay::setAC3Delay(int delay) { if (m_dvb_service) m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1); - if (m_decoder) - m_decoder->setAC3Delay(delay); + if (m_decoder) { + std::string config_delay; + int config_delay_int = 0; + if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0) + config_delay_int = atoi(config_delay.c_str()); + m_decoder->setAC3Delay(delay + config_delay_int); + } } void eDVBServicePlay::setPCMDelay(int delay) { if (m_dvb_service) m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1); - if (m_decoder) - m_decoder->setPCMDelay(delay); + if (m_decoder) { + std::string config_delay; + int config_delay_int = 0; + if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0) + config_delay_int = atoi(config_delay.c_str()); + else + config_delay_int = 0; + m_decoder->setPCMDelay(delay + config_delay_int); + } } void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)