Ticket #6611: hdpvr-signalmonitor-v2.patch
| File hdpvr-signalmonitor-v2.patch, 10.5 KB (added by jppoet@…, 3 years ago) |
|---|
-
libs/libmythtv/analogsignalmonitor.cpp
old new 4 4 #include <cerrno> 5 5 #include <unistd.h> 6 6 #include <sys/ioctl.h> 7 #include <poll.h> 7 8 8 9 #include "videodev_myth.h" 9 10 #include "mythcontext.h" 10 11 #include "analogsignalmonitor.h" 11 12 #include "v4lchannel.h" 12 13 13 #define LOC QString("AnalogSM: ").arg(channel->GetDevice())14 #define LOC_ERR QString("AnalogSM, Error: ").arg(channel->GetDevice())14 #define LOC QString("AnalogSM: %1 ").arg(channel->GetDevice()) 15 #define LOC_ERR QString("AnalogSM, Error: %1 ").arg(channel->GetDevice()) 15 16 16 AnalogSignalMonitor::AnalogSignalMonitor( 17 int db_cardnum, V4LChannel *_channel,uint64_t _flags) :17 AnalogSignalMonitor::AnalogSignalMonitor(int db_cardnum, V4LChannel *_channel, 18 uint64_t _flags) : 18 19 SignalMonitor(db_cardnum, _channel, _flags), 19 usingv4l2(false) 20 m_usingv4l2(false), 21 m_stage(0) 20 22 { 21 23 int videofd = channel->GetFd(); 22 24 if (videofd >= 0) 23 usingv4l2 = CardUtil::hasV4L2(videofd); 25 { 26 m_usingv4l2 = CardUtil::hasV4L2(videofd); 27 CardUtil::GetV4LInfo(videofd, m_card, m_driver, m_version); 28 VERBOSE(VB_RECORD, LOC + QString("card '%1' driver '%2' version '%3'") 29 .arg(m_card).arg(m_driver).arg(m_version)); 30 } 31 } 32 33 bool AnalogSignalMonitor::handleHDPVR(int videofd) 34 { 35 struct v4l2_encoder_cmd command; 36 struct pollfd polls; 37 38 if (m_stage == 0) 39 { 40 VERBOSE(VB_RECORD, LOC + "hd-pvr start encoding"); 41 // Tell it to start encoding, then wait for it to actually feed us 42 // some data. 43 memset(&command, 0, sizeof(struct v4l2_encoder_cmd)); 44 command.cmd = V4L2_ENC_CMD_START; 45 if (ioctl(videofd, VIDIOC_ENCODER_CMD, &command) == 0) 46 m_stage = 1; 47 else 48 { 49 VERBOSE(VB_IMPORTANT, LOC_ERR + "Start encoding failed" + ENO); 50 command.cmd = V4L2_ENC_CMD_STOP; 51 ioctl(videofd, VIDIOC_ENCODER_CMD, &command); 52 } 53 } 54 55 if (m_stage == 1) 56 { 57 VERBOSE(VB_RECORD, LOC + "hd-pvr wait for data"); 58 59 polls.fd = videofd; 60 polls.events = POLLIN; 61 polls.revents = 0; 62 63 if (poll(&polls, 1, 1500) > 0) 64 { 65 m_stage = 2; 66 QMutexLocker locker(&statusLock); 67 signalStrength.SetValue(25); 68 } 69 else 70 { 71 VERBOSE(VB_RECORD, LOC + "Poll timed-out. Resetting"); 72 memset(&command, 0, sizeof(struct v4l2_encoder_cmd)); 73 command.cmd = V4L2_ENC_CMD_STOP; 74 ioctl(videofd, VIDIOC_ENCODER_CMD, &command); 75 m_stage = 0; 76 77 QMutexLocker locker(&statusLock); 78 signalStrength.SetValue(0); 79 } 80 } 81 82 if (m_stage == 2) 83 { 84 VERBOSE(VB_RECORD, LOC + "hd-pvr data ready. Stop encoding"); 85 86 command.cmd = V4L2_ENC_CMD_STOP; 87 if (ioctl(videofd, VIDIOC_ENCODER_CMD, &command) == 0) 88 m_stage = 3; 89 else 90 { 91 QMutexLocker locker(&statusLock); 92 signalStrength.SetValue(50); 93 } 94 } 95 96 if (m_stage == 3) 97 { 98 struct v4l2_format vfmt; 99 memset(&vfmt, 0, sizeof(vfmt)); 100 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 101 102 VERBOSE(VB_RECORD, LOC + "hd-pvr waiting for valid resolution"); 103 if ((ioctl(videofd, VIDIOC_G_FMT, &vfmt) == 0) && vfmt.fmt.pix.width) 104 { 105 VERBOSE(VB_RECORD, LOC + QString("hd-pvr resolution %1 x %2") 106 .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height)); 107 m_stage = 4; 108 } 109 else 110 { 111 QMutexLocker locker(&statusLock); 112 signalStrength.SetValue(75); 113 } 114 } 115 116 return (m_stage == 4); 24 117 } 25 118 26 119 void AnalogSignalMonitor::UpdateValues(void) … … void AnalogSignalMonitor::UpdateValues(v 36 129 return; 37 130 38 131 bool isLocked = false; 39 if ( usingv4l2)132 if (m_usingv4l2) 40 133 { 41 struct v4l2_tuner tuner; 42 bzero(&tuner, sizeof(tuner)); 43 44 if (ioctl(videofd, VIDIOC_G_TUNER, &tuner, 0) < 0) 45 { 46 VERBOSE(VB_IMPORTANT, 47 LOC_ERR + "Failed to probe signal (v4l2)" + ENO); 48 } 134 if (m_driver == "hdpvr") 135 isLocked = handleHDPVR(videofd); 49 136 else 50 137 { 51 isLocked = tuner.signal; 138 struct v4l2_tuner tuner; 139 bzero(&tuner, sizeof(tuner)); 140 141 if (ioctl(videofd, VIDIOC_G_TUNER, &tuner, 0) < 0) 142 { 143 VERBOSE(VB_IMPORTANT, 144 LOC_ERR + "Failed to probe signal (v4l2)" + ENO); 145 } 146 else 147 { 148 isLocked = tuner.signal; 149 } 52 150 } 53 151 } 54 152 else … … void AnalogSignalMonitor::UpdateValues(v 70 168 { 71 169 QMutexLocker locker(&statusLock); 72 170 signalLock.SetValue(isLocked); 73 signalStrength.SetValue(isLocked ? 100 : 0); 171 if (isLocked) 172 signalStrength.SetValue(100); 74 173 } 75 174 76 175 EmitStatus(); -
libs/libmythtv/analogsignalmonitor.h
old new class AnalogSignalMonitor : public Signa 19 19 virtual void UpdateValues(void); 20 20 21 21 private: 22 bool usingv4l2; 22 bool handleHDPVR(int videofd); 23 24 bool m_usingv4l2; 25 QString m_card; 26 QString m_driver; 27 uint32_t m_version; 28 int m_stage; 23 29 }; 24 30 25 31 #endif // _ANALOG_SIGNAL_MONITOR_H_ -
libs/libmythtv/mpegrecorder.cpp
old new void MpegRecorder::StartRecording(void) 1041 1041 1042 1042 if (driver == "hdpvr") 1043 1043 { 1044 if (curRecording->recgroup == "LiveTV")1045 {1046 // Don't bother checking resolution, always use best bitrate1047 int maxbitrate = std::max(high_mpeg4peakbitrate,1048 high_mpeg4avgbitrate);1049 SetBitrate(high_mpeg4avgbitrate, maxbitrate, "LiveTV");1050 }1051 1052 1044 int progNum = 1; 1053 1045 MPEGStreamData *sd = new MPEGStreamData(progNum, true); 1054 1046 sd->SetRecordingType(_recording_type); … … bool MpegRecorder::StartEncoding(int fd) 1492 1484 memset(&command, 0, sizeof(struct v4l2_encoder_cmd)); 1493 1485 command.cmd = V4L2_ENC_CMD_START; 1494 1486 1495 if (driver == "hdpvr" && curRecording->recgroup != "LiveTV")1487 if (driver == "hdpvr") 1496 1488 HandleResolutionChanges(); 1497 1489 1498 1490 VERBOSE(VB_RECORD, LOC + "StartEncoding"); … … void MpegRecorder::HandleSingleProgramPM 1615 1607 DTVRecorder::BufferedWrite(*(reinterpret_cast<TSPacket*>(&buf[i]))); 1616 1608 } 1617 1609 1618 /// After a resolution change, it can take the HD-PVR a few1619 /// seconds before it is usable again.1620 bool MpegRecorder::WaitFor_HDPVR(void)1621 {1622 struct v4l2_encoder_cmd command;1623 struct v4l2_format vfmt;1624 struct pollfd polls;1625 int idx;1626 1627 // Tell it to start encoding, then wait for it to actually feed us1628 // some data.1629 QMutexLocker locker(&start_stop_encoding_lock);1630 1631 // Sleep any less than 1.5 seconds, and the HD-PVR will1632 // return the old resolution, when the resolution is changing.1633 usleep(1500 * 1000);1634 1635 memset(&command, 0, sizeof(struct v4l2_encoder_cmd));1636 command.cmd = V4L2_ENC_CMD_START;1637 1638 for (idx = 0; idx < 20; ++idx)1639 {1640 if (ioctl(readfd, VIDIOC_ENCODER_CMD, &command) == 0)1641 break;1642 usleep(100 * 1000);1643 }1644 1645 if (idx == 20)1646 return false;1647 1648 polls.fd = readfd;1649 polls.events = POLLIN;1650 polls.revents = 0;1651 1652 if (poll(&polls, 1, 5000) <= 0)1653 return false;1654 1655 // HD-PVR should now be "ready"1656 command.cmd = V4L2_ENC_CMD_STOP;1657 1658 if (ioctl(readfd, VIDIOC_ENCODER_CMD, &command) < 0)1659 return false;1660 1661 memset(&vfmt, 0, sizeof(vfmt));1662 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;1663 1664 for (idx = 0; idx < 20; ++idx)1665 {1666 if (0 == ioctl(chanfd, VIDIOC_G_FMT, &vfmt))1667 return true;1668 // Typically takes 0.9 seconds after a resolution change1669 usleep(100 * 1000);1670 }1671 1672 VERBOSE(VB_RECORD, LOC + "WaitForHDPVR failed");1673 return false;1674 }1675 1676 1610 void MpegRecorder::SetBitrate(int bitrate, int maxbitrate, 1677 1611 const QString & reason) 1678 1612 { … … void MpegRecorder::HandleResolutionChang 1710 1644 memset(&vfmt, 0, sizeof(vfmt)); 1711 1645 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1712 1646 1713 if (driver == "hdpvr")1714 WaitFor_HDPVR();1715 1716 1647 if (0 == ioctl(chanfd, VIDIOC_G_FMT, &vfmt)) 1717 1648 { 1718 1649 VERBOSE(VB_RECORD, LOC + QString("Got Resolution %1x%2") -
libs/libmythtv/mpegrecorder.h
old new class MpegRecorder : public DTVRecorder, 86 86 87 87 void ResetForNewFile(void); 88 88 89 bool WaitFor_HDPVR(void);90 89 void SetBitrate(int bitrate, int maxbitrate, const QString & reason); 91 90 void HandleResolutionChanges(void); 92 91 -
libs/libmythtv/signalmonitor.h
old new inline bool SignalMonitor::IsRequired(co 301 301 return (CardUtil::IsDVBCardType(cardtype) || 302 302 (cardtype.toUpper() == "HDTV") || 303 303 (cardtype.toUpper() == "HDHOMERUN") || 304 (cardtype.toUpper() == "HDPVR") || 304 305 (cardtype.toUpper() == "FIREWIRE") || 305 306 (cardtype.toUpper() == "FREEBOX")); 306 307 } -
libs/libmythtv/signalmonitor.cpp
old new SignalMonitor *SignalMonitor::Init(QStri 96 96 #endif 97 97 98 98 #ifdef USING_V4L 99 #if 0 // Just use ChannelChangeMonitor for these types 100 if ((cardtype.toUpper() == "V4L") || 101 (cardtype.toUpper() == "MPEG")) 99 if (cardtype.toUpper() == "HDPVR") 102 100 { 103 101 V4LChannel *chan = dynamic_cast<V4LChannel*>(channel); 104 102 if (chan) 105 103 signalMonitor = new AnalogSignalMonitor(db_cardnum, chan); 106 104 } 107 105 #endif 108 #endif109 106 110 107 #ifdef USING_HDHOMERUN 111 108 if (cardtype.toUpper() == "HDHOMERUN")
