Пример #1
0
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]);
            }
        }
    }
}
Пример #2
0
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]);
            }
        }
    }
}
Пример #3
0
void MpegRecorder::run(void)
{
    if (!Open())
    {
        if (_error.isEmpty())
            _error = "Failed to open V4L device";
        return;
    }

    bool has_select = true;

#if defined(__FreeBSD__)
    // HACK. FreeBSD PVR150/500 driver doesn't currently support select()
    has_select = false;
#endif

    if (driver == "hdpvr")
    {
        int progNum = 1;
        MPEGStreamData *sd = new MPEGStreamData
                             (progNum, tvrec ? tvrec->GetCaptureCardNum() : -1,
                              true);
        sd->SetRecordingType(_recording_type);
        SetStreamData(sd);

        _stream_data->AddAVListener(this);
        _stream_data->AddWritingListener(this);

        // Make sure the first things in the file are a PAT & PMT
        HandleSingleProgramPAT(_stream_data->PATSingleProgram(), true);
        HandleSingleProgramPMT(_stream_data->PMTSingleProgram(), true);
        _wait_for_keyframe_option = true;
    }

    {
        QMutexLocker locker(&pauseLock);
        request_recording = true;
        request_helper = true;
        recording = true;
        recordingWait.wakeAll();
    }

    unsigned char *buffer = new unsigned char[bufferSize + 1];
    int len;
    int remainder = 0;

    bool      good_data = false;
    bool      gap = false;
    QDateTime gap_start;

    MythTimer elapsedTimer;
    float elapsed;
    long long bytesRead = 0;
    int dummyBPS = 0;  // Bytes per second, but env var is BITS PER SECOND

    if (getenv("DUMMYBPS"))
    {
        dummyBPS = atoi(getenv("DUMMYBPS")) / 8;
        LOG(VB_GENERAL, LOG_INFO,
            LOC + QString("Throttling dummy recorder to %1 bits per second")
                .arg(dummyBPS * 8));
    }

    struct timeval tv;
    fd_set rdset;

    if (deviceIsMpegFile)
        elapsedTimer.start();
    else if (_device_read_buffer)
    {
        LOG(VB_RECORD, LOG_INFO, LOC + "Initial startup of recorder");
        StartEncoding();
    }

    QByteArray vdevice = videodevice.toLatin1();
    while (IsRecordingRequested() && !IsErrored())
    {
        if (PauseAndWait(100))
            continue;

        if (deviceIsMpegFile)
        {
            if (dummyBPS && bytesRead)
            {
                elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
                while ((bytesRead / elapsed) > dummyBPS)
                {
                    usleep(50000);
                    elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
                }
            }
            else if (GetFramesWritten())
            {
                elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
                while ((GetFramesWritten() / elapsed) > 30)
                {
                    usleep(50000);
                    elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
                }
            }
        }

        if (_device_read_buffer)
        {
            len = _device_read_buffer->Read
                  (&(buffer[remainder]), bufferSize - remainder);

            // Check for DRB errors
            if (_device_read_buffer->IsErrored())
            {
                LOG(VB_GENERAL, LOG_ERR, LOC + "Device error detected");

                if (good_data)
                {
                    if (gap)
                    {
                        /* Already processing a gap, which means
                         * restarting the encoding didn't work! */
                        SetRecordingStatus(rsFailing, __FILE__, __LINE__);
                    }
                    else
                        gap = true;
                }

                RestartEncoding();
            }
            else if (_device_read_buffer->IsEOF() &&
                     IsRecordingRequested())
            {
                LOG(VB_GENERAL, LOG_ERR, LOC + "Device EOF detected");
                _error = "Device EOF detected";
            }
            else
            {
                // If we have seen good data, but now have a gap, note it
                if (good_data)
                {
                    if (gap)
                    {
                        QMutexLocker locker(&statisticsLock);
                        QDateTime gap_end(MythDate::current());

                        recordingGaps.push_back(RecordingGap
                                                (gap_start, gap_end));
                        LOG(VB_RECORD, LOG_DEBUG,
                            LOC + QString("Inserted gap %1 dur %2")
                            .arg(recordingGaps.back().toString())
                            .arg(gap_start.secsTo(gap_end)));
                        gap = false;
                    }
                    else
                        gap_start = MythDate::current();
                }
                else
                    good_data = true;
            }
        }
        else
        {
            if (has_select)
            {
                tv.tv_sec = 5;
                tv.tv_usec = 0;
                FD_ZERO(&rdset);
                FD_SET(readfd, &rdset);

                switch (select(readfd + 1, &rdset, NULL, NULL, &tv))
                {
                    case -1:
                        if (errno == EINTR)
                            continue;

                        LOG(VB_GENERAL, LOG_ERR, LOC + "Select error" + ENO);
                        continue;

                    case 0:
                        LOG(VB_GENERAL, LOG_ERR, LOC + "select timeout - "
                                "driver has stopped responding");

                        if (close(readfd) != 0)
                        {
                            LOG(VB_GENERAL, LOG_ERR, LOC + "Close error" + ENO);
                        }

                        // Force card to be reopened on next iteration..
                        readfd = -1;
                        continue;

                    default:
                        break;
                }
            }

            len = read(readfd, &(buffer[remainder]), bufferSize - remainder);

            if (len < 0 && !has_select)
            {
                QMutexLocker locker(&pauseLock);
                if (request_recording && !request_pause)
                    unpauseWait.wait(&pauseLock, 25);
                continue;
            }

            if ((len == 0) && (deviceIsMpegFile))
            {
                close(readfd);
                readfd = open(vdevice.constData(), O_RDONLY);

                if (readfd >= 0)
                {
                    len = read(readfd,
                               &(buffer[remainder]), bufferSize - remainder);
                }

                if (len <= 0)
                {
                    _error = "Failed to read from video file";
                    continue;
                }
            }
            else if (len < 0 && errno != EAGAIN)
            {
                LOG(VB_GENERAL, LOG_ERR, LOC + QString("error reading from: %1")
                        .arg(videodevice) + ENO);
                continue;
            }
        }

        if (len > 0)
        {
            bytesRead += len;
            len += remainder;

            if (driver == "hdpvr")
            {
                remainder = _stream_data->ProcessData(buffer, len);
                int start_remain = len - remainder;
                if (remainder && (start_remain >= remainder))
                    memcpy(buffer, buffer+start_remain, remainder);
                else if (remainder)
                    memmove(buffer, buffer+start_remain, remainder);
            }
            else
            {
                FindPSKeyFrames(buffer, len);
            }
        }
    }

    LOG(VB_RECORD, LOG_INFO, LOC + "run finishing up");

    StopEncoding();

    {
        QMutexLocker locker(&pauseLock);
        request_helper = false;
    }

    if (vbi_thread)
    {
        vbi_thread->wait();
        delete vbi_thread;
        vbi_thread = NULL;
        CloseVBIDevice();
    }

    FinishRecording();

    delete[] buffer;

    if (driver == "hdpvr")
    {
        _stream_data->RemoveWritingListener(this);
        _stream_data->RemoveAVListener(this);
        SetStreamData(NULL);
    }

    QMutexLocker locker(&pauseLock);
    request_recording = false;
    recording = false;
    recordingWait.wakeAll();
}