MythTV  master
analogsignalmonitor.cpp
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 // Copyright (c) 2005, Daniel Thor Kristjansson
3 
4 #include <cerrno>
5 #include <unistd.h>
6 #include <sys/ioctl.h>
7 #include <poll.h>
8 
10 #include "analogsignalmonitor.h"
11 #include "v4lchannel.h"
12 
13 #define LOC QString("AnalogSigMon[%1](%2): ") \
14  .arg(m_inputid).arg(m_channel->GetDevice())
15 
17  V4LChannel *_channel,
18  bool _release_stream,
19  uint64_t _flags)
20  : SignalMonitor(db_cardnum, _channel, _release_stream, _flags)
21 {
22  int videofd = m_channel->GetFd();
23  if (videofd >= 0)
24  {
25  uint32_t caps = 0;
26  if (!CardUtil::GetV4LInfo(videofd, m_card, m_driver, m_version, caps))
27  return;
28 
29  m_usingV4l2 = ((caps & V4L2_CAP_VIDEO_CAPTURE) != 0U);
30  LOG(VB_RECORD, LOG_INFO, QString("card '%1' driver '%2' version '%3'")
31  .arg(m_card, m_driver, QString::number(m_version)));
32  }
33 }
34 
36 {
37  struct v4l2_queryctrl qctrl {};
38  qctrl.id = V4L2_CID_MPEG_AUDIO_ENCODING;
39 
40  int audtype = V4L2_MPEG_AUDIO_ENCODING_AC3;
41 
42  if (ioctl(videofd, VIDIOC_QUERYCTRL, &qctrl) != 0)
43  {
44  LOG(VB_GENERAL, LOG_ERR, LOC +
45  "Unable to get supported audio codecs for verification." + ENO);
46  return false;
47  }
48 
49  struct v4l2_ext_control ext_ctrl {};
50  struct v4l2_ext_controls ext_ctrls {};
51 
52  ext_ctrl.id = V4L2_CID_MPEG_AUDIO_ENCODING;
53 
54  ext_ctrls.reserved[0] = 0;
55  ext_ctrls.count = 1;
56  ext_ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
57  ext_ctrls.controls = &ext_ctrl;
58 
59  if (ioctl(videofd, VIDIOC_G_EXT_CTRLS, &ext_ctrls) != 0)
60  {
61  LOG(VB_GENERAL, LOG_ERR, LOC +
62  "Unable to get current audio codecs for verification." + ENO);
63  return false;
64  }
65 
66  int current_audio = ext_ctrls.controls->value;
67 
68  if (audtype != current_audio)
69  {
70  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Audio desired %1, current %2 "
71  "min %3 max %4")
72  .arg(audtype)
73  .arg(current_audio)
74  .arg(qctrl.minimum)
75  .arg(qctrl.maximum)
76  );
77 
78  ext_ctrl.id = V4L2_CID_MPEG_AUDIO_ENCODING;
79  ext_ctrl.value = audtype;
80  if (ioctl(videofd, VIDIOC_S_EXT_CTRLS, &ext_ctrls) == 0)
81  {
82  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Changed audio encoding "
83  "from %1 to %2.")
84  .arg(current_audio)
85  .arg(audtype)
86  );
87  }
88  else
89  {
90  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to changed audio "
91  "encoding from %1 to %2.")
92  .arg(current_audio)
93  .arg(audtype)
94  + ENO
95  );
96  }
97 
98  return false;
99  }
100 
101  return true;
102 }
103 
104 /* m_stableTime is used to designate how long we need to see a stable
105  * resolution reported from the HD-PVR driver, before we consider it a
106  * good lock. In my testing 2 seconds is safe, while 1 second worked
107  * most of the time. --jp
108  */
110 {
111  struct v4l2_format vfmt {};
112  vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
113 
114  if ((ioctl(videofd, VIDIOC_G_FMT, &vfmt) == 0) &&
115  vfmt.fmt.pix.width && m_width == vfmt.fmt.pix.width &&
116  VerifyHDPVRaudio(videofd))
117  {
118  if (!m_timer.isRunning())
119  {
120  LOG(VB_RECORD, LOG_ERR, QString("hd-pvr resolution %1 x %2")
121  .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
122  ++m_lockCnt;
123  m_timer.start();
124  }
125  else if (m_timer.elapsed() > m_stableTime)
126  {
127  LOG(VB_RECORD, LOG_ERR, QString("hd-pvr stable at %1 x %2")
128  .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
129  m_timer.stop();
130  return true;
131  }
132  else
133  {
134  QMutexLocker locker(&m_statusLock);
136  }
137  }
138  else
139  {
140  if (--m_logIdx == 0)
141  {
142  LOG(VB_RECORD, LOG_ERR, "hd-pvr waiting for valid resolution");
143  m_logIdx = 40;
144  }
145  m_width = vfmt.fmt.pix.width;
146  m_timer.stop();
147  QMutexLocker locker(&m_statusLock);
149  }
150 
151  return false;
152 }
153 
155 {
157 
158  {
159  QMutexLocker locker(&m_statusLock);
160  if (!m_scriptStatus.IsGood())
161  return;
162  }
163 
164  if (!m_running || m_exit)
165  return;
166 
167  int videofd = m_channel->GetFd();
168  if (videofd < 0)
169  return;
170 
171  bool isLocked = false;
172  if (m_usingV4l2)
173  {
174  if (m_driver == "hdpvr")
175  isLocked = handleHDPVR(videofd);
176  else
177  {
178  struct v4l2_tuner tuner {};
179 
180  if (ioctl(videofd, VIDIOC_G_TUNER, &tuner, 0) < 0)
181  {
182  LOG(VB_GENERAL, LOG_ERR, "Failed to probe signal (v4l2)" + ENO);
183  }
184  else
185  {
186  isLocked = (tuner.signal != 0);
187  }
188  }
189  }
190 
191  {
192  QMutexLocker locker(&m_statusLock);
193  m_signalLock.SetValue(static_cast<int>(isLocked));
194  if (isLocked)
196  }
197 
198  EmitStatus();
199  if (IsAllGood())
201 }
AnalogSignalMonitor::m_logIdx
int m_logIdx
Definition: analogsignalmonitor.h:33
MythTimer::elapsed
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
Definition: mythtimer.cpp:91
ENO
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:73
analogsignalmonitor.h
AnalogSignalMonitor::m_stableTime
std::chrono::milliseconds m_stableTime
Definition: analogsignalmonitor.h:30
SignalMonitorValue::SetValue
void SetValue(int _value)
Definition: signalmonitorvalue.h:74
SignalMonitor::IsAllGood
virtual bool IsAllGood(void) const
Definition: signalmonitor.h:81
SignalMonitor::m_channel
ChannelBase * m_channel
Definition: signalmonitor.h:201
MythTimer::stop
void stop(void)
Stops timer, next call to isRunning() will return false and any calls to elapsed() or restart() will ...
Definition: mythtimer.cpp:78
SignalMonitor::m_exit
volatile bool m_exit
Definition: signalmonitor.h:225
MythTimer::isRunning
bool isRunning(void) const
Returns true if start() or restart() has been called at least once since construction and since any c...
Definition: mythtimer.cpp:135
AnalogSignalMonitor::m_lockCnt
uint m_lockCnt
Definition: analogsignalmonitor.h:31
AnalogSignalMonitor::m_card
QString m_card
Definition: analogsignalmonitor.h:26
MythTimer::start
void start(void)
starts measuring elapsed time.
Definition: mythtimer.cpp:47
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
AnalogSignalMonitor::m_timer
MythTimer m_timer
Definition: analogsignalmonitor.h:32
SignalMonitor::m_running
volatile bool m_running
Definition: signalmonitor.h:224
AnalogSignalMonitor::AnalogSignalMonitor
AnalogSignalMonitor(int db_cardnum, V4LChannel *_channel, bool _release_stream, uint64_t _flags=kSigMon_WaitForSig)
Definition: analogsignalmonitor.cpp:16
SignalMonitor::m_statusLock
QRecursiveMutex m_statusLock
Definition: signalmonitor.h:227
SignalMonitor::m_scriptStatus
SignalMonitorValue m_scriptStatus
Definition: signalmonitor.h:218
AnalogSignalMonitor::UpdateValues
void UpdateValues(void) override
This should be overridden to actually do signal monitoring.
Definition: analogsignalmonitor.cpp:154
AnalogSignalMonitor::m_width
uint m_width
Definition: analogsignalmonitor.h:29
AnalogSignalMonitor::handleHDPVR
bool handleHDPVR(int videofd)
Definition: analogsignalmonitor.cpp:109
SignalMonitor::m_signalStrength
SignalMonitorValue m_signalStrength
Definition: signalmonitor.h:217
mythlogging.h
CardUtil::GetV4LInfo
static bool GetV4LInfo(int videofd, QString &input, QString &driver, uint32_t &version, uint32_t &capabilities)
Definition: cardutil.cpp:2351
SignalMonitor::m_signalLock
SignalMonitorValue m_signalLock
Definition: signalmonitor.h:216
SignalMonitor::SendMessageAllGood
void SendMessageAllGood(void)
Definition: signalmonitor.cpp:465
v4lchannel.h
SignalMonitor::EmitStatus
virtual void EmitStatus(void)
Definition: signalmonitor.cpp:472
SignalMonitor::UpdateValues
virtual void UpdateValues(void)
This should be overridden to actually do signal monitoring.
Definition: signalmonitor.cpp:456
SignalMonitor
Signal monitoring base class.
Definition: signalmonitor.h:30
SignalMonitorValue::IsGood
bool IsGood() const
Returns true if the value is equal to the threshold, or on the right side of the threshold (depends o...
Definition: signalmonitorvalue.h:56
AnalogSignalMonitor::m_usingV4l2
bool m_usingV4l2
Definition: analogsignalmonitor.h:25
AnalogSignalMonitor::VerifyHDPVRaudio
bool VerifyHDPVRaudio(int videofd)
Definition: analogsignalmonitor.cpp:35
ChannelBase::GetFd
virtual int GetFd(void) const
Returns file descriptor, -1 if it does not exist.
Definition: channelbase.h:57
AnalogSignalMonitor::m_version
uint32_t m_version
Definition: analogsignalmonitor.h:28
V4LChannel
Implements tuning for TV cards using the V4L driver API, both versions 1 and 2.
Definition: v4lchannel.h:30
LOC
#define LOC
Definition: analogsignalmonitor.cpp:13
AnalogSignalMonitor::m_driver
QString m_driver
Definition: analogsignalmonitor.h:27