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(inputid).arg(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::pat_keys;
32 
48  FirewireChannel *_channel,
49  bool _release_stream,
50  uint64_t _flags)
51  : DTVSignalMonitor(db_cardnum, _channel, _release_stream, _flags),
52  dtvMonitorRunning(false),
53  tableMonitorThread(nullptr),
54  stb_needs_retune(true),
55  stb_needs_to_wait_for_pat(false),
56  stb_needs_to_wait_for_power(false)
57 {
58  LOG(VB_CHANNEL, LOG_INFO, LOC + "ctor");
59 
61 
63 
66 }
67 
72 {
73  LOG(VB_CHANNEL, LOG_INFO, LOC + "dtor");
74  Stop();
75 }
76 
81 {
82  LOG(VB_CHANNEL, LOG_INFO, LOC + "Stop() -- begin");
85  {
86  dtvMonitorRunning = false;
88  delete tableMonitorThread;
89  tableMonitorThread = nullptr;
90  }
91  LOG(VB_CHANNEL, LOG_INFO, LOC + "Stop() -- end");
92 }
93 
95 {
97 
98  FirewireChannel *fwchan = dynamic_cast<FirewireChannel*>(channel);
99  if (!fwchan)
100  return;
101 
102  bool crc_bogus = !fwchan->GetFirewireDevice()->IsSTBBufferCleared();
103  if (crc_bogus && stb_needs_to_wait_for_pat &&
105  {
106  LOG(VB_CHANNEL, LOG_INFO, LOC + "HandlePAT() ignoring PAT");
107  uint tsid = pat->TransportStreamID();
108  GetStreamData()->SetVersionPAT(tsid, -1,0);
109  return;
110  }
111 
112  if (crc_bogus && stb_needs_to_wait_for_pat)
113  {
114  LOG(VB_GENERAL, LOG_WARNING, LOC + "Wait for valid PAT timed out");
116  }
117 
119 }
120 
122 {
123  LOG(VB_CHANNEL, LOG_INFO, LOC + "HandlePMT()");
124 
126 
128  {
129  GetStreamData()->SetVersionPMT(pnum, -1,0);
130  LOG(VB_CHANNEL, LOG_INFO, LOC + "HandlePMT() ignoring PMT");
131  return;
132  }
133 
134  DTVSignalMonitor::HandlePMT(pnum, pmt);
135 }
136 
138 {
141  dtvMonitorRunning = true;
142 
143  LOG(VB_CHANNEL, LOG_INFO, LOC + "RunTableMonitor(): -- begin");
144 
145  FirewireChannel *lchan = dynamic_cast<FirewireChannel*>(channel);
146  if (!lchan)
147  {
148  LOG(VB_CHANNEL, LOG_INFO, LOC + "RunTableMonitor(): -- err");
149  while (dtvMonitorRunning)
150  std::this_thread::sleep_for(std::chrono::milliseconds(10));
151 
152  LOG(VB_CHANNEL, LOG_INFO, LOC + "RunTableMonitor(): -- err end");
153  return;
154  }
155 
156  FirewireDevice *dev = lchan->GetFirewireDevice();
157 
158  dev->OpenPort();
159  dev->AddListener(this);
160 
161  while (dtvMonitorRunning && GetStreamData())
162  std::this_thread::sleep_for(std::chrono::milliseconds(10));
163 
164  LOG(VB_CHANNEL, LOG_INFO, LOC + "RunTableMonitor(): -- shutdown ");
165 
166  dev->RemoveListener(this);
167  dev->ClosePort();
168 
169  while (dtvMonitorRunning)
170  std::this_thread::sleep_for(std::chrono::milliseconds(10));
171 
172  LOG(VB_CHANNEL, LOG_INFO, LOC + "RunTableMonitor(): -- end");
173 }
174 
175 void FirewireSignalMonitor::AddData(const unsigned char *data, uint len)
176 {
177  if (!dtvMonitorRunning)
178  return;
179 
180  if (GetStreamData())
181  GetStreamData()->ProcessData((unsigned char *)data, len);
182 }
183 
195 {
196  if (!running || exit)
197  return;
198 
199  if (dtvMonitorRunning)
200  {
201  EmitStatus();
202  if (IsAllGood())
204  // TODO dtv signals...
205 
206  update_done = true;
207  return;
208  }
209 
212  {
213  return;
214  }
216 
217  FirewireChannel *fwchan = dynamic_cast<FirewireChannel*>(channel);
218  if (!fwchan)
219  return;
220 
222  {
223  bool retried = false;
224  while (true)
225  {
226  FirewireDevice::PowerState power = fwchan->GetPowerState();
227  if (FirewireDevice::kAVCPowerOn == power)
228  {
230  }
231  else if (FirewireDevice::kAVCPowerOff == power)
232  {
234  fwchan->SetPowerState(true);
237  }
238  else
239  {
240  bool qfailed = (FirewireDevice::kAVCPowerQueryFailed == power);
241  if (qfailed && !retried)
242  {
243  retried = true;
244  continue;
245  }
246 
247  LOG(VB_RECORD, LOG_WARNING,
248  "Can't determine if STB is power on, assuming it is...");
250  }
251  break;
252  }
253  }
254 
255  bool isLocked = !HasFlags(kFWSigMon_WaitForPower) ||
257 
258  if (isLocked && stb_needs_retune)
259  {
260  fwchan->Retune();
261  isLocked = stb_needs_retune = false;
262  }
263 
265 
266  {
267  QMutexLocker locker(&statusLock);
268  if (!scriptStatus.IsGood())
269  return;
270  }
271 
272  // Set SignalMonitorValues from info from card.
273  {
274  QMutexLocker locker(&statusLock);
275  signalStrength.SetValue(isLocked ? 100 : 0);
276  signalLock.SetValue(isLocked ? 1 : 0);
277  }
278 
279  EmitStatus();
280  if (IsAllGood())
282 
283  // Start table monitoring if we are waiting on any table
284  // and we have a lock.
285  if (isLocked && GetStreamData() &&
289  {
291 
292  LOG(VB_CHANNEL, LOG_INFO, LOC + "UpdateValues() -- "
293  "Waiting for table monitor to start");
294 
295  while (!dtvMonitorRunning)
296  std::this_thread::sleep_for(std::chrono::milliseconds(5));
297 
298  LOG(VB_CHANNEL, LOG_INFO, LOC + "UpdateValues() -- "
299  "Table monitor started");
300  }
301 
302  update_done = true;
303 }
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:216
void HandlePMT(uint, const ProgramMapTable *) override
void HandlePAT(const ProgramAssociationTable *) 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.
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:91
FirewireTableMonitorThread * tableMonitorThread
static const uint kBufferTimeout
static const uint64_t kDTVSigMon_WaitForPMT
static const uint64_t kDTVSigMon_WaitForPAT
virtual ~FirewireSignalMonitor()
Stops signal monitoring and table monitoring threads.
bool wait(unsigned long time=ULONG_MAX)
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:312
bool HasAnyFlag(uint64_t _flags) const
static const uint64_t kFWSigMon_PowerMatch
We've seen a FireWire STB power state matching our requirements.
unsigned int uint
Definition: compat.h:140
static const uint64_t kDTVSigMon_PMTSeen
We've seen a PMT, which maps program to audio, video and other stream PIDs.
void HandlePMT(uint, const ProgramMapTable *) override
static const uint64_t kDTVSigMon_WaitForVCT
static const uint64_t kDTVSigMon_WaitForMGT
FirewireSignalMonitor * m_parent
SignalMonitorValue signalLock
void SetVersionPMT(uint pnum, int version, uint last_section)
void SetValue(int _value)
bool Retune(void) override
static const uint64_t kDTVSigMon_WaitForNIT
Overall structure.
virtual void Stop()
Stop signal monitoring thread.
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:85
static const uint64_t kSigMon_WaitForSig
virtual FirewireDevice::PowerState GetPowerState(void) const
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.
#define LOC
void SendMessageAllGood(void)
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:579
uint TransportStreamID(void) const
Definition: mpegtables.h:598
void HandlePAT(const ProgramAssociationTable *) override
static const uint64_t kDTVSigMon_PATMatch
We've seen a PAT matching our requirements.
int elapsed(void) const
Returns milliseconds elapsed since last start() or restart()
Definition: mythtimer.cpp:90
This class is intended to detect the presence of needed tables.
void Stop(void) override
Stop signal monitoring and table monitoring threads.
virtual FirewireDevice * GetFirewireDevice(void)
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
virtual void RemoveListener(TSDataListener *)
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:203
static const uint64_t kDTVSigMon_WaitForSDT
SignalMonitorValue signalStrength
static const uint64_t kFWSigMon_WaitForPower
SignalMonitorValue scriptStatus
static QMap< void *, uint > pat_keys
ChannelBase * channel
virtual bool ClosePort(void)=0
volatile bool running
virtual bool OpenPort(void)=0
virtual void AddListener(TSDataListener *)
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
volatile bool exit
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:656
void start(void)
starts measuring elapsed time.
Definition: mythtimer.cpp:47
virtual void EmitStatus(void)
virtual void UpdateValues(void)
This should be overridden to actually do signal monitoring.
bool IsSTBBufferCleared(void) const
bool HasFlags(uint64_t _flags) const
virtual bool SetPowerState(bool on)
void AddData(const unsigned char *data, uint dataSize) override
Callback function to add MPEG2 TS data.