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 
9 #ifdef USING_V4L1
10 #include <linux/videodev.h>
11 #endif // USING_V4L1
12 
13 #include "mythlogging.h"
14 #include "analogsignalmonitor.h"
15 #include "v4lchannel.h"
16 
17 #define LOC QString("AnalogSigMon[%1](%2): ") \
18  .arg(m_inputid).arg(m_channel->GetDevice())
19 
21  V4LChannel *_channel,
22  bool _release_stream,
23  uint64_t _flags)
24  : SignalMonitor(db_cardnum, _channel, _release_stream, _flags)
25 {
26  int videofd = m_channel->GetFd();
27  if (videofd >= 0)
28  {
29  uint32_t caps = 0;
30  if (!CardUtil::GetV4LInfo(videofd, m_card, m_driver, m_version, caps))
31  return;
32 
33  m_usingV4l2 = ((caps & V4L2_CAP_VIDEO_CAPTURE) != 0U);
34  LOG(VB_RECORD, LOG_INFO, QString("card '%1' driver '%2' version '%3'")
35  .arg(m_card, m_driver, QString::number(m_version)));
36  }
37 }
38 
40 {
41  struct v4l2_queryctrl qctrl {};
42  qctrl.id = V4L2_CID_MPEG_AUDIO_ENCODING;
43 
44  int audtype = V4L2_MPEG_AUDIO_ENCODING_AC3;
45 
46  if (ioctl(videofd, VIDIOC_QUERYCTRL, &qctrl) != 0)
47  {
48  LOG(VB_GENERAL, LOG_ERR, LOC +
49  "Unable to get supported audio codecs for verification." + ENO);
50  return false;
51  }
52 
53  struct v4l2_ext_control ext_ctrl {};
54  struct v4l2_ext_controls ext_ctrls {};
55 
56  ext_ctrl.id = V4L2_CID_MPEG_AUDIO_ENCODING;
57 
58  ext_ctrls.reserved[0] = 0;
59  ext_ctrls.count = 1;
60  ext_ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
61  ext_ctrls.controls = &ext_ctrl;
62 
63  if (ioctl(videofd, VIDIOC_G_EXT_CTRLS, &ext_ctrls) != 0)
64  {
65  LOG(VB_GENERAL, LOG_ERR, LOC +
66  "Unable to get current audio codecs for verification." + ENO);
67  return false;
68  }
69 
70  int current_audio = ext_ctrls.controls->value;
71 
72  if (audtype != current_audio)
73  {
74  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Audio desired %1, current %2 "
75  "min %3 max %4")
76  .arg(audtype)
77  .arg(current_audio)
78  .arg(qctrl.minimum)
79  .arg(qctrl.maximum)
80  );
81 
82  ext_ctrl.id = V4L2_CID_MPEG_AUDIO_ENCODING;
83  ext_ctrl.value = audtype;
84  if (ioctl(videofd, VIDIOC_S_EXT_CTRLS, &ext_ctrls) == 0)
85  {
86  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Changed audio encoding "
87  "from %1 to %2.")
88  .arg(current_audio)
89  .arg(audtype)
90  );
91  }
92  else
93  {
94  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to changed audio "
95  "encoding from %1 to %2.")
96  .arg(current_audio)
97  .arg(audtype)
98  + ENO
99  );
100  }
101 
102  return false;
103  }
104 
105  return true;
106 }
107 
108 /* m_stableTime is used to designate how long we need to see a stable
109  * resolution reported from the HD-PVR driver, before we consider it a
110  * good lock. In my testing 2 seconds is safe, while 1 second worked
111  * most of the time. --jp
112  */
114 {
115  struct v4l2_format vfmt {};
116  vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
117 
118  if ((ioctl(videofd, VIDIOC_G_FMT, &vfmt) == 0) &&
119  vfmt.fmt.pix.width && m_width == vfmt.fmt.pix.width &&
120  VerifyHDPVRaudio(videofd))
121  {
122  if (!m_timer.isRunning())
123  {
124  LOG(VB_RECORD, LOG_ERR, QString("hd-pvr resolution %1 x %2")
125  .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
126  ++m_lockCnt;
127  m_timer.start();
128  }
129  else if (m_timer.elapsed() > m_stableTime)
130  {
131  LOG(VB_RECORD, LOG_ERR, QString("hd-pvr stable at %1 x %2")
132  .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
133  m_timer.stop();
134  return true;
135  }
136  else
137  {
138  QMutexLocker locker(&m_statusLock);
140  }
141  }
142  else
143  {
144  if (--m_logIdx == 0)
145  {
146  LOG(VB_RECORD, LOG_ERR, "hd-pvr waiting for valid resolution");
147  m_logIdx = 40;
148  }
149  m_width = vfmt.fmt.pix.width;
150  m_timer.stop();
151  QMutexLocker locker(&m_statusLock);
153  }
154 
155  return false;
156 }
157 
159 {
161 
162  {
163  QMutexLocker locker(&m_statusLock);
164  if (!m_scriptStatus.IsGood())
165  return;
166  }
167 
168  if (!m_running || m_exit)
169  return;
170 
171  int videofd = m_channel->GetFd();
172  if (videofd < 0)
173  return;
174 
175  bool isLocked = false;
176  if (m_usingV4l2)
177  {
178  if (m_driver == "hdpvr")
179  isLocked = handleHDPVR(videofd);
180  else
181  {
182  struct v4l2_tuner tuner {};
183 
184  if (ioctl(videofd, VIDIOC_G_TUNER, &tuner, 0) < 0)
185  {
186  LOG(VB_GENERAL, LOG_ERR, "Failed to probe signal (v4l2)" + ENO);
187  }
188  else
189  {
190  isLocked = (tuner.signal != 0);
191  }
192  }
193  }
194 #ifdef USING_V4L1
195  else
196  {
197  struct video_tuner tuner;
198  memset(&tuner, 0, sizeof(tuner));
199 
200  if (ioctl(videofd, VIDIOCGTUNER, &tuner, 0) < 0)
201  {
202  LOG(VB_GENERAL, LOG_ERR, "Failed to probe signal (v4l1)" + ENO);
203  }
204  else
205  {
206  isLocked = tuner.signal;
207  }
208  }
209 #endif // USING_V4L1
210 
211  {
212  QMutexLocker locker(&m_statusLock);
213  m_signalLock.SetValue(static_cast<int>(isLocked));
214  if (isLocked)
216  }
217 
218  EmitStatus();
219  if (IsAllGood())
221 }
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:72
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:85
SignalMonitor::m_channel
ChannelBase * m_channel
Definition: signalmonitor.h:205
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:229
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:23
AnalogSignalMonitor::m_timer
MythTimer m_timer
Definition: analogsignalmonitor.h:32
SignalMonitor::m_running
volatile bool m_running
Definition: signalmonitor.h:228
AnalogSignalMonitor::AnalogSignalMonitor
AnalogSignalMonitor(int db_cardnum, V4LChannel *_channel, bool _release_stream, uint64_t _flags=kSigMon_WaitForSig)
Definition: analogsignalmonitor.cpp:20
SignalMonitor::m_statusLock
QRecursiveMutex m_statusLock
Definition: signalmonitor.h:234
SignalMonitor::m_scriptStatus
SignalMonitorValue m_scriptStatus
Definition: signalmonitor.h:222
AnalogSignalMonitor::UpdateValues
void UpdateValues(void) override
This should be overridden to actually do signal monitoring.
Definition: analogsignalmonitor.cpp:158
AnalogSignalMonitor::m_width
uint m_width
Definition: analogsignalmonitor.h:29
AnalogSignalMonitor::handleHDPVR
bool handleHDPVR(int videofd)
Definition: analogsignalmonitor.cpp:113
SignalMonitor::m_signalStrength
SignalMonitorValue m_signalStrength
Definition: signalmonitor.h:221
mythlogging.h
CardUtil::GetV4LInfo
static bool GetV4LInfo(int videofd, QString &input, QString &driver, uint32_t &version, uint32_t &capabilities)
Definition: cardutil.cpp:2246
SignalMonitor::m_signalLock
SignalMonitorValue m_signalLock
Definition: signalmonitor.h:220
SignalMonitor::SendMessageAllGood
void SendMessageAllGood(void)
Definition: signalmonitor.cpp:467
v4lchannel.h
SignalMonitor::EmitStatus
virtual void EmitStatus(void)
Definition: signalmonitor.cpp:474
SignalMonitor::UpdateValues
virtual void UpdateValues(void)
This should be overridden to actually do signal monitoring.
Definition: signalmonitor.cpp:458
SignalMonitor
Signal monitoring base class.
Definition: signalmonitor.h:34
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:39
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:17
AnalogSignalMonitor::m_driver
QString m_driver
Definition: analogsignalmonitor.h:27