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