Beispiel #1
0
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;
}
/** \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");
}
Beispiel #3
0
/** \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");
}
Beispiel #4
0
void DVBStreamHandler::CycleFiltersByPriority(void)
{
    QMutexLocker writing_locker(&_pid_lock);
    QMap<PIDPriority, pid_list_t> priority_queue;
    QMap<PIDPriority, uint> priority_open_cnt;

    PIDInfoMap::const_iterator cit = _pid_info.begin();
    for (; cit != _pid_info.end(); ++cit)
    {
        PIDPriority priority = GetPIDPriority((*cit)->_pid);
        priority_queue[priority].push_back(cit.key());
        if ((*cit)->IsOpen())
            priority_open_cnt[priority]++;
    }

    QMap<PIDPriority, pid_list_t>::iterator it = priority_queue.begin();
    for (; it != priority_queue.end(); ++it)
        sort((*it).begin(), (*it).end());

    for (PIDPriority i = kPIDPriorityHigh; i > kPIDPriorityNone;
         i = (PIDPriority)((int)i-1))
    {
        while (priority_open_cnt[i] < priority_queue[i].size())
        {
            // if we can open a filter, just do it

            // find first closed filter after first open an filter "k"
            pid_list_t::iterator open = find(
                _pid_info, priority_queue[i],
                priority_queue[i].begin(), priority_queue[i].end(), true);
            if (open == priority_queue[i].end())
                open = priority_queue[i].begin();

            pid_list_t::iterator closed = find(
                _pid_info, priority_queue[i],
                open, priority_queue[i].end(), false);

            if (closed == priority_queue[i].end())
                break; // something is broken

            if (_pid_info[*closed]->Open(_dvb_dev, _using_section_reader))
            {
                _open_pid_filters++;
                priority_open_cnt[i]++;
                continue;
            }

            // if we can't open a filter, try to close a lower priority one
            bool freed = false;
            for (PIDPriority j = (PIDPriority)((int)i - 1);
                 (j > kPIDPriorityNone) && !freed;
                 j = (PIDPriority)((int)j-1))
            {
                if (!priority_open_cnt[j])
                    continue;

                for (uint k = 0; (k < priority_queue[j].size()) && !freed; k++)
                {
                    PIDInfo *info = _pid_info[priority_queue[j][k]];
                    if (!info->IsOpen())
                        continue;

                    if (info->Close(_dvb_dev))
                        freed = true;

                    _open_pid_filters--;
                    priority_open_cnt[j]--;
                }
            }

            if (freed)
            {
                // if we can open a filter, just do it
                if (_pid_info[*closed]->Open(
                        _dvb_dev, _using_section_reader))
                {
                    _open_pid_filters++;
                    priority_open_cnt[i]++;
                    continue;
                }
            }

            // we have to cycle within our priority level

            if (_cycle_timer.elapsed() < 1000)
                break; // we don't want to cycle too often

            if (!_pid_info[*open]->IsOpen())
                break; // nothing to close..

            // close "open"
            bool ok = _pid_info[*open]->Close(_dvb_dev);
            _open_pid_filters--;
            priority_open_cnt[i]--;

            // open "closed"
            if (ok && _pid_info[*closed]->
                Open(_dvb_dev, _using_section_reader))
            {
                _open_pid_filters++;
                priority_open_cnt[i]++;
            }

            break; // we only want to cycle once per priority per run
        }
    }

    _cycle_timer.start();
}
Beispiel #5
0
bool HDHRStreamHandler::UpdateFilters(void)
{
    if (_tune_mode == hdhrTuneModeFrequency)
        _tune_mode = hdhrTuneModeFrequencyPid;

    if (_tune_mode != hdhrTuneModeFrequencyPid)
    {
        LOG(VB_GENERAL, LOG_ERR, LOC +
            "UpdateFilters called in wrong tune mode");
        return false;
    }

#ifdef DEBUG_PID_FILTERS
    LOG(VB_RECORD, LOG_INFO, LOC + "UpdateFilters()");
#endif // DEBUG_PID_FILTERS
    QMutexLocker locker(&_pid_lock);

    QString filter = "";

    vector<uint> range_min;
    vector<uint> range_max;

    PIDInfoMap::const_iterator it = _pid_info.begin();
    for (; it != _pid_info.end(); ++it)
    {
        range_min.push_back(it.key());
        PIDInfoMap::const_iterator eit = it;
        for (++eit;
             (eit != _pid_info.end()) && (it.key() + 1 == eit.key());
             ++it, ++eit);
        range_max.push_back(it.key());
    }
    if (range_min.size() > 16)
    {
        range_min.resize(16);
        uint pid_max = range_max.back();
        range_max.resize(15);
        range_max.push_back(pid_max);
    }

    for (uint i = 0; i < range_min.size(); i++)
    {
        filter += filt_str(range_min[i]);
        if (range_min[i] != range_max[i])
            filter += QString("-%1").arg(filt_str(range_max[i]));
        filter += " ";
    }

    filter = filter.trimmed();

    QString new_filter = TunerSet("filter", filter);

#ifdef DEBUG_PID_FILTERS
    QString msg = QString("Filter: '%1'").arg(filter);
    if (filter != new_filter)
        msg += QString("\n\t\t\t\t'%2'").arg(new_filter);

    LOG(VB_RECORD, LOG_INFO, LOC + msg);
#endif // DEBUG_PID_FILTERS

    return filter == new_filter;
}