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(_inputid).arg(_device)
25 
28 
29 QMap<QString,DVBStreamHandler*> DVBStreamHandler::_handlers;
30 QMap<QString,uint> DVBStreamHandler::_handlers_refcnt;
32 
33 DVBStreamHandler *DVBStreamHandler::Get(const QString &devname,
34  int inputid)
35 {
36  QMutexLocker locker(&_handlers_lock);
37 
38  QMap<QString,DVBStreamHandler*>::iterator it =
39  _handlers.find(devname);
40 
41  if (it == _handlers.end())
42  {
43  _handlers[devname] = new DVBStreamHandler(devname, inputid);
44  _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  _handlers_refcnt[devname]++;
53  uint rcount = _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 _handlers[devname];
61 }
62 
63 void DVBStreamHandler::Return(DVBStreamHandler * & ref, int inputid)
64 {
65  QMutexLocker locker(&_handlers_lock);
66 
67  QString devname = ref->_device;
68 
69  QMap<QString,uint>::iterator rit = _handlers_refcnt.find(devname);
70  if (rit == _handlers_refcnt.end())
71  return;
72 
73  QMap<QString,DVBStreamHandler*>::iterator it = _handlers.find(devname);
74 
75  if (*rit > 1)
76  {
77  ref = nullptr;
78  (*rit)--;
79  return;
80  }
81 
82  if ((it != _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  _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  _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, _device))
103  , _allow_retune(false)
104  , _sigmon(nullptr)
105  , _dvbchannel(nullptr)
106  , _drb(nullptr)
107 {
108  setObjectName("DVBRead");
109 }
110 
112 {
113  if (_drb && _running_desired && !desired)
114  {
116  _drb->Stop();
117  }
118  else
119  {
121  }
122 }
123 
125 {
126  RunProlog();
127  LOG(VB_RECORD, LOG_DEBUG, LOC + "run(): begin");
128 
130  RunSR();
131  else
132  RunTS();
133 
134  LOG(VB_RECORD, LOG_DEBUG, LOC + "run(): end");
135  RunEpilog();
136 }
137 
149 {
150  QByteArray dvr_dev_path = _dvr_dev_path.toLatin1();
151  int dvr_fd;
152  for (int tries = 1; ; ++tries)
153  {
154  dvr_fd = open(dvr_dev_path.constData(), O_RDONLY | O_NONBLOCK);
155  if (dvr_fd >= 0)
156  break;
157 
158  LOG(VB_GENERAL, LOG_WARNING, LOC +
159  QString("Opening DVR device %1 failed : %2")
160  .arg(_dvr_dev_path).arg(strerror(errno)));
161 
162  if (tries >= 20 || (errno != EBUSY && errno != EAGAIN))
163  {
164  LOG(VB_GENERAL, LOG_ERR, LOC +
165  QString("Failed to open DVR device %1 : %2")
166  .arg(_dvr_dev_path).arg(strerror(errno)));
167  _error = true;
168  return;
169  }
170  std::this_thread::sleep_for(std::chrono::milliseconds(50));
171  }
172 
173  int remainder = 0;
174  int buffer_size = TSPacket::kSize * 15000;
175  unsigned char *buffer = new unsigned char[buffer_size];
176  if (!buffer)
177  {
178  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to allocate memory");
179  close(dvr_fd);
180  _error = true;
181  return;
182  }
183  memset(buffer, 0, buffer_size);
184 
185  DeviceReadBuffer *drb = nullptr;
186  if (_needs_buffering)
187  {
188  drb = new DeviceReadBuffer(this, true, false);
189  if (!drb->Setup(_device, dvr_fd))
190  {
191  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to allocate DRB buffer");
192  delete drb;
193  delete[] buffer;
194  close(dvr_fd);
195  _error = true;
196  return;
197  }
198 
199  drb->Start();
200  }
201 
202  {
203  // SetRunning() + set _drb
204  QMutexLocker locker(&_start_stop_lock);
205  _running = true;
207  _using_section_reader = false;
208  _drb = drb;
209  }
210 
211  LOG(VB_RECORD, LOG_DEBUG, LOC + "RunTS(): begin");
212 
213  fd_set fd_select_set;
214  FD_ZERO( &fd_select_set);
215  FD_SET (dvr_fd, &fd_select_set);
216  while (_running_desired && !_error)
217  {
218  RetuneMonitor();
220 
221  ssize_t len = 0;
222 
223  if (drb)
224  {
225  len = drb->Read(&(buffer[remainder]), buffer_size - remainder);
226 
227  // Check for DRB errors
228  if (drb->IsErrored())
229  {
230  LOG(VB_GENERAL, LOG_ERR, LOC + "Device error detected");
231  _error = true;
232  }
233 
234  if (drb->IsEOF() && _running_desired)
235  {
236  LOG(VB_GENERAL, LOG_ERR, LOC + "Device EOF detected");
237  _error = true;
238  }
239  }
240  else
241  {
242  // timeout gets reset by select, so we need to create new one
243  struct timeval timeout = { 0, 50 /* ms */ * 1000 /* -> usec */ };
244  int ret = select(dvr_fd+1, &fd_select_set, nullptr, nullptr, &timeout);
245  if (ret == -1 && errno != EINTR)
246  {
247  LOG(VB_GENERAL, LOG_ERR, LOC + "select() failed" + ENO);
248  }
249  else
250  {
251  len = read(dvr_fd, &(buffer[remainder]),
252  buffer_size - remainder);
253  }
254 
255  if ((0 == len) || (-1 == len))
256  {
257  std::this_thread::sleep_for(std::chrono::microseconds(100));
258  continue;
259  }
260  }
261 
262  len += remainder;
263 
264  if (len < 10) // 10 bytes = 4 bytes TS header + 6 bytes PES header
265  {
266  remainder = len;
267  continue;
268  }
269 
270  _listener_lock.lock();
271 
272  if (_stream_data_list.empty())
273  {
274  _listener_lock.unlock();
275  continue;
276  }
277 
278  StreamDataList::const_iterator sit = _stream_data_list.begin();
279  for (; sit != _stream_data_list.end(); ++sit)
280  remainder = sit.key()->ProcessData(buffer, len);
281 
282  WriteMPTS(buffer, len - remainder);
283 
284  _listener_lock.unlock();
285 
286  if (remainder > 0 && (len > remainder)) // leftover bytes
287  memmove(buffer, &(buffer[len - remainder]), remainder);
288  }
289  LOG(VB_RECORD, LOG_DEBUG, LOC + "RunTS(): " + "shutdown");
290 
292 
293  {
294  QMutexLocker locker(&_start_stop_lock);
295  _drb = nullptr;
296  }
297 
298  if (drb)
299  {
300  if (drb->IsRunning())
301  drb->Stop();
302  delete drb;
303  }
304 
305  close(dvr_fd);
306  delete[] buffer;
307 
308  LOG(VB_RECORD, LOG_DEBUG, LOC + "RunTS(): " + "end");
309 
310  SetRunning(false, _needs_buffering, false);
311 }
312 
320 {
321  int buffer_size = 4192; // maximum size of Section we handle
322  unsigned char *buffer = pes_alloc(buffer_size);
323  if (!buffer)
324  {
325  _error = true;
326  return;
327  }
328 
329  SetRunning(true, _needs_buffering, true);
330 
331  LOG(VB_RECORD, LOG_DEBUG, LOC + "RunSR(): begin");
332 
333  while (_running_desired && !_error)
334  {
335  RetuneMonitor();
337 
338  QMutexLocker read_locker(&_pid_lock);
339 
340  bool readSomething = false;
341  PIDInfoMap::const_iterator fit = _pid_info.begin();
342  for (; fit != _pid_info.end(); ++fit)
343  {
344  int len = read((*fit)->filter_fd, buffer, buffer_size);
345  if (len <= 0)
346  continue;
347 
348  readSomething = true;
349 
350  const PSIPTable psip(buffer);
351 
352  if (psip.SectionSyntaxIndicator())
353  {
354  _listener_lock.lock();
355  StreamDataList::const_iterator sit = _stream_data_list.begin();
356  for (; sit != _stream_data_list.end(); ++sit)
357  sit.key()->HandleTables(fit.key() /* pid */, psip);
358  _listener_lock.unlock();
359  }
360  }
361 
362  if (!readSomething)
363  std::this_thread::sleep_for(std::chrono::milliseconds(3));
364  }
365  LOG(VB_RECORD, LOG_DEBUG, LOC + "RunSR(): " + "shutdown");
366 
368 
369  pes_free(buffer);
370 
371  SetRunning(false, _needs_buffering, true);
372 
373  LOG(VB_RECORD, LOG_DEBUG, LOC + "RunSR(): " + "end");
374 }
375 
376 typedef vector<uint> pid_list_t;
377 
378 static pid_list_t::iterator find(
379  const PIDInfoMap &map,
380  pid_list_t &list,
381  pid_list_t::iterator begin,
382  pid_list_t::iterator end, bool find_open)
383 {
384  pid_list_t::iterator it;
385  for (it = begin; it != end; ++it)
386  {
387  PIDInfoMap::const_iterator mit = map.find(*it);
388  if ((mit != map.end()) && ((*mit)->IsOpen() == find_open))
389  return it;
390  }
391 
392  for (it = list.begin(); it != begin; ++it)
393  {
394  PIDInfoMap::const_iterator mit = map.find(*it);
395  if ((mit != map.end()) && ((*mit)->IsOpen() == find_open))
396  return it;
397  }
398 
399  return list.end();
400 }
401 
403 {
404  QMutexLocker writing_locker(&_pid_lock);
405  QMap<PIDPriority, pid_list_t> priority_queue;
406  QMap<PIDPriority, uint> priority_open_cnt;
407 
408  PIDInfoMap::const_iterator cit = _pid_info.begin();
409  for (; cit != _pid_info.end(); ++cit)
410  {
411  PIDPriority priority = GetPIDPriority((*cit)->_pid);
412  priority_queue[priority].push_back(cit.key());
413  if ((*cit)->IsOpen())
414  priority_open_cnt[priority]++;
415  }
416 
417  QMap<PIDPriority, pid_list_t>::iterator it = priority_queue.begin();
418  for (; it != priority_queue.end(); ++it)
419  sort((*it).begin(), (*it).end());
420 
422  i = (PIDPriority)((int)i-1))
423  {
424  while (priority_open_cnt[i] < priority_queue[i].size())
425  {
426  // if we can open a filter, just do it
427 
428  // find first closed filter after first open an filter "k"
429  pid_list_t::iterator open = find(
430  _pid_info, priority_queue[i],
431  priority_queue[i].begin(), priority_queue[i].end(), true);
432  if (open == priority_queue[i].end())
433  open = priority_queue[i].begin();
434 
435  pid_list_t::iterator closed = find(
436  _pid_info, priority_queue[i],
437  open, priority_queue[i].end(), false);
438 
439  if (closed == priority_queue[i].end())
440  break; // something is broken
441 
442  if (_pid_info[*closed]->Open(_device, _using_section_reader))
443  {
445  priority_open_cnt[i]++;
446  continue;
447  }
448 
449  // if we can't open a filter, try to close a lower priority one
450  bool freed = false;
451  for (PIDPriority j = (PIDPriority)((int)i - 1);
452  (j > kPIDPriorityNone) && !freed;
453  j = (PIDPriority)((int)j-1))
454  {
455  if (!priority_open_cnt[j])
456  continue;
457 
458  for (uint k = 0; (k < priority_queue[j].size()) && !freed; k++)
459  {
460  PIDInfo *info = _pid_info[priority_queue[j][k]];
461  if (!info->IsOpen())
462  continue;
463 
464  if (info->Close(_device))
465  freed = true;
466 
468  priority_open_cnt[j]--;
469  }
470  }
471 
472  if (freed)
473  {
474  // if we can open a filter, just do it
475  if (_pid_info[*closed]->Open(
477  {
479  priority_open_cnt[i]++;
480  continue;
481  }
482  }
483 
484  // we have to cycle within our priority level
485 
486  if (_cycle_timer.elapsed() < 1000)
487  break; // we don't want to cycle too often
488 
489  if (!_pid_info[*open]->IsOpen())
490  break; // nothing to close..
491 
492  // close "open"
493  bool ok = _pid_info[*open]->Close(_device);
495  priority_open_cnt[i]--;
496 
497  // open "closed"
498  if (ok && _pid_info[*closed]->
500  {
502  priority_open_cnt[i]++;
503  }
504 
505  break; // we only want to cycle once per priority per run
506  }
507  }
508 
510 }
511 
513  bool allow,
514  DTVSignalMonitor *sigmon,
515  DVBChannel *dvbchan)
516 {
517  if (allow && sigmon && dvbchan)
518  {
519  _allow_retune = true;
520  _sigmon = sigmon;
521  _dvbchannel = dvbchan;
522  }
523  else
524  {
525  _allow_retune = false;
526  _sigmon = nullptr;
527  _dvbchannel = nullptr;
528  }
529 }
530 
532 {
533  if (!_allow_retune)
534  return;
535 
536  // Rotor position
538  {
539  const DiSEqCDevRotor *rotor = _dvbchannel->GetRotor();
540  if (rotor)
541  {
542  bool was_moving, is_moving;
543  _sigmon->GetRotorStatus(was_moving, is_moving);
544 
545  // Retune if move completes normally
546  if (was_moving && !is_moving)
547  {
548  LOG(VB_CHANNEL, LOG_INFO,
549  LOC + "Retuning for rotor completion");
550  _dvbchannel->Retune();
551 
552  // (optionally) No need to wait for SDT anymore...
553  // RemoveFlags(kDTVSigMon_WaitForSDT);
554  }
555  }
556  else
557  {
558  // If no rotor is present, pretend the movement is completed
559  _sigmon->SetRotorValue(100);
560  }
561  }
562 }
563 
573 {
574  const uint pat_pid = 0x0;
575 
576  {
577  QMutexLocker locker(&_rec_supports_ts_monitoring_lock);
578  QMap<QString,bool>::const_iterator it;
580  if (it != _rec_supports_ts_monitoring.end())
581  return *it;
582  }
583 
584  QByteArray dvr_dev_path = _dvr_dev_path.toLatin1();
585  int dvr_fd = open(dvr_dev_path.constData(), O_RDONLY | O_NONBLOCK);
586  if (dvr_fd < 0)
587  {
588  QMutexLocker locker(&_rec_supports_ts_monitoring_lock);
590  return false;
591  }
592 
593  bool supports_ts = false;
594  if (AddPIDFilter(new DVBPIDInfo(pat_pid)))
595  {
596  supports_ts = true;
597  RemovePIDFilter(pat_pid);
598  }
599 
600  close(dvr_fd);
601 
602  QMutexLocker locker(&_rec_supports_ts_monitoring_lock);
603  _rec_supports_ts_monitoring[_device] = supports_ts;
604 
605  return supports_ts;
606 }
607 
608 #undef LOC
609 
610 #define LOC QString("PIDInfo(%1): ").arg(dvb_dev)
611 
612 bool DVBPIDInfo::Open(const QString &dvb_dev, bool use_section_reader)
613 {
614  if (filter_fd >= 0)
615  {
616  close(filter_fd);
617  filter_fd = -1;
618  }
619 
620  QString demux_fn = CardUtil::GetDeviceName(DVB_DEV_DEMUX, dvb_dev);
621  QByteArray demux_ba = demux_fn.toLatin1();
622 
623  LOG(VB_RECORD, LOG_DEBUG, LOC + QString("Opening filter for pid 0x%1")
624  .arg(_pid, 0, 16));
625 
626  int mux_fd = open(demux_ba.constData(), O_RDWR | O_NONBLOCK);
627  if (mux_fd == -1)
628  {
629  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to open demux device %1 "
630  "for filter on pid 0x%2")
631  .arg(demux_fn).arg(_pid, 0, 16));
632  return false;
633  }
634 
635  if (!use_section_reader)
636  {
637  struct dmx_pes_filter_params pesFilterParams;
638  memset(&pesFilterParams, 0, sizeof(struct dmx_pes_filter_params));
639  pesFilterParams.pid = (uint16_t) _pid;
640  pesFilterParams.input = DMX_IN_FRONTEND;
641  pesFilterParams.output = DMX_OUT_TS_TAP;
642  pesFilterParams.flags = DMX_IMMEDIATE_START;
643  pesFilterParams.pes_type = DMX_PES_OTHER;
644 
645  if (ioctl(mux_fd, DMX_SET_PES_FILTER, &pesFilterParams) < 0)
646  {
647  LOG(VB_GENERAL, LOG_ERR, LOC +
648  QString("Failed to set TS filter (pid 0x%1)")
649  .arg(_pid, 0, 16));
650 
651  close(mux_fd);
652  return false;
653  }
654  }
655  else
656  {
657  struct dmx_sct_filter_params sctFilterParams;
658  memset(&sctFilterParams, 0, sizeof(struct dmx_sct_filter_params));
659  switch ( _pid )
660  {
661  case 0x0: // PAT
662  sctFilterParams.filter.filter[0] = 0;
663  sctFilterParams.filter.mask[0] = 0xff;
664  break;
665  case 0x0010: // assume this is for an NIT, NITo, PMT
666  // This filter will give us table ids 0x00-0x03, 0x40-0x43
667  // we expect to see table ids 0x02, 0x40 and 0x41 on this PID
668  // NOTE: In theory, this will break with ATSC when PID 0x10
669  // is used for ATSC/MPEG tables. This is frowned upon,
670  // but PMTs have been seen on in the wild.
671  sctFilterParams.filter.filter[0] = 0x00;
672  sctFilterParams.filter.mask[0] = 0xbc;
673  break;
674  case 0x0011: // assume this is for an SDT, SDTo, PMT
675  // This filter will give us table ids 0x02, 0x06, 0x42 and 0x46
676  // All but 0x06 are ones we want to see.
677  // NOTE: In theory this will break with ATSC when pid 0x11
678  // is used for random ATSC tables. In practice only
679  // video data has been seen on 0x11.
680  sctFilterParams.filter.filter[0] = 0x02;
681  sctFilterParams.filter.mask[0] = 0xbb;
682  break;
683  case 0x1ffb: // assume this is for various ATSC tables
684  // MGT 0xC7, Terrestrial VCT 0xC8, Cable VCT 0xC9, RRT 0xCA,
685  // STT 0xCD, DCCT 0xD3, DCCSCT 0xD4, Caption 0x86
686  sctFilterParams.filter.filter[0] = 0x80;
687  sctFilterParams.filter.mask[0] = 0xa0;
688  break;
689  default:
690  // otherwise assume it could be any table
691  sctFilterParams.filter.filter[0] = 0x00;
692  sctFilterParams.filter.mask[0] = 0x00;
693  break;
694  }
695  sctFilterParams.pid = (uint16_t) _pid;
696  sctFilterParams.timeout = 0;
697  sctFilterParams.flags = DMX_IMMEDIATE_START;
698 
699  if (ioctl(mux_fd, DMX_SET_FILTER, &sctFilterParams) < 0)
700  {
701  LOG(VB_GENERAL, LOG_ERR, LOC +
702  "Failed to set \"section\" filter " +
703  QString("(pid 0x%1) (filter %2)").arg(_pid, 0, 16)
704  .arg(sctFilterParams.filter.filter[0]));
705  close(mux_fd);
706  return false;
707  }
708  }
709 
710  filter_fd = mux_fd;
711 
712  return true;
713 }
714 
715 bool DVBPIDInfo::Close(const QString &dvb_dev)
716 {
717  LOG(VB_RECORD, LOG_DEBUG, LOC +
718  QString("Closing filter for pid 0x%1").arg(_pid, 0, 16));
719 
720  if (!IsOpen())
721  return false;
722 
723  int tmp = filter_fd;
724  filter_fd = -1;
725 
726  int err = close(tmp);
727  if (err < 0)
728  {
729  LOG(VB_GENERAL, LOG_ERR,
730  LOC + QString("Failed to close mux (pid 0x%1)")
731  .arg(_pid, 0, 16) + ENO);
732 
733  return false;
734  }
735 
736  return true;
737 }
738 
739 #if 0
740 
741 // We don't yet do kernel buffer allocation in dvbstreamhandler..
742 
743 int DVBRecorder::OpenFilterFd(uint pid, int pes_type, uint stream_type)
744 {
745  if (_open_pid_filters >= _max_pid_filters)
746  return -1;
747 
748  // bits per millisecond
749  uint bpms = (StreamID::IsVideo(stream_type)) ? 19200 : 500;
750  // msec of buffering we want
751  uint msec_of_buffering = max(POLL_WARNING_TIMEOUT + 50, 1500);
752  // actual size of buffer we need
753  uint pid_buffer_size = ((bpms*msec_of_buffering + 7) / 8);
754  // rounded up to the nearest page
755  pid_buffer_size = ((pid_buffer_size + 4095) / 4096) * 4096;
756 
757  LOG(VB_RECORD, LOG_DEBUG, LOC + QString("Adding pid 0x%1 size(%2)")
758  .arg(pid,0,16).arg(pid_buffer_size));
759 
760  // Open the demux device
761  QString dvbdev = CardUtil::GetDeviceName(
762  DVB_DEV_DEMUX, _card_number_option);
763  QByteArray dev = dvbdev.toLatin1();
764 
765  int fd_tmp = open(dev.constData(), O_RDWR);
766  if (fd_tmp < 0)
767  {
768  LOG(VB_GENERAL, LOG_ERR, LOC + "Could not open demux device." + ENO);
769  _max_pid_filters = _open_pid_filters;
770  return -1;
771  }
772 
773  // Try to make the demux buffer large enough to
774  // allow for longish disk writes.
775  uint sz = pid_buffer_size;
776  uint usecs = msec_of_buffering * 1000;
777  while (ioctl(fd_tmp, DMX_SET_BUFFER_SIZE, sz) < 0 && sz > 1024*8)
778  {
779  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to set demux buffer size for "+
780  QString("pid 0x%1 to %2").arg(pid,0,16).arg(sz) + ENO);
781 
782  sz /= 2;
783  sz = ((sz+4095)/4096)*4096;
784  usecs /= 2;
785  }
786 #if 0
787  LOG(VB_RECORD, LOG_DEBUG, LOC + "Set demux buffer size for " +
788  QString("pid 0x%1 to %2,\n\t\t\twhich gives us a %3 msec buffer.")
789  .arg(pid,0,16).arg(sz).arg(usecs/1000));
790 #endif
791 
792  // Set the filter type
793  struct dmx_pes_filter_params params;
794  memset(&params, 0, sizeof(params));
795  params.input = DMX_IN_FRONTEND;
796  params.output = DMX_OUT_TS_TAP;
797  params.flags = DMX_IMMEDIATE_START;
798  params.pid = pid;
799  params.pes_type = (dmx_pes_type_t) pes_type;
800  if (ioctl(fd_tmp, DMX_SET_PES_FILTER, &params) < 0)
801  {
802  close(fd_tmp);
803 
804  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to set demux filter." + ENO);
805  _max_pid_filters = _open_pid_filters;
806  return -1;
807  }
808 
809  _open_pid_filters++;
810  return fd_tmp;
811 }
812 #endif
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:216
#define LOC
Collection of helper utilities for input DB use.
Definition: cardutil.h:39
bool IsRunning(void) const
bool _using_section_reader
bool IsOpen(void) const
Definition: streamhandler.h:38
virtual void SetRotorValue(int)
void SetRetuneAllowed(bool allow, DTVSignalMonitor *sigmon, DVBChannel *dvbchan)
static QMutex _handlers_lock
#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
void SetRunningDesired(bool desired) override
At minimum this sets _running_desired, this may also send signals to anything that might be blocking ...
bool UpdateFiltersFromStreamData(void)
static QMap< QString, DVBStreamHandler * > _handlers
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.
volatile bool _error
unsigned int uint
Definition: compat.h:140
Provides interface to the tuning hardware when using DVB drivers.
Definition: dvbchannel.h:29
static QMap< QString, bool > _rec_supports_ts_monitoring
unsigned char * pes_alloc(uint size)
Definition: pespacket.cpp:330
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:250
const DiSEqCDevRotor * GetRotor(void) const
Returns rotor object if it exists, nullptr otherwise.
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:910
uint Read(unsigned char *buf, uint count)
Try to Read count bytes from into buffer.
bool _allow_section_reader
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
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
MythTimer _cycle_timer
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 Close(const QString &dvb_dev) override
QMutex _listener_lock
volatile bool _running_desired
Rotor class.
Definition: diseqc.h:292
unsigned short uint16_t
Definition: iso6937tables.h:1
void RunTS(void)
Uses TS filtering devices to read a DVB device for tables & data.
#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
This class is intended to detect the presence of needed tables.
PIDPriority
StreamDataList _stream_data_list
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:181
vector< uint > pid_list_t
QThread::Priority priority(void) const
Definition: mthread.cpp:265
static QMutex _rec_supports_ts_monitoring_lock
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.
virtual void SetRunningDesired(bool desired)
At minimum this sets _running_desired, this may also send signals to anything that might be blocking ...
void pes_free(unsigned char *ptr)
Definition: pespacket.cpp:342
DeviceReadBuffer * _drb
static QMap< QString, uint > _handlers_refcnt
static DVBStreamHandler * Get(const QString &dvb_device, int inputid)
bool AddPIDFilter(PIDInfo *info)
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:203
Buffers reads from device files.
void CycleFiltersByPriority(void) override
uint _open_pid_filters
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.
PIDInfoMap _pid_info
void start(void)
starts measuring elapsed time.
Definition: mythtimer.cpp:47
uint _pid
Definition: streamhandler.h:40
bool RemoveAllPIDFilters(void)
QMutex _start_stop_lock
DTVSignalMonitor * _sigmon
PIDPriority GetPIDPriority(uint pid) const
bool HasFlags(uint64_t _flags) const