00001
00002
00003
00004 #include <cerrno>
00005 #include <unistd.h>
00006 #include <sys/ioctl.h>
00007 #include <poll.h>
00008
00009 #ifdef USING_V4L1
00010 #include <linux/videodev.h>
00011 #endif // USING_V4L1
00012
00013 #include "mythlogging.h"
00014 #include "analogsignalmonitor.h"
00015 #include "v4lchannel.h"
00016
00017 #define LOC QString("AnalogSM(%1): ").arg(channel->GetDevice())
00018
00019 AnalogSignalMonitor::AnalogSignalMonitor(
00020 int db_cardnum, V4LChannel *_channel, uint64_t _flags) :
00021 SignalMonitor(db_cardnum, _channel, _flags),
00022 m_usingv4l2(false), m_stage(0)
00023 {
00024 int videofd = channel->GetFd();
00025 if (videofd >= 0)
00026 {
00027 uint32_t caps;
00028 if (!CardUtil::GetV4LInfo(videofd, m_card, m_driver, m_version, caps))
00029 {
00030 videofd = -1;
00031 return;
00032 }
00033 m_usingv4l2 = !!(caps & V4L2_CAP_VIDEO_CAPTURE);
00034 LOG(VB_RECORD, LOG_INFO, QString("card '%1' driver '%2' version '%3'")
00035 .arg(m_card).arg(m_driver).arg(m_version));
00036 }
00037 }
00038
00039 bool AnalogSignalMonitor::handleHDPVR(int videofd)
00040 {
00041 struct v4l2_encoder_cmd command;
00042 struct pollfd polls;
00043
00044 if (m_stage == 0)
00045 {
00046 LOG(VB_RECORD, LOG_INFO, "hd-pvr start encoding");
00047
00048
00049 memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
00050 command.cmd = V4L2_ENC_CMD_START;
00051 if (ioctl(videofd, VIDIOC_ENCODER_CMD, &command) == 0)
00052 m_stage = 1;
00053 else
00054 {
00055 LOG(VB_GENERAL, LOG_ERR, "Start encoding failed" + ENO);
00056 command.cmd = V4L2_ENC_CMD_STOP;
00057 ioctl(videofd, VIDIOC_ENCODER_CMD, &command);
00058 }
00059 }
00060
00061 if (m_stage == 1)
00062 {
00063 LOG(VB_RECORD, LOG_INFO, "hd-pvr wait for data");
00064
00065 polls.fd = videofd;
00066 polls.events = POLLIN;
00067 polls.revents = 0;
00068
00069 if (poll(&polls, 1, 1500) > 0)
00070 {
00071 m_stage = 2;
00072 QMutexLocker locker(&statusLock);
00073 signalStrength.SetValue(25);
00074 }
00075 else
00076 {
00077 LOG(VB_RECORD, LOG_INFO, "Poll timed-out. Resetting");
00078 memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
00079 command.cmd = V4L2_ENC_CMD_STOP;
00080 ioctl(videofd, VIDIOC_ENCODER_CMD, &command);
00081 m_stage = 0;
00082
00083 QMutexLocker locker(&statusLock);
00084 signalStrength.SetValue(0);
00085 }
00086 }
00087
00088 if (m_stage == 2)
00089 {
00090 LOG(VB_RECORD, LOG_INFO, "hd-pvr data ready. Stop encoding");
00091
00092 command.cmd = V4L2_ENC_CMD_STOP;
00093 if (ioctl(videofd, VIDIOC_ENCODER_CMD, &command) == 0)
00094 m_stage = 3;
00095 else
00096 {
00097 QMutexLocker locker(&statusLock);
00098 signalStrength.SetValue(50);
00099 }
00100 }
00101
00102 if (m_stage == 3)
00103 {
00104 struct v4l2_format vfmt;
00105 memset(&vfmt, 0, sizeof(vfmt));
00106 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00107
00108 LOG(VB_RECORD, LOG_INFO, "hd-pvr waiting for valid resolution");
00109 if ((ioctl(videofd, VIDIOC_G_FMT, &vfmt) == 0) && vfmt.fmt.pix.width)
00110 {
00111 LOG(VB_RECORD, LOG_INFO, QString("hd-pvr resolution %1 x %2")
00112 .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
00113 m_stage = 4;
00114 }
00115 else
00116 {
00117 QMutexLocker locker(&statusLock);
00118 signalStrength.SetValue(75);
00119 }
00120 }
00121
00122 return (m_stage == 4);
00123 }
00124
00125 void AnalogSignalMonitor::UpdateValues(void)
00126 {
00127 SignalMonitor::UpdateValues();
00128
00129 {
00130 QMutexLocker locker(&statusLock);
00131 if (!scriptStatus.IsGood())
00132 return;
00133 }
00134
00135 if (!running || exit)
00136 return;
00137
00138 int videofd = channel->GetFd();
00139 if (videofd < 0)
00140 return;
00141
00142 bool isLocked = false;
00143 if (m_usingv4l2)
00144 {
00145 if (m_driver == "hdpvr")
00146 isLocked = handleHDPVR(videofd);
00147 else
00148 {
00149 struct v4l2_tuner tuner;
00150 memset(&tuner, 0, sizeof(tuner));
00151
00152 if (ioctl(videofd, VIDIOC_G_TUNER, &tuner, 0) < 0)
00153 {
00154 LOG(VB_GENERAL, LOG_ERR, "Failed to probe signal (v4l2)" + ENO);
00155 }
00156 else
00157 {
00158 isLocked = tuner.signal;
00159 }
00160 }
00161 }
00162 #ifdef USING_V4L1
00163 else
00164 {
00165 struct video_tuner tuner;
00166 memset(&tuner, 0, sizeof(tuner));
00167
00168 if (ioctl(videofd, VIDIOCGTUNER, &tuner, 0) < 0)
00169 {
00170 LOG(VB_GENERAL, LOG_ERR, "Failed to probe signal (v4l1)" + ENO);
00171 }
00172 else
00173 {
00174 isLocked = tuner.signal;
00175 }
00176 }
00177 #endif // USING_V4L1
00178
00179 {
00180 QMutexLocker locker(&statusLock);
00181 signalLock.SetValue(isLocked);
00182 if (isLocked)
00183 signalStrength.SetValue(100);
00184 }
00185
00186 EmitStatus();
00187 if (IsAllGood())
00188 SendMessageAllGood();
00189 }
00190