MythTV  master
firewiresignalmonitor.cpp
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 // Copyright (c) 2006, Daniel Thor Kristjansson
3 
4 #include <fcntl.h>
5 #include <sys/select.h>
6 #include <chrono> // for milliseconds
7 #include <thread> // for sleep_for
8 
9 #include "mythdbcon.h"
10 #include "atscstreamdata.h"
11 #include "mpegtables.h"
12 #include "atsctables.h"
13 #include "firewirechannel.h"
14 #include "firewiresignalmonitor.h"
15 #include "mythlogging.h"
16 
17 #define LOC QString("FireSigMon[%1](%2): ") \
18  .arg(m_inputid).arg(m_channel->GetDevice())
19 
21 {
22  RunProlog();
24  RunEpilog();
25 }
26 
27 const uint FirewireSignalMonitor::kPowerTimeout = 3000; /* ms */
28 const uint FirewireSignalMonitor::kBufferTimeout = 5000; /* ms */
29 
30 QMap<void*,uint> FirewireSignalMonitor::s_pat_keys;
32 
48  FirewireChannel *_channel,
49  bool _release_stream,
50  uint64_t _flags)
51  : DTVSignalMonitor(db_cardnum, _channel, _release_stream, _flags)
52 {
53  LOG(VB_CHANNEL, LOG_INFO, LOC + "ctor");
54 
56 
58 
61 }
62 
67 {
68  LOG(VB_CHANNEL, LOG_INFO, LOC + "dtor");
70 }
71 
76 {
77  LOG(VB_CHANNEL, LOG_INFO, LOC + "Stop() -- begin");
80  {
81  m_dtvMonitorRunning = false;
83  delete m_tableMonitorThread;
84  m_tableMonitorThread = nullptr;
85  }
86  LOG(VB_CHANNEL, LOG_INFO, LOC + "Stop() -- end");
87 }
88 
90 {
92 
93  auto *fwchan = dynamic_cast<FirewireChannel*>(m_channel);
94  if (!fwchan)
95  return;
96 
97  bool crc_bogus = !fwchan->GetFirewireDevice()->IsSTBBufferCleared();
98  if (crc_bogus && m_stb_needs_to_wait_for_pat &&
100  {
101  LOG(VB_CHANNEL, LOG_INFO, LOC + "HandlePAT() ignoring PAT");
102  uint tsid = pat->TransportStreamID();
103  GetStreamData()->SetVersionPAT(tsid, -1,0);
104  return;
105  }
106 
107  if (crc_bogus && m_stb_needs_to_wait_for_pat)
108  {
109  LOG(VB_GENERAL, LOG_WARNING, LOC + "Wait for valid PAT timed out");
111  }
112 
114 }
115 
117 {
118  LOG(VB_CHANNEL, LOG_INFO, LOC + "HandlePMT()");
119 
121 
123  {
124  GetStreamData()->SetVersionPMT(pnum, -1,0);
125  LOG(VB_CHANNEL, LOG_INFO, LOC + "HandlePMT() ignoring PMT");
126  return;
127  }
128 
129  DTVSignalMonitor::HandlePMT(pnum, pmt);
130 }
131 
133 {
136  m_dtvMonitorRunning = true;
137 
138  LOG(VB_CHANNEL, LOG_INFO, LOC + "RunTableMonitor(): -- begin");
139 
140  auto *lchan = dynamic_cast<FirewireChannel*>(m_channel);
141  if (!lchan)
142  {
143  LOG(VB_CHANNEL, LOG_INFO, LOC + "RunTableMonitor(): -- err");
144  while (m_dtvMonitorRunning)
145  std::this_thread::sleep_for(std::chrono::milliseconds(10));
146 
147  LOG(VB_CHANNEL, LOG_INFO, LOC + "RunTableMonitor(): -- err end");
148  return;
149  }
150 
151  FirewireDevice *dev = lchan->GetFirewireDevice();
152 
153  dev->OpenPort();
154  dev->AddListener(this);
155 
157  std::this_thread::sleep_for(std::chrono::milliseconds(10));
158 
159  LOG(VB_CHANNEL, LOG_INFO, LOC + "RunTableMonitor(): -- shutdown ");
160 
161  dev->RemoveListener(this);
162  dev->ClosePort();
163 
164  while (m_dtvMonitorRunning)
165  std::this_thread::sleep_for(std::chrono::milliseconds(10));
166 
167  LOG(VB_CHANNEL, LOG_INFO, LOC + "RunTableMonitor(): -- end");
168 }
169 
170 void FirewireSignalMonitor::AddData(const unsigned char *data, uint len)
171 {
172  if (!m_dtvMonitorRunning)
173  return;
174 
175  if (GetStreamData())
176  GetStreamData()->ProcessData((unsigned char *)data, len);
177 }
178 
190 {
191  if (!m_running || m_exit)
192  return;
193 
195  {
196  EmitStatus();
197  if (IsAllGood())
199  // TODO dtv signals...
200 
201  m_update_done = true;
202  return;
203  }
204 
207  {
208  return;
209  }
211 
212  auto *fwchan = dynamic_cast<FirewireChannel*>(m_channel);
213  if (!fwchan)
214  return;
215 
217  {
218  bool retried = false;
219  while (true)
220  {
221  FirewireDevice::PowerState power = fwchan->GetPowerState();
222  if (FirewireDevice::kAVCPowerOn == power)
223  {
225  }
226  else if (FirewireDevice::kAVCPowerOff == power)
227  {
229  fwchan->SetPowerState(true);
232  }
233  else
234  {
235  bool qfailed = (FirewireDevice::kAVCPowerQueryFailed == power);
236  if (qfailed && !retried)
237  {
238  retried = true;
239  continue;
240  }
241 
242  LOG(VB_RECORD, LOG_WARNING,
243  "Can't determine if STB is power on, assuming it is...");
245  }
246  break;
247  }
248  }
249 
250  bool isLocked = !HasFlags(kFWSigMon_WaitForPower) ||
252 
253  if (isLocked && m_stb_needs_retune)
254  {
255  fwchan->Retune();
256  isLocked = m_stb_needs_retune = false;
257  }
258 
260 
261  {
262  QMutexLocker locker(&m_statusLock);
263  if (!m_scriptStatus.IsGood())
264  return;
265  }
266 
267  // Set SignalMonitorValues from info from card.
268  {
269  QMutexLocker locker(&m_statusLock);
270  m_signalStrength.SetValue(isLocked ? 100 : 0);
271  m_signalLock.SetValue(isLocked ? 1 : 0);
272  }
273 
274  EmitStatus();
275  if (IsAllGood())
277 
278  // Start table monitoring if we are waiting on any table
279  // and we have a lock.
280  if (isLocked && GetStreamData() &&
284  {
286 
287  LOG(VB_CHANNEL, LOG_INFO, LOC + "UpdateValues() -- "
288  "Waiting for table monitor to start");
289 
290  while (!m_dtvMonitorRunning)
291  std::this_thread::sleep_for(std::chrono::milliseconds(5));
292 
293  LOG(VB_CHANNEL, LOG_INFO, LOC + "UpdateValues() -- "
294  "Table monitor started");
295  }
296 
297  m_update_done = true;
298 }
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:215
SignalMonitorValue m_scriptStatus
QMutex m_statusLock
void HandlePMT(uint program_num, const ProgramMapTable *pmt) override
static const uint kPowerTimeout
static const uint64_t kDTVSigMon_PATSeen
We've seen a PAT, which maps MPEG program numbers to pids where we find PMTs.
virtual void RemoveListener(TSDataListener *listener)
static const uint kBufferTimeout
static const uint64_t kDTVSigMon_WaitForPMT
static const uint64_t kDTVSigMon_WaitForPAT
bool wait(unsigned long time=ULONG_MAX)
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:311
bool HasAnyFlag(uint64_t _flags) const
static const uint64_t kFWSigMon_PowerMatch
We've seen a FireWire STB power state matching our requirements.
static const uint64_t kDTVSigMon_PMTSeen
We've seen a PMT, which maps program to audio, video and other stream PIDs.
void AddData(const unsigned char *data, uint len) override
Callback function to add MPEG2 TS data.
static const uint64_t kDTVSigMon_WaitForVCT
static const uint64_t kDTVSigMon_WaitForMGT
FirewireSignalMonitor * m_parent
virtual void AddListener(TSDataListener *listener)
void SetVersionPMT(uint pnum, int version, uint last_section)
void SetValue(int _value)
static const uint64_t kDTVSigMon_WaitForNIT
Overall structure.
void HandlePMT(uint pnum, const ProgramMapTable *pmt) override
virtual void Stop()
Stop signal monitoring thread.
static const uint64_t kSigMon_WaitForSig
ChannelBase * m_channel
virtual FirewireDevice::PowerState GetPowerState(void) const
volatile bool m_exit
FirewireChannel Copyright (c) 2005 by Jim Westfall and Dave Abrahams Distributed as part of MythTV un...
static const uint64_t kFWSigMon_PowerSeen
We've seen the FireWire STB power state.
MPEGStreamData * GetStreamData()
Returns the MPEG stream data if it exists.
void HandlePAT(const ProgramAssociationTable *pat) override
#define LOC
unsigned int uint
Definition: compat.h:140
void SendMessageAllGood(void)
volatile bool m_running
virtual int ProcessData(const unsigned char *buffer, int len)
The Program Association Table lists all the programs in a stream, and is always found on PID 0.
Definition: mpegtables.h:589
uint TransportStreamID(void) const
Definition: mpegtables.h:608
static const uint64_t kDTVSigMon_PATMatch
We've seen a PAT matching our requirements.
static QMap< void *, uint > s_pat_keys
This class is intended to detect the presence of needed tables.
void Stop(void) override
Stop signal monitoring and table monitoring threads.
void AddFlags(uint64_t _flags) override
void SetVersionPAT(uint tsid, int version, uint last_section)
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
bool IsAllGood(void) const override
void HandlePAT(const ProgramAssociationTable *pat) override
SignalMonitorValue m_signalStrength
int elapsed(void)
Returns milliseconds elapsed since last start() or restart()
Definition: mythtimer.cpp:90
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:202
static const uint64_t kDTVSigMon_WaitForSDT
static const uint64_t kFWSigMon_WaitForPower
virtual bool ClosePort(void)=0
FirewireTableMonitorThread * m_tableMonitorThread
virtual bool OpenPort(void)=0
void run(void) override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
bool IsGood() const
Returns true if the value is equal to the threshold, or on the right side of the threshold (depends o...
friend class FirewireTableMonitorThread
~FirewireSignalMonitor() override
Stops signal monitoring and table monitoring threads.
void SetThreshold(int _threshold)
void UpdateValues(void) override
Fills in frontend stats and emits status Qt signals.
A PMT table maps a program described in the ProgramAssociationTable to various PID's which describe t...
Definition: mpegtables.h:666
void start(void)
starts measuring elapsed time.
Definition: mythtimer.cpp:47
SignalMonitorValue m_signalLock
virtual void EmitStatus(void)
virtual void UpdateValues(void)
This should be overridden to actually do signal monitoring.
bool HasFlags(uint64_t _flags) const