bool DVBStreamHandler::UpdateFiltersFromStreamData(void) { UpdateListeningForEIT(); pid_map_t pids; { QMutexLocker read_locker(&_listener_lock); for (uint i = 0; i < _stream_data_list.size(); i++) _stream_data_list[i]->GetPIDs(pids); } QMap<uint, PIDInfo*> add_pids; vector<uint> del_pids; { QMutexLocker read_locker(&_pid_lock); // PIDs that need to be added.. pid_map_t::const_iterator lit = pids.constBegin(); for (; lit != pids.constEnd(); ++lit) { if (*lit && (_pid_info.find(lit.key()) == _pid_info.end())) { add_pids[lit.key()] = new PIDInfo( lit.key(), StreamID::PrivSec, DMX_PES_OTHER); } } // PIDs that need to be removed.. PIDInfoMap::const_iterator fit = _pid_info.begin(); for (; fit != _pid_info.end(); ++fit) { bool in_pids = pids.find(fit.key()) != pids.end(); if (!in_pids) del_pids.push_back(fit.key()); } } // Remove PIDs bool ok = true; vector<uint>::iterator dit = del_pids.begin(); for (; dit != del_pids.end(); ++dit) ok &= RemovePIDFilter(*dit); // Add PIDs QMap<uint, PIDInfo*>::iterator ait = add_pids.begin(); for (; ait != add_pids.end(); ++ait) ok &= AddPIDFilter(*ait); // Cycle filters if it's been a while if (_cycle_timer.elapsed() > 1000) CycleFiltersByPriority(); return ok; }
void DVBStreamHandler::UpdateListeningForEIT(void) { vector<uint> add_eit, del_eit; QMutexLocker read_locker(&_listener_lock); for (uint i = 0; i < _stream_data_list.size(); i++) { MPEGStreamData *sd = _stream_data_list[i]; if (sd->HasEITPIDChanges(_eit_pids) && sd->GetEITPIDChanges(_eit_pids, add_eit, del_eit)) { for (uint i = 0; i < del_eit.size(); i++) { uint_vec_t::iterator it; it = find(_eit_pids.begin(), _eit_pids.end(), del_eit[i]); if (it != _eit_pids.end()) _eit_pids.erase(it); sd->RemoveListeningPID(del_eit[i]); } for (uint i = 0; i < add_eit.size(); i++) { _eit_pids.push_back(add_eit[i]); sd->AddListeningPID(add_eit[i]); } } } }
void StreamHandler::UpdateListeningForEIT(void) { vector<uint> add_eit, del_eit; QMutexLocker read_locker(&m_listener_lock); StreamDataList::const_iterator it1 = m_stream_data_list.begin(); for (; it1 != m_stream_data_list.end(); ++it1) { MPEGStreamData *sd = it1.key(); if (sd->HasEITPIDChanges(m_eit_pids) && sd->GetEITPIDChanges(m_eit_pids, add_eit, del_eit)) { for (uint i = 0; i < del_eit.size(); i++) { uint_vec_t::iterator it2; it2 = find(m_eit_pids.begin(), m_eit_pids.end(), del_eit[i]); if (it2 != m_eit_pids.end()) m_eit_pids.erase(it2); sd->RemoveListeningPID(del_eit[i]); } for (uint i = 0; i < add_eit.size(); i++) { m_eit_pids.push_back(add_eit[i]); sd->AddListeningPID(add_eit[i]); } } } }
/** \fn DVBStreamHandler::RunSR(void) * \brief Uses "Section" reader to read a DVB device for tables * * This currently only supports DVB streams, ATSC and the raw MPEG * streams used by some cable and satelite providers is not supported. */ void DVBStreamHandler::RunSR(void) { int buffer_size = 4192; // maximum size of Section we handle unsigned char *buffer = new unsigned char[buffer_size]; if (!buffer) { _error = true; return; } SetRunning(true, _needs_buffering, true); LOG(VB_RECORD, LOG_INFO, LOC + "RunSR(): begin"); while (_running_desired && !_error) { RetuneMonitor(); UpdateFiltersFromStreamData(); QMutexLocker read_locker(&_pid_lock); bool readSomething = false; PIDInfoMap::const_iterator fit = _pid_info.begin(); for (; fit != _pid_info.end(); ++fit) { int len = read((*fit)->filter_fd, buffer, buffer_size); if (len <= 0) continue; readSomething = true; const PESPacket pes = PESPacket::ViewData(buffer); const PSIPTable psip(pes); if (psip.SectionSyntaxIndicator()) { _listener_lock.lock(); StreamDataList::const_iterator sit = _stream_data_list.begin(); for (; sit != _stream_data_list.end(); ++sit) sit.key()->HandleTables(fit.key() /* pid */, psip); _listener_lock.unlock(); } } if (!readSomething) usleep(3000); } LOG(VB_RECORD, LOG_INFO, LOC + "RunSR(): " + "shutdown"); RemoveAllPIDFilters(); delete[] buffer; SetRunning(false, _needs_buffering, true); LOG(VB_RECORD, LOG_INFO, LOC + "RunSR(): " + "end"); }
/** \fn DVBStreamHandler::RunSR(void) * \brief Uses "Section" reader to read a DVB device for tables * * This currently only supports DVB streams, ATSC and the raw MPEG * streams used by some cable and satelite providers is not supported. */ void DVBStreamHandler::RunSR(void) { int buffer_size = 4192; // maximum size of Section we handle unsigned char *buffer = new unsigned char[buffer_size]; if (!buffer) return; VERBOSE(VB_RECORD, LOC + "RunSR(): begin"); while (IsRunning()) { RetuneMonitor(); UpdateFiltersFromStreamData(); QMutexLocker read_locker(&_pid_lock); bool readSomething = false; PIDInfoMap::const_iterator fit = _pid_info.begin(); for (; fit != _pid_info.end(); ++fit) { int len = read((*fit)->filter_fd, buffer, buffer_size); if (len <= 0) continue; readSomething = true; const PESPacket pes = PESPacket::ViewData(buffer); const PSIPTable psip(pes); if (psip.SectionSyntaxIndicator()) { _listener_lock.lock(); for (uint i = 0; i < _stream_data_list.size(); i++) { _stream_data_list[i]->HandleTables( fit.key() /* pid */, psip); } _listener_lock.unlock(); } } if (!readSomething) usleep(3000); } VERBOSE(VB_RECORD, LOC + "RunSR(): " + "shutdown"); RemoveAllPIDFilters(); delete[] buffer; VERBOSE(VB_RECORD, LOC + "RunSR(): " + "end"); }
bool HDHRStreamHandler::UpdateFiltersFromStreamData(void) { UpdateListeningForEIT(); pid_map_t pids; { QMutexLocker read_locker(&_listener_lock); for (uint i = 0; i < _stream_data_list.size(); i++) _stream_data_list[i]->GetPIDs(pids); } uint_vec_t add_pids; vector<uint> del_pids; { QMutexLocker read_locker(&_pid_lock); // PIDs that need to be added.. pid_map_t::const_iterator lit = pids.constBegin(); for (; lit != pids.constEnd(); ++lit) { vector<uint>::iterator it; it = lower_bound(_pid_info.begin(), _pid_info.end(), lit.key()); if (it == _pid_info.end() || *it != lit.key()) add_pids.push_back(lit.key()); } // PIDs that need to be removed.. vector<uint>::const_iterator fit = _pid_info.begin(); for (; fit != _pid_info.end(); ++fit) { bool in_pids = pids.find(*fit) != pids.end(); if (!in_pids) del_pids.push_back(*fit); } } bool need_update = false; // Remove PIDs bool ok = true; vector<uint>::iterator dit = del_pids.begin(); for (; dit != del_pids.end(); ++dit) { need_update = true; ok &= RemovePIDFilter(*dit, false); } // Add PIDs vector<uint>::iterator ait = add_pids.begin(); for (; ait != add_pids.end(); ++ait) { need_update = true; ok &= AddPIDFilter(*ait, false); } if (need_update) return UpdateFilters() && ok; return ok; }
/** * @brief process instance from actual to expect. * expect actual action * yes no Install * yes yes same Nothing * yes yes no-same Update * no yes remove */ void MatrixManager::process_instance_expect() { if (!_host_info.is_ready()) { LOG.info("HostInfo is INVALID, ignore processing"); return; } if (_expect_list == NULL) { LOG.info("No EXPECT received. ignore processing"); return; } ::sailor::ReadLocker read_locker(&_expect_lock); ::sailor::WriteLocker write_locker(&_instance_lock); // generate tmp_instance_list, to find diff between _expect_list and _instance_list. std::map<std::string, Instance *> tmp_instace_list(_instance_list); for (std::vector<InstanceInfo>::iterator expect = _expect_list->begin(); expect != _expect_list->end(); ++ expect) { std::map<std::string, Instance *>::iterator iter = _instance_list.find(expect->get_instance_name()); if (iter == _instance_list.end()) { // not in local InstanceMeta meta = expect->get_instance_meta(); // has enough resource if (!_host_info.has_enough_resource(meta._resource)) { LOG.warn("MatrixManager: no enough resource or for instance[%s], \nneed resource: %s, \nhost info: %s", expect->get_instance_name().c_str(), meta._resource.to_json().toStyledString().c_str(), _host_info.to_json().toStyledString().c_str()); continue; } Instance * slot = new Instance(_current_generation, expect->get_service_name(), expect->get_offset()); // do state transformation if (!slot->do_install(meta)) { LOG.warn("MatrixManager: ignore install"); delete slot; continue; } _instance_list.insert(std::pair<std::string, Instance *>(expect->get_instance_name(), slot)); _host_info.use_resource(expect->get_instance_meta()._resource); ++ _current_generation; // call executor to install _executor.install(slot->get_instance_info(), slot->get_generation()); LOG.trace("MatrixManager: add new Instance [%s] success.", slot->get_instance_info().get_instance_name().c_str()); } else { // instance is already in local tmp_instace_list.erase(expect->get_instance_name()); Instance * slot = iter->second; const InstanceInfo& instance_info = slot->get_instance_info(); if (instance_info.get_meta_version() == expect->get_meta_version()) { // local and expect is same, ignore it. continue; } // local and expect is not same, update it. if (!slot->do_update(expect->get_instance_meta())) { LOG.info("MatrixManager: ignore update of instance %s.", iter->first.c_str()); continue; } // call executor to do update. _executor.update(slot->get_instance_info(), slot->get_generation()); LOG.trace("MatrixManager: update Instance [%s] success.", slot->get_instance_info().get_instance_name().c_str()); } } // find instances that in local but not in expect. and then remove it. for (std::map<std::string, Instance *>::iterator iter = tmp_instace_list.begin(); iter != tmp_instace_list.end(); ++ iter) { Instance * slot = iter->second; if (!slot->do_remove()) { continue; } _executor.remove(slot->get_instance_info(), slot->get_generation()); LOG.trace("MatrixManager: remove Instance [%s] success.", slot->get_instance_info().get_instance_name().c_str()); } }