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]); } } } }
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(); }