Ticket #6611: hdpvr-signalmonitor.patch
| File hdpvr-signalmonitor.patch, 9.1 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 int idx; 38 39 if (m_stage == 0) 40 { 41 VERBOSE(VB_RECORD, LOC + "hd-pvr start encoding"); 42 // Tell it to start encoding, then wait for it to actually feed us 43 // some data. 44 memset(&command, 0, sizeof(struct v4l2_encoder_cmd)); 45 command.cmd = V4L2_ENC_CMD_START; 46 if (ioctl(videofd, VIDIOC_ENCODER_CMD, &command) == 0) 47 m_stage = 1; 48 else 49 VERBOSE(VB_IMPORTANT, LOC_ERR + "Start encoding failed" + ENO); 50 } 51 52 if (m_stage == 1) 53 { 54 VERBOSE(VB_RECORD, LOC + "hd-pvr wait for data"); 55 56 polls.fd = videofd; 57 polls.events = POLLIN; 58 polls.revents = 0; 59 60 if (poll(&polls, 1, 1500) > 0) 61 m_stage = 2; 62 else 63 { 64 VERBOSE(VB_RECORD, LOC + "Poll timed-out. Resetting"); 65 memset(&command, 0, sizeof(struct v4l2_encoder_cmd)); 66 command.cmd = V4L2_ENC_CMD_STOP; 67 ioctl(videofd, VIDIOC_ENCODER_CMD, &command); 68 m_stage = 0; 69 } 70 } 71 72 if (m_stage == 2) 73 { 74 VERBOSE(VB_RECORD, LOC + "hd-pvr data ready. Stop encoding"); 75 76 command.cmd = V4L2_ENC_CMD_STOP; 77 if (ioctl(videofd, VIDIOC_ENCODER_CMD, &command) == 0) 78 m_stage = 3; 79 } 80 81 if (m_stage == 3) 82 { 83 struct v4l2_format vfmt; 84 memset(&vfmt, 0, sizeof(vfmt)); 85 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 86 87 VERBOSE(VB_RECORD, LOC + "hd-pvr waiting for valid resolution"); 88 if ((ioctl(videofd, VIDIOC_G_FMT, &vfmt) == 0) && vfmt.fmt.pix.width) 89 m_stage = 4; 90 } 91 92 return (m_stage == 4); 24 93 } 25 94 26 95 void AnalogSignalMonitor::UpdateValues(void) … … void AnalogSignalMonitor::UpdateValues(v 33 102 return; 34 103 35 104 bool isLocked = false; 36 if ( usingv4l2)105 if (m_usingv4l2) 37 106 { 38 struct v4l2_tuner tuner; 39 bzero(&tuner, sizeof(tuner)); 40 41 if (ioctl(videofd, VIDIOC_G_TUNER, &tuner, 0) < 0) 42 { 43 VERBOSE(VB_IMPORTANT, 44 LOC_ERR + "Failed to probe signal (v4l2)" + ENO); 45 } 107 if (m_driver == "hdpvr") 108 isLocked = handleHDPVR(videofd); 46 109 else 47 110 { 48 isLocked = tuner.signal; 111 struct v4l2_tuner tuner; 112 bzero(&tuner, sizeof(tuner)); 113 114 if (ioctl(videofd, VIDIOC_G_TUNER, &tuner, 0) < 0) 115 { 116 VERBOSE(VB_IMPORTANT, 117 LOC_ERR + "Failed to probe signal (v4l2)" + ENO); 118 } 119 else 120 { 121 isLocked = tuner.signal; 122 } 49 123 } 50 124 } 51 125 else -
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 287 287 return (CardUtil::IsDVBCardType(cardtype) || 288 288 (cardtype.toUpper() == "HDTV") || 289 289 (cardtype.toUpper() == "HDHOMERUN") || 290 (cardtype.toUpper() == "HDPVR") || 290 291 (cardtype.toUpper() == "FIREWIRE") || 291 292 (cardtype.toUpper() == "FREEBOX")); 292 293 } … … inline bool SignalMonitor::IsSupported(c 295 296 { 296 297 return (IsRequired(cardtype) || 297 298 (cardtype.toUpper() == "V4L") || 299 (cardtype.toUpper() == "HDPVR") || 298 300 (cardtype.toUpper() == "MPEG")); 299 301 } 300 302
