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