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}
#define LOC
bool VerifyHDPVRaudio(int videofd)
bool handleHDPVR(int videofd)
AnalogSignalMonitor(int db_cardnum, V4LChannel *_channel, bool _release_stream, uint64_t _flags=kSigMon_WaitForSig)
void UpdateValues(void) override
This should be overridden to actually do signal monitoring.
std::chrono::milliseconds m_stableTime
static bool GetV4LInfo(int videofd, QString &input, QString &driver, uint32_t &version, uint32_t &capabilities)
Definition: cardutil.cpp:2355
virtual int GetFd(void) const
Returns file descriptor, -1 if it does not exist.
Definition: channelbase.h:57
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
Definition: mythtimer.cpp:91
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
void stop(void)
Stops timer, next call to isRunning() will return false and any calls to elapsed() or restart() will ...
Definition: mythtimer.cpp:78
void start(void)
starts measuring elapsed time.
Definition: mythtimer.cpp:47
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)
Signal monitoring base class.
Definition: signalmonitor.h:31
QRecursiveMutex m_statusLock
volatile bool m_exit
void SendMessageAllGood(void)
SignalMonitorValue m_signalLock
SignalMonitorValue m_scriptStatus
volatile bool m_running
ChannelBase * m_channel
virtual bool IsAllGood(void) const
Definition: signalmonitor.h:81
virtual void EmitStatus(void)
virtual void UpdateValues(void)
This should be overridden to actually do signal monitoring.
SignalMonitorValue m_signalStrength
Implements tuning for TV cards using the V4L driver API, both versions 1 and 2.
Definition: v4lchannel.h:32
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:74
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39