MythTV  master
dvbstreamhandler.cpp
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 
3 // POSIX headers
4 #include <chrono> // for milliseconds
5 #include <fcntl.h>
6 #include <sys/ioctl.h>
7 #include <sys/select.h>
8 #include <thread> // for sleep_for
9 
10 // Qt headers
11 #include <QString>
12 
13 // MythTV headers
15 
16 #include "cardutil.h"
17 #include "diseqc.h" // for rotor retune
18 #include "dtvsignalmonitor.h"
19 #include "dvbchannel.h"
20 #include "dvbstreamhandler.h"
21 #include "dvbtypes.h" // for pid filtering
22 #include "mpeg/mpegstreamdata.h"
23 #include "mpeg/streamlisteners.h"
24 
25 #define LOC QString("DVBSH[%1](%2): ").arg(m_inputId).arg(m_device)
26 
29 
30 QMap<QString,DVBStreamHandler*> DVBStreamHandler::s_handlers;
31 QMap<QString,uint> DVBStreamHandler::s_handlersRefCnt;
33 
34 #if !defined(__suseconds_t)
35 #ifdef Q_OS_MACOS
36 using __suseconds_t = __darwin_suseconds_t;
37 #else
38 using __suseconds_t = long int;
39 #endif
40 #endif
41 static constexpr __suseconds_t k50Milliseconds {static_cast<__suseconds_t>(50 * 1000)};
42 
43 
44 DVBStreamHandler *DVBStreamHandler::Get(const QString &devname,
45  int inputid)
46 {
47  QMutexLocker locker(&s_handlersLock);
48 
49  QMap<QString,DVBStreamHandler*>::iterator it =
50  s_handlers.find(devname);
51 
52  if (it == s_handlers.end())
53  {
54  s_handlers[devname] = new DVBStreamHandler(devname, inputid);
55  s_handlersRefCnt[devname] = 1;
56 
57  LOG(VB_RECORD, LOG_INFO,
58  QString("DVBSH[%1]: Creating new stream handler %2")
59  .arg(inputid).arg(devname));
60  }
61  else
62  {
63  s_handlersRefCnt[devname]++;
64  uint rcount = s_handlersRefCnt[devname];
65  LOG(VB_RECORD, LOG_INFO,
66  QString("DVBSH[%1]: Using existing stream handler for %2")
67  .arg(inputid)
68  .arg(devname) + QString(" (%1 in use)").arg(rcount));
69  }
70 
71  return s_handlers[devname];
72 }
73 
74 void DVBStreamHandler::Return(DVBStreamHandler * & ref, int inputid)
75 {
76  QMutexLocker locker(&s_handlersLock);
77 
78  QString devname = ref->m_device;
79 
80  QMap<QString,uint>::iterator rit = s_handlersRefCnt.find(devname);
81  if (rit == s_handlersRefCnt.end())
82  return;
83 
84  QMap<QString,DVBStreamHandler*>::iterator it = s_handlers.find(devname);
85 
86  if (*rit > 1)
87  {
88  ref = nullptr;
89  (*rit)--;
90  return;
91  }
92 
93  if ((it != s_handlers.end()) && (*it == ref))
94  {
95  LOG(VB_RECORD, LOG_INFO, QString("DVBSH[%1]: Closing handler for %2")
96  .arg(inputid).arg(devname));
97  delete *it;
98  s_handlers.erase(it);
99  }
100  else
101  {
102  LOG(VB_GENERAL, LOG_ERR,
103  QString("DVBSH[%1] Error: Couldn't find handler for %2")
104  .arg(inputid).arg(devname));
105  }
106 
107  s_handlersRefCnt.erase(rit);
108  ref = nullptr;
109 }
110 
111 DVBStreamHandler::DVBStreamHandler(const QString &dvb_device, int inputid)
112  : StreamHandler(dvb_device, inputid)
113  , m_dvrDevPath(CardUtil::GetDeviceName(DVB_DEV_DVR, m_device))
114 {
115  setObjectName("DVBRead");
116 }
117 
119 {
120  RunProlog();
121  LOG(VB_RECORD, LOG_DEBUG, LOC + "run(): begin");
122 
124  RunSR();
125  else
126  RunTS();
127 
128  LOG(VB_RECORD, LOG_DEBUG, LOC + "run(): end");
129  RunEpilog();
130 }
131 
143 {
144  QByteArray dvr_dev_path = m_dvrDevPath.toLatin1();
145  int dvr_fd = 0;
146  for (int tries = 1; ; ++tries)
147  {
148  dvr_fd = open(dvr_dev_path.constData(), O_RDONLY | O_NONBLOCK);
149  if (dvr_fd >= 0)
150  break;
151 
152  LOG(VB_GENERAL, LOG_WARNING, LOC +
153  QString("Opening DVR device %1 failed : %2")
154  .arg(m_dvrDevPath, strerror(errno)));
155 
156  if (tries >= 20 || (errno != EBUSY && errno != EAGAIN))
157  {
158  LOG(VB_GENERAL, LOG_ERR, LOC +
159  QString("Failed to open DVR device %1 : %2")
160  .arg(m_dvrDevPath, strerror(errno)));
161  m_bError = true;
162  return;
163  }
164  std::this_thread::sleep_for(50ms);
165  }
166 
167  int remainder = 0;
168  int buffer_size = TSPacket::kSize * 15000;
169  auto *buffer = new unsigned char[buffer_size];
170  if (!buffer)
171  {
172  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to allocate memory");
173  close(dvr_fd);
174  m_bError = true;
175  return;
176  }
177  memset(buffer, 0, buffer_size);
178 
179  DeviceReadBuffer *drb = nullptr;
180  if (m_needsBuffering)
181  {
182  drb = new DeviceReadBuffer(this, true, false);
183  if (!drb->Setup(m_device, dvr_fd))
184  {
185  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to allocate DRB buffer");
186  delete drb;
187  delete[] buffer;
188  close(dvr_fd);
189  m_bError = true;
190  return;
191  }
192 
193  drb->Start();
194  }
195 
196  {
197  // SetRunning() + set m_drb
198  QMutexLocker locker(&m_startStopLock);
199  m_running = true;
201  m_usingSectionReader = false;
202  m_drb = drb;
203  }
204 
205  LOG(VB_RECORD, LOG_DEBUG, LOC + "RunTS(): begin");
206 
207  fd_set fd_select_set;
208  FD_ZERO( &fd_select_set); // NOLINT(readability-isolate-declaration)
209  FD_SET (dvr_fd, &fd_select_set);
210  while (m_runningDesired && !m_bError)
211  {
212  RetuneMonitor();
214 
215  ssize_t len = 0;
216 
217  if (drb)
218  {
219  len = drb->Read(&(buffer[remainder]), buffer_size - remainder);
220 
221  // Check for DRB errors
222  if (drb->IsErrored())
223  {
224  LOG(VB_GENERAL, LOG_ERR, LOC + "Device error detected");
225  m_bError = true;
226  }
227 
228  if (drb->IsEOF() && m_runningDesired)
229  {
230  LOG(VB_GENERAL, LOG_ERR, LOC + "Device EOF detected");
231  m_bError = true;
232  }
233  }
234  else
235  {
236  // timeout gets reset by select, so we need to create new one
237  struct timeval timeout = { 0, k50Milliseconds };
238  int ret = select(dvr_fd+1, &fd_select_set, nullptr, nullptr, &timeout);
239  if (ret == -1 && errno != EINTR)
240  {
241  LOG(VB_GENERAL, LOG_ERR, LOC + "select() failed" + ENO);
242  }
243  else
244  {
245  len = read(dvr_fd, &(buffer[remainder]),
246  buffer_size - remainder);
247  }
248 
249  if ((0 == len) || (-1 == len))
250  {
251  std::this_thread::sleep_for(100us);
252  continue;
253  }
254  }
255 
256  len += remainder;
257 
258  if (len < 10) // 10 bytes = 4 bytes TS header + 6 bytes PES header
259  {
260  remainder = len;
261  continue;
262  }
263 
264  m_listenerLock.lock();
265 
266  if (m_streamDataList.empty())
267  {
268  m_listenerLock.unlock();
269  continue;
270  }
271 
272  for (auto sit = m_streamDataList.cbegin(); sit != m_streamDataList.cend(); ++sit)
273  remainder = sit.key()->ProcessData(buffer, len);
274 
275  WriteMPTS(buffer, len - remainder);
276 
277  m_listenerLock.unlock();
278 
279  if (remainder > 0 && (len > remainder)) // leftover bytes
280  memmove(buffer, &(buffer[len - remainder]), remainder);
281  }
282  LOG(VB_RECORD, LOG_DEBUG, LOC + "RunTS(): " + "shutdown");
283 
285 
286  {
287  QMutexLocker locker(&m_startStopLock);
288  m_drb = nullptr;
289  }
290 
291  delete drb;
292  close(dvr_fd);
293  delete[] buffer;
294 
295  LOG(VB_RECORD, LOG_DEBUG, LOC + "RunTS(): " + "end");
296 
297  SetRunning(false, m_needsBuffering, false);
298 }
299 
307 {
308  int buffer_size = 4192; // maximum size of Section we handle
309  unsigned char *buffer = pes_alloc(buffer_size);
310  if (!buffer)
311  {
312  m_bError = true;
313  return;
314  }
315 
316  SetRunning(true, m_needsBuffering, true);
317 
318  LOG(VB_RECORD, LOG_DEBUG, LOC + "RunSR(): begin");
319 
320  while (m_runningDesired && !m_bError)
321  {
322  RetuneMonitor();
324 
325  QMutexLocker read_locker(&m_pidLock);
326 
327  bool readSomething = false;
328  for (auto fit = m_pidInfo.cbegin(); fit != m_pidInfo.cend(); ++fit)
329  {
330  int len = read((*fit)->m_filterFd, buffer, buffer_size);
331  if (len <= 0)
332  continue;
333 
334  readSomething = true;
335 
336  const PSIPTable psip(buffer);
337 
338  if (psip.SectionSyntaxIndicator())
339  {
340  m_listenerLock.lock();
341  for (auto sit = m_streamDataList.cbegin(); sit != m_streamDataList.cend(); ++sit)
342  sit.key()->HandleTables(fit.key() /* pid */, psip);
343  m_listenerLock.unlock();
344  }
345  }
346 
347  if (!readSomething)
348  std::this_thread::sleep_for(3ms);
349  }
350  LOG(VB_RECORD, LOG_DEBUG, LOC + "RunSR(): " + "shutdown");
351 
353 
354  pes_free(buffer);
355 
356  SetRunning(false, m_needsBuffering, true);
357 
358  LOG(VB_RECORD, LOG_DEBUG, LOC + "RunSR(): " + "end");
359 }
360 
361 using pid_list_t = std::vector<uint>;
362 
363 static pid_list_t::iterator find(
364  const PIDInfoMap &map,
365  pid_list_t &list,
366  pid_list_t::iterator begin,
367  pid_list_t::iterator end, bool find_open)
368 {
369  pid_list_t::iterator it;
370  for (it = begin; it != end; ++it)
371  {
372  PIDInfoMap::const_iterator mit = map.find(*it);
373  if ((mit != map.end()) && ((*mit)->IsOpen() == find_open))
374  return it;
375  }
376 
377  for (it = list.begin(); it != begin; ++it)
378  {
379  PIDInfoMap::const_iterator mit = map.find(*it);
380  if ((mit != map.end()) && ((*mit)->IsOpen() == find_open))
381  return it;
382  }
383 
384  return list.end();
385 }
386 
388 {
389  QMutexLocker writing_locker(&m_pidLock);
390  QMap<PIDPriority, pid_list_t> priority_queue;
391  QMap<PIDPriority, uint> priority_open_cnt;
392 
393  for (auto cit = m_pidInfo.cbegin(); cit != m_pidInfo.cend(); ++cit)
394  {
395  PIDPriority priority = GetPIDPriority((*cit)->m_pid);
396  priority_queue[priority].push_back(cit.key());
397  if ((*cit)->IsOpen())
398  priority_open_cnt[priority]++;
399  }
400 
401  for (auto & it : priority_queue)
402  std::sort(it.begin(), it.end());
403 
405  i = (PIDPriority)((int)i-1))
406  {
407  while (priority_open_cnt[i] < priority_queue[i].size())
408  {
409  // if we can open a filter, just do it
410 
411  // find first closed filter after first open an filter "k"
412  auto open = find(m_pidInfo, priority_queue[i],
413  priority_queue[i].begin(), priority_queue[i].end(), true);
414  if (open == priority_queue[i].end())
415  open = priority_queue[i].begin();
416 
417  auto closed = find(m_pidInfo, priority_queue[i],
418  open, priority_queue[i].end(), false);
419 
420  if (closed == priority_queue[i].end())
421  break; // something is broken
422 
423  if (m_pidInfo[*closed]->Open(m_device, m_usingSectionReader))
424  {
426  priority_open_cnt[i]++;
427  continue;
428  }
429 
430  // if we can't open a filter, try to close a lower priority one
431  bool freed = false;
432  for (auto j = (PIDPriority)((int)i - 1);
433  (j > kPIDPriorityNone) && !freed;
434  j = (PIDPriority)((int)j-1))
435  {
436  if (!priority_open_cnt[j])
437  continue;
438 
439  for (uint k = 0; (k < priority_queue[j].size()) && !freed; k++)
440  {
441  PIDInfo *info = m_pidInfo[priority_queue[j][k]];
442  if (!info->IsOpen())
443  continue;
444 
445  if (info->Close(m_device))
446  freed = true;
447 
449  priority_open_cnt[j]--;
450  }
451  }
452 
453  if (freed)
454  {
455  // if we can open a filter, just do it
456  if (m_pidInfo[*closed]->Open(
458  {
460  priority_open_cnt[i]++;
461  continue;
462  }
463  }
464 
465  // we have to cycle within our priority level
466 
467  if (m_cycleTimer.elapsed() < 1s)
468  break; // we don't want to cycle too often
469 
470  if (!m_pidInfo[*open]->IsOpen())
471  break; // nothing to close..
472 
473  // close "open"
474  bool ok = m_pidInfo[*open]->Close(m_device);
476  priority_open_cnt[i]--;
477 
478  // open "closed"
479  if (ok && m_pidInfo[*closed]->
481  {
483  priority_open_cnt[i]++;
484  }
485 
486  break; // we only want to cycle once per priority per run
487  }
488  }
489 
491 }
492 
494  bool allow,
495  DTVSignalMonitor *sigmon,
496  DVBChannel *dvbchan)
497 {
498  if (allow && sigmon && dvbchan)
499  {
500  m_allowRetune = true;
501  m_sigMon = sigmon;
502  m_dvbChannel = dvbchan;
503  }
504  else
505  {
506  m_allowRetune = false;
507  m_sigMon = nullptr;
508  m_dvbChannel = nullptr;
509  }
510 }
511 
513 {
514  if (!m_allowRetune)
515  return;
516 
517  // Rotor position
519  {
520  const DiSEqCDevRotor *rotor = m_dvbChannel->GetRotor();
521  if (rotor)
522  {
523  bool was_moving = false;
524  bool is_moving = false;
525  m_sigMon->GetRotorStatus(was_moving, is_moving);
526 
527  // Retune if move completes normally
528  if (was_moving && !is_moving)
529  {
530  LOG(VB_CHANNEL, LOG_INFO,
531  LOC + "Retuning for rotor completion");
532  m_dvbChannel->Retune();
533 
534  // (optionally) No need to wait for SDT anymore...
535  // RemoveFlags(kDTVSigMon_WaitForSDT);
536  }
537  }
538  else
539  {
540  // If no rotor is present, pretend the movement is completed
541  m_sigMon->SetRotorValue(100);
542  }
543  }
544 }
545 
555 {
556  const uint pat_pid = 0x0;
557 
558  {
559  QMutexLocker locker(&s_rec_supportsTsMonitoringLock);
560  QMap<QString,bool>::const_iterator it;
561  it = s_recSupportsTsMonitoring.constFind(m_device);
562  if (it != s_recSupportsTsMonitoring.constEnd())
563  return *it;
564  }
565 
566  QByteArray dvr_dev_path = m_dvrDevPath.toLatin1();
567  int dvr_fd = open(dvr_dev_path.constData(), O_RDONLY | O_NONBLOCK);
568  if (dvr_fd < 0)
569  {
570  QMutexLocker locker(&s_rec_supportsTsMonitoringLock);
572  return false;
573  }
574 
575  bool supports_ts = false;
576  if (AddPIDFilter(new DVBPIDInfo(pat_pid)))
577  {
578  supports_ts = true;
579  RemovePIDFilter(pat_pid);
580  }
581 
582  close(dvr_fd);
583 
584  QMutexLocker locker(&s_rec_supportsTsMonitoringLock);
585  s_recSupportsTsMonitoring[m_device] = supports_ts;
586 
587  return supports_ts;
588 }
589 
590 #undef LOC
591 
592 #define LOC QString("PIDInfo(%1): ").arg(dvb_dev)
593 
594 bool DVBPIDInfo::Open(const QString &dvb_dev, bool use_section_reader)
595 {
596  if (m_filterFd >= 0)
597  {
598  close(m_filterFd);
599  m_filterFd = -1;
600  }
601 
602  QString demux_fn = CardUtil::GetDeviceName(DVB_DEV_DEMUX, dvb_dev);
603  QByteArray demux_ba = demux_fn.toLatin1();
604 
605  LOG(VB_RECORD, LOG_DEBUG, LOC + QString("Opening filter for pid 0x%1")
606  .arg(m_pid, 0, 16));
607 
608  int mux_fd = open(demux_ba.constData(), O_RDWR | O_NONBLOCK);
609  if (mux_fd == -1)
610  {
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));
614  return false;
615  }
616 
617  if (!use_section_reader)
618  {
619  struct dmx_pes_filter_params pesFilterParams {};
620  pesFilterParams.pid = (uint16_t) m_pid;
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;
625 
626  if (ioctl(mux_fd, DMX_SET_PES_FILTER, &pesFilterParams) < 0)
627  {
628  LOG(VB_GENERAL, LOG_ERR, LOC +
629  QString("Failed to set TS filter (pid 0x%1)")
630  .arg(m_pid, 0, 16));
631 
632  close(mux_fd);
633  return false;
634  }
635  }
636  else
637  {
638  struct dmx_sct_filter_params sctFilterParams {};
639  switch ( m_pid )
640  {
641  case 0x0: // PAT
642  sctFilterParams.filter.filter[0] = 0;
643  sctFilterParams.filter.mask[0] = 0xff;
644  break;
645  case 0x0010: // assume this is for an NIT, NITo, PMT
646  // This filter will give us table ids 0x00-0x03, 0x40-0x43
647  // we expect to see table ids 0x02, 0x40 and 0x41 on this PID
648  // NOTE: In theory, this will break with ATSC when PID 0x10
649  // is used for ATSC/MPEG tables. This is frowned upon,
650  // but PMTs have been seen on in the wild.
651  sctFilterParams.filter.filter[0] = 0x00;
652  sctFilterParams.filter.mask[0] = 0xbc;
653  break;
654  case 0x0011: // assume this is for an SDT, SDTo, PMT
655  // This filter will give us table ids 0x02, 0x06, 0x42 and 0x46
656  // All but 0x06 are ones we want to see.
657  // NOTE: In theory this will break with ATSC when pid 0x11
658  // is used for random ATSC tables. In practice only
659  // video data has been seen on 0x11.
660  sctFilterParams.filter.filter[0] = 0x02;
661  sctFilterParams.filter.mask[0] = 0xbb;
662  break;
663  case 0x1ffb: // assume this is for various ATSC tables
664  // MGT 0xC7, Terrestrial VCT 0xC8, Cable VCT 0xC9, RRT 0xCA,
665  // STT 0xCD, DCCT 0xD3, DCCSCT 0xD4, Caption 0x86
666  sctFilterParams.filter.filter[0] = 0x80;
667  sctFilterParams.filter.mask[0] = 0xa0;
668  break;
669  default:
670  // otherwise assume it could be any table
671  sctFilterParams.filter.filter[0] = 0x00;
672  sctFilterParams.filter.mask[0] = 0x00;
673  break;
674  }
675  sctFilterParams.pid = (uint16_t) m_pid;
676  sctFilterParams.timeout = 0;
677  sctFilterParams.flags = DMX_IMMEDIATE_START;
678 
679  if (ioctl(mux_fd, DMX_SET_FILTER, &sctFilterParams) < 0)
680  {
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]));
685  close(mux_fd);
686  return false;
687  }
688  }
689 
690  m_filterFd = mux_fd;
691 
692  return true;
693 }
694 
695 bool DVBPIDInfo::Close(const QString &dvb_dev)
696 {
697  LOG(VB_RECORD, LOG_DEBUG, LOC +
698  QString("Closing filter for pid 0x%1").arg(m_pid, 0, 16));
699 
700  if (!IsOpen())
701  return false;
702 
703  int tmp = m_filterFd;
704  m_filterFd = -1;
705 
706  int err = close(tmp);
707  if (err < 0)
708  {
709  LOG(VB_GENERAL, LOG_ERR,
710  LOC + QString("Failed to close mux (pid 0x%1)")
711  .arg(m_pid, 0, 16) + ENO);
712 
713  return false;
714  }
715 
716  return true;
717 }
718 
719 #if 0
720 
721 // We don't yet do kernel buffer allocation in dvbstreamhandler..
722 
723 int DVBRecorder::OpenFilterFd(uint pid, int pes_type, uint stream_type)
724 {
725  if (_open_pid_filters >= _max_pid_filters)
726  return -1;
727 
728  // bits per millisecond
729  uint bpms = (StreamID::IsVideo(stream_type)) ? 19200 : 500;
730  // msec of buffering we want
731  std::chrono::milliseconds msec_of_buffering = std::max(POLL_WARNING_TIMEOUT + 50ms, 1500ms);
732  // actual size of buffer we need
733  uint pid_buffer_size = ((bpms*msec_of_buffering.count() + 7) / 8);
734  // rounded up to the nearest page
735  pid_buffer_size = ((pid_buffer_size + 4095) / 4096) * 4096;
736 
737  LOG(VB_RECORD, LOG_DEBUG, LOC + QString("Adding pid 0x%1 size(%2)")
738  .arg(pid,0,16).arg(pid_buffer_size));
739 
740  // Open the demux device
741  QString dvbdev = CardUtil::GetDeviceName(
742  DVB_DEV_DEMUX, _card_number_option);
743  QByteArray dev = dvbdev.toLatin1();
744 
745  int fd_tmp = open(dev.constData(), O_RDWR);
746  if (fd_tmp < 0)
747  {
748  LOG(VB_GENERAL, LOG_ERR, LOC + "Could not open demux device." + ENO);
749  _max_pid_filters = _open_pid_filters;
750  return -1;
751  }
752 
753  // Try to make the demux buffer large enough to
754  // allow for longish disk writes.
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)
758  {
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);
761 
762  sz /= 2;
763  sz = ((sz+4095)/4096)*4096;
764  usecs /= 2;
765  }
766 #if 0
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()));
771 #endif
772 
773  // Set the filter type
774  struct dmx_pes_filter_params params;
775  memset(&params, 0, sizeof(params));
776  params.input = DMX_IN_FRONTEND;
777  params.output = DMX_OUT_TS_TAP;
778  params.flags = DMX_IMMEDIATE_START;
779  params.pid = pid;
780  params.pes_type = (dmx_pes_type_t) pes_type;
781  if (ioctl(fd_tmp, DMX_SET_PES_FILTER, &params) < 0)
782  {
783  close(fd_tmp);
784 
785  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to set demux filter." + ENO);
786  _max_pid_filters = _open_pid_filters;
787  return -1;
788  }
789 
790  _open_pid_filters++;
791  return fd_tmp;
792 }
793 #endif
DVBStreamHandler::m_sigMon
DTVSignalMonitor * m_sigMon
Definition: dvbstreamhandler.h:66
MythTimer::elapsed
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
Definition: mythtimer.cpp:91
O_NONBLOCK
#define O_NONBLOCK
Definition: compat.h:341
PIDInfo::Close
virtual bool Close(const QString &)
Definition: streamhandler.h:38
ENO
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:73
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:102
DeviceReadBuffer::Start
void Start(void)
Definition: DeviceReadBuffer.cpp:106
DVBStreamHandler::SetRetuneAllowed
void SetRetuneAllowed(bool allow, DTVSignalMonitor *sigmon, DVBChannel *dvbchan)
Definition: dvbstreamhandler.cpp:493
DeviceReadBuffer::Setup
bool Setup(const QString &streamName, int streamfd, uint readQuanta=sizeof(TSPacket), uint deviceBufferSize=0, uint deviceBufferCount=1)
Definition: DeviceReadBuffer.cpp:49
DVBChannel::GetRotor
const DiSEqCDevRotor * GetRotor(void) const
Returns rotor object if it exists, nullptr otherwise.
Definition: dvbchannel.cpp:1158
DiSEqCDevRotor
Rotor class.
Definition: diseqc.h:302
DVBStreamHandler::m_allowRetune
volatile bool m_allowRetune
Definition: dvbstreamhandler.h:64
StreamHandler::RemoveAllPIDFilters
bool RemoveAllPIDFilters(void)
Definition: streamhandler.cpp:240
StreamHandler::SetRunning
void SetRunning(bool running, bool using_buffering, bool using_section_reader)
Definition: streamhandler.cpp:173
StreamHandler::WriteMPTS
void WriteMPTS(const unsigned char *buffer, uint len)
Write out a copy of the raw MPTS.
Definition: streamhandler.cpp:355
StreamHandler
Definition: streamhandler.h:56
discid.disc.read
def read(device=None, features=[])
Definition: disc.py:35
DVBStreamHandler::s_recSupportsTsMonitoring
static QMap< QString, bool > s_recSupportsTsMonitoring
Definition: dvbstreamhandler.h:72
diseqc.h
PIDInfo
Definition: streamhandler.h:27
MThread::setObjectName
void setObjectName(const QString &name)
Definition: mthread.cpp:238
DVBStreamHandler::s_rec_supportsTsMonitoringLock
static QMutex s_rec_supportsTsMonitoringLock
Definition: dvbstreamhandler.h:71
DeviceReadBuffer::Read
uint Read(unsigned char *buf, uint count)
Try to Read count bytes from into buffer.
Definition: DeviceReadBuffer.cpp:616
MythTimer::start
void start(void)
starts measuring elapsed time.
Definition: mythtimer.cpp:47
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MThread::RunProlog
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:196
DVBStreamHandler::RetuneMonitor
void RetuneMonitor(void)
Definition: dvbstreamhandler.cpp:512
streamlisteners.h
kPIDPriorityNone
@ kPIDPriorityNone
Definition: mpegstreamdata.h:78
DeviceReadBuffer
Buffers reads from device files.
Definition: DeviceReadBuffer.h:35
StreamHandler::m_startStopLock
QMutex m_startStopLock
Definition: streamhandler.h:118
DTVSignalMonitor::SetRotorValue
virtual void SetRotorValue(int)
Definition: dtvsignalmonitor.h:49
StreamHandler::GetPIDPriority
PIDPriority GetPIDPriority(uint pid) const
Definition: streamhandler.cpp:343
DVBStreamHandler::m_dvrDevPath
QString m_dvrDevPath
Definition: dvbstreamhandler.h:63
StreamID::IsVideo
static bool IsVideo(uint type)
Returns true iff video is an MPEG1/2/3, H264 or open cable video stream.
Definition: mpegtables.h:168
dvbchannel.h
PIDInfo::IsOpen
bool IsOpen(void) const
Definition: streamhandler.h:39
__suseconds_t
__darwin_suseconds_t __suseconds_t
Definition: dvbstreamhandler.cpp:36
close
#define close
Definition: compat.h:43
tmp
static guint32 * tmp
Definition: goom_core.cpp:26
DVBPIDInfo
Definition: dvbstreamhandler.h:22
StreamHandler::m_openPidFilters
uint m_openPidFilters
Definition: streamhandler.h:134
dvbstreamhandler.h
PSIPTable
A PSIP table is a variant of a PES packet containing an MPEG, ATSC or DVB table.
Definition: mpegtables.h:409
StreamHandler::m_usingSectionReader
bool m_usingSectionReader
Definition: streamhandler.h:128
StreamHandler::m_needsBuffering
bool m_needsBuffering
Definition: streamhandler.h:113
StreamHandler::m_listenerLock
QRecursiveMutex m_listenerLock
Definition: streamhandler.h:144
StreamHandler::m_running
bool m_running
Definition: streamhandler.h:125
StreamHandler::m_pidInfo
PIDInfoMap m_pidInfo
Definition: streamhandler.h:133
dvbtypes.h
mythlogging.h
SignalMonitor::kDVBSigMon_WaitForPos
static const uint64_t kDVBSigMon_WaitForPos
Wait for rotor to complete turning the antenna.
Definition: signalmonitor.h:198
DVBStreamHandler::Return
static void Return(DVBStreamHandler *&ref, int inputid)
Definition: dvbstreamhandler.cpp:74
pid_list_t
std::vector< uint > pid_list_t
Definition: dvbstreamhandler.cpp:361
DVBStreamHandler::Get
static DVBStreamHandler * Get(const QString &devname, int inputid)
Definition: dvbstreamhandler.cpp:44
StreamHandler::m_pidLock
QRecursiveMutex m_pidLock
Definition: streamhandler.h:131
DVBStreamHandler::DVBStreamHandler
DVBStreamHandler(const QString &dvb_device, int inputid)
Definition: dvbstreamhandler.cpp:111
StreamHandler::m_usingBuffering
bool m_usingBuffering
Definition: streamhandler.h:127
DVBStreamHandler::RunSR
void RunSR(void)
Uses "Section" reader to read a DVB device for tables.
Definition: dvbstreamhandler.cpp:306
StreamHandler::UpdateFiltersFromStreamData
bool UpdateFiltersFromStreamData(void)
Definition: streamhandler.cpp:290
DVBStreamHandler::s_handlers
static QMap< QString, DVBStreamHandler * > s_handlers
Definition: dvbstreamhandler.h:76
DVBStreamHandler::RunTS
void RunTS(void)
Uses TS filtering devices to read a DVB device for tables & data.
Definition: dvbstreamhandler.cpp:142
MThread::RunEpilog
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:209
CardUtil
Collection of helper utilities for input DB use.
Definition: cardutil.h:41
pes_free
void pes_free(unsigned char *ptr)
Definition: pespacket.cpp:369
DVBStreamHandler::m_dvbChannel
DVBChannel * m_dvbChannel
Definition: dvbstreamhandler.h:67
uint
unsigned int uint
Definition: compat.h:81
DVBStreamHandler::m_drb
DeviceReadBuffer * m_drb
Definition: dvbstreamhandler.h:68
DVBStreamHandler
Definition: dvbstreamhandler.h:32
DVBChannel::Retune
bool Retune(void) override
Definition: dvbchannel.cpp:980
DTVSignalMonitor::GetRotorStatus
virtual void GetRotorStatus(bool &was_moving, bool &is_moving)
Definition: dtvsignalmonitor.h:47
mpegstreamdata.h
kPIDPriorityHigh
@ kPIDPriorityHigh
Definition: mpegstreamdata.h:81
MThread::priority
QThread::Priority priority(void) const
Definition: mthread.cpp:253
StreamHandler::AddPIDFilter
bool AddPIDFilter(PIDInfo *info)
Definition: streamhandler.cpp:191
CardUtil::GetDeviceName
static QString GetDeviceName(dvb_dev_type_t type, const QString &device)
Definition: cardutil.cpp:2953
DVBChannel
Provides interface to the tuning hardware when using DVB drivers.
Definition: dvbchannel.h:31
StreamHandler::m_cycleTimer
MythTimer m_cycleTimer
Definition: streamhandler.h:136
DVBStreamHandler::CycleFiltersByPriority
void CycleFiltersByPriority(void) override
Definition: dvbstreamhandler.cpp:387
DVB_DEV_DEMUX
@ DVB_DEV_DEMUX
Definition: cardutil.h:32
SignalMonitor::HasFlags
bool HasFlags(uint64_t _flags) const
Definition: signalmonitor.cpp:275
PIDInfo::m_pid
uint m_pid
Definition: streamhandler.h:41
pes_alloc
unsigned char * pes_alloc(uint size)
Definition: pespacket.cpp:357
cardutil.h
DVBStreamHandler::s_handlersRefCnt
static QMap< QString, uint > s_handlersRefCnt
Definition: dvbstreamhandler.h:77
StreamHandler::m_runningDesired
volatile bool m_runningDesired
Definition: streamhandler.h:119
PIDInfoMap
QMap< uint, PIDInfo * > PIDInfoMap
Definition: streamhandler.h:49
PIDInfo::m_filterFd
int m_filterFd
Input filter file descriptor.
Definition: streamhandler.h:42
DVBStreamHandler::run
void run(void) override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: dvbstreamhandler.cpp:118
StreamHandler::m_streamDataList
StreamDataList m_streamDataList
Definition: streamhandler.h:145
StreamHandler::RemovePIDFilter
bool RemovePIDFilter(uint pid)
Definition: streamhandler.cpp:208
DTVSignalMonitor
This class is intended to detect the presence of needed tables.
Definition: dtvsignalmonitor.h:14
DeviceReadBuffer::IsErrored
bool IsErrored(void) const
Definition: DeviceReadBuffer.cpp:242
DVBStreamHandler::s_handlersLock
static QMutex s_handlersLock
Definition: dvbstreamhandler.h:75
DVBPIDInfo::Open
bool Open(const QString &dvb_dev, bool use_section_reader) override
Definition: dvbstreamhandler.cpp:594
DVBStreamHandler::SupportsTSMonitoring
bool SupportsTSMonitoring(void)
Returns true if TS monitoring is supported.
Definition: dvbstreamhandler.cpp:554
StreamHandler::m_bError
volatile bool m_bError
Definition: streamhandler.h:124
DeviceReadBuffer::IsEOF
bool IsEOF(void) const
Definition: DeviceReadBuffer.cpp:248
uint16_t
unsigned short uint16_t
Definition: iso6937tables.h:3
DVBPIDInfo::Close
bool Close(const QString &dvb_dev) override
Definition: dvbstreamhandler.cpp:695
StreamHandler::m_device
QString m_device
Definition: streamhandler.h:111
DVB_DEV_DVR
@ DVB_DEV_DVR
Definition: cardutil.h:31
LOC
#define LOC
Definition: dvbstreamhandler.cpp:592
PIDPriority
PIDPriority
Definition: mpegstreamdata.h:76
dtvsignalmonitor.h
PSIPTable::SectionSyntaxIndicator
bool SectionSyntaxIndicator(void) const
Definition: mpegtables.h:518
find
static pid_list_t::iterator find(const PIDInfoMap &map, pid_list_t &list, pid_list_t::iterator begin, pid_list_t::iterator end, bool find_open)
Definition: dvbstreamhandler.cpp:363
k50Milliseconds
static constexpr __suseconds_t k50Milliseconds
Definition: dvbstreamhandler.cpp:41
TSPacket::kSize
static constexpr unsigned int kSize
Definition: tspacket.h:259
StreamHandler::m_allowSectionReader
bool m_allowSectionReader
Definition: streamhandler.h:114