7 #include <sys/select.h>
25 #define LOC QString("DVBSH[%1](%2): ").arg(m_inputId).arg(m_device)
34 #if !defined(__suseconds_t)
49 QMap<QString,DVBStreamHandler*>::iterator it =
57 LOG(VB_RECORD, LOG_INFO,
58 QString(
"DVBSH[%1]: Creating new stream handler %2")
59 .arg(inputid).arg(devname));
65 LOG(VB_RECORD, LOG_INFO,
66 QString(
"DVBSH[%1]: Using existing stream handler for %2")
68 .arg(devname) + QString(
" (%1 in use)").arg(rcount));
84 QMap<QString,DVBStreamHandler*>::iterator it =
s_handlers.find(devname);
95 LOG(VB_RECORD, LOG_INFO, QString(
"DVBSH[%1]: Closing handler for %2")
96 .arg(inputid).arg(devname));
102 LOG(VB_GENERAL, LOG_ERR,
103 QString(
"DVBSH[%1] Error: Couldn't find handler for %2")
104 .arg(inputid).arg(devname));
121 LOG(VB_RECORD, LOG_DEBUG,
LOC +
"run(): begin");
128 LOG(VB_RECORD, LOG_DEBUG,
LOC +
"run(): end");
146 for (
int tries = 1; ; ++tries)
148 dvr_fd = open(dvr_dev_path.constData(), O_RDONLY |
O_NONBLOCK);
152 LOG(VB_GENERAL, LOG_WARNING,
LOC +
153 QString(
"Opening DVR device %1 failed : %2")
156 if (tries >= 20 || (errno != EBUSY && errno != EAGAIN))
158 LOG(VB_GENERAL, LOG_ERR,
LOC +
159 QString(
"Failed to open DVR device %1 : %2")
164 std::this_thread::sleep_for(50ms);
169 auto *buffer =
new unsigned char[buffer_size];
172 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to allocate memory");
177 memset(buffer, 0, buffer_size);
185 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to allocate DRB buffer");
205 LOG(VB_RECORD, LOG_DEBUG,
LOC +
"RunTS(): begin");
207 fd_set fd_select_set;
208 FD_ZERO( &fd_select_set);
209 FD_SET (dvr_fd, &fd_select_set);
219 len = drb->
Read(&(buffer[remainder]), buffer_size - remainder);
224 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Device error detected");
230 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Device EOF detected");
238 int ret = select(dvr_fd+1, &fd_select_set,
nullptr,
nullptr, &
timeout);
239 if (ret == -1 && errno != EINTR)
241 LOG(VB_GENERAL, LOG_ERR,
LOC +
"select() failed" +
ENO);
245 len =
read(dvr_fd, &(buffer[remainder]),
246 buffer_size - remainder);
249 if ((0 == len) || (-1 == len))
251 std::this_thread::sleep_for(100us);
273 remainder = sit.key()->ProcessData(buffer, len);
279 if (remainder > 0 && (len > remainder))
280 memmove(buffer, &(buffer[len - remainder]), remainder);
282 LOG(VB_RECORD, LOG_DEBUG,
LOC +
"RunTS(): " +
"shutdown");
295 LOG(VB_RECORD, LOG_DEBUG,
LOC +
"RunTS(): " +
"end");
308 int buffer_size = 4192;
309 unsigned char *buffer =
pes_alloc(buffer_size);
318 LOG(VB_RECORD, LOG_DEBUG,
LOC +
"RunSR(): begin");
327 bool readSomething =
false;
330 int len =
read((*fit)->m_filterFd, buffer, buffer_size);
334 readSomething =
true;
342 sit.key()->HandleTables(fit.key() , psip);
348 std::this_thread::sleep_for(3ms);
350 LOG(VB_RECORD, LOG_DEBUG,
LOC +
"RunSR(): " +
"shutdown");
358 LOG(VB_RECORD, LOG_DEBUG,
LOC +
"RunSR(): " +
"end");
363 static pid_list_t::iterator
find(
366 pid_list_t::iterator begin,
367 pid_list_t::iterator end,
bool find_open)
369 pid_list_t::iterator it;
370 for (it = begin; it != end; ++it)
372 PIDInfoMap::const_iterator mit = map.find(*it);
373 if ((mit != map.end()) && ((*mit)->IsOpen() == find_open))
377 for (it = list.begin(); it != begin; ++it)
379 PIDInfoMap::const_iterator mit = map.find(*it);
380 if ((mit != map.end()) && ((*mit)->IsOpen() == find_open))
390 QMap<PIDPriority, pid_list_t> priority_queue;
391 QMap<PIDPriority, uint> priority_open_cnt;
396 priority_queue[
priority].push_back(cit.key());
397 if ((*cit)->IsOpen())
401 for (
auto & it : priority_queue)
402 std::sort(it.begin(), it.end());
407 while (priority_open_cnt[i] < priority_queue[i].size())
413 priority_queue[i].begin(), priority_queue[i].end(),
true);
414 if (open == priority_queue[i].end())
415 open = priority_queue[i].begin();
418 open, priority_queue[i].end(),
false);
420 if (closed == priority_queue[i].end())
426 priority_open_cnt[i]++;
436 if (!priority_open_cnt[j])
439 for (
uint k = 0; (k < priority_queue[j].size()) && !freed; k++)
449 priority_open_cnt[j]--;
460 priority_open_cnt[i]++;
476 priority_open_cnt[i]--;
483 priority_open_cnt[i]++;
498 if (allow && sigmon && dvbchan)
523 bool was_moving =
false;
524 bool is_moving =
false;
528 if (was_moving && !is_moving)
530 LOG(VB_CHANNEL, LOG_INFO,
531 LOC +
"Retuning for rotor completion");
556 const uint pat_pid = 0x0;
560 QMap<QString,bool>::const_iterator it;
567 int dvr_fd = open(dvr_dev_path.constData(), O_RDONLY |
O_NONBLOCK);
575 bool supports_ts =
false;
592 #define LOC QString("PIDInfo(%1): ").arg(dvb_dev)
603 QByteArray demux_ba = demux_fn.toLatin1();
605 LOG(VB_RECORD, LOG_DEBUG,
LOC + QString(
"Opening filter for pid 0x%1")
608 int mux_fd = open(demux_ba.constData(), O_RDWR |
O_NONBLOCK);
611 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Failed to open demux device %1 "
612 "for filter on pid 0x%2")
613 .arg(demux_fn).arg(
m_pid, 0, 16));
617 if (!use_section_reader)
619 struct dmx_pes_filter_params pesFilterParams {};
621 pesFilterParams.input = DMX_IN_FRONTEND;
622 pesFilterParams.output = DMX_OUT_TS_TAP;
623 pesFilterParams.flags = DMX_IMMEDIATE_START;
624 pesFilterParams.pes_type = DMX_PES_OTHER;
626 if (ioctl(mux_fd, DMX_SET_PES_FILTER, &pesFilterParams) < 0)
628 LOG(VB_GENERAL, LOG_ERR,
LOC +
629 QString(
"Failed to set TS filter (pid 0x%1)")
638 struct dmx_sct_filter_params sctFilterParams {};
642 sctFilterParams.filter.filter[0] = 0;
643 sctFilterParams.filter.mask[0] = 0xff;
651 sctFilterParams.filter.filter[0] = 0x00;
652 sctFilterParams.filter.mask[0] = 0xbc;
660 sctFilterParams.filter.filter[0] = 0x02;
661 sctFilterParams.filter.mask[0] = 0xbb;
666 sctFilterParams.filter.filter[0] = 0x80;
667 sctFilterParams.filter.mask[0] = 0xa0;
671 sctFilterParams.filter.filter[0] = 0x00;
672 sctFilterParams.filter.mask[0] = 0x00;
676 sctFilterParams.timeout = 0;
677 sctFilterParams.flags = DMX_IMMEDIATE_START;
679 if (ioctl(mux_fd, DMX_SET_FILTER, &sctFilterParams) < 0)
681 LOG(VB_GENERAL, LOG_ERR,
LOC +
682 "Failed to set \"section\" filter " +
683 QString(
"(pid 0x%1) (filter %2)").arg(
m_pid, 0, 16)
684 .arg(sctFilterParams.filter.filter[0]));
697 LOG(VB_RECORD, LOG_DEBUG,
LOC +
698 QString(
"Closing filter for pid 0x%1").arg(
m_pid, 0, 16));
709 LOG(VB_GENERAL, LOG_ERR,
710 LOC + QString(
"Failed to close mux (pid 0x%1)")
723 int DVBRecorder::OpenFilterFd(
uint pid,
int pes_type,
uint stream_type)
725 if (_open_pid_filters >= _max_pid_filters)
731 std::chrono::milliseconds msec_of_buffering = std::max(POLL_WARNING_TIMEOUT + 50ms, 1500ms);
733 uint pid_buffer_size = ((bpms*msec_of_buffering.count() + 7) / 8);
735 pid_buffer_size = ((pid_buffer_size + 4095) / 4096) * 4096;
737 LOG(VB_RECORD, LOG_DEBUG,
LOC + QString(
"Adding pid 0x%1 size(%2)")
738 .arg(pid,0,16).arg(pid_buffer_size));
743 QByteArray dev = dvbdev.toLatin1();
745 int fd_tmp = open(dev.constData(), O_RDWR);
748 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Could not open demux device." +
ENO);
749 _max_pid_filters = _open_pid_filters;
755 uint sz = pid_buffer_size;
756 std::chrono::microseconds usecs = msec_of_buffering;
757 while (ioctl(fd_tmp, DMX_SET_BUFFER_SIZE, sz) < 0 && sz > 1024*8)
759 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to set demux buffer size for "+
760 QString(
"pid 0x%1 to %2").arg(pid,0,16).arg(sz) +
ENO);
763 sz = ((sz+4095)/4096)*4096;
767 LOG(VB_RECORD, LOG_DEBUG,
LOC +
"Set demux buffer size for " +
768 QString(
"pid 0x%1 to %2,\n\t\t\twhich gives us a %3 msec buffer.")
769 .arg(pid,0,16).arg(sz)
770 .arg(duration_cast<std::chrono::milliseconds>(usecs).count()));
774 struct dmx_pes_filter_params params;
775 memset(¶ms, 0,
sizeof(params));
776 params.input = DMX_IN_FRONTEND;
777 params.output = DMX_OUT_TS_TAP;
778 params.flags = DMX_IMMEDIATE_START;
780 params.pes_type = (dmx_pes_type_t) pes_type;
781 if (ioctl(fd_tmp, DMX_SET_PES_FILTER, ¶ms) < 0)
785 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to set demux filter." +
ENO);
786 _max_pid_filters = _open_pid_filters;