Ticket #6611: hdpvr-signalmonitor-v2.1.patch

File hdpvr-signalmonitor-v2.1.patch, 11.5 KB (added by jpoet, 2 years ago)

Updated for r23670

  • libs/libmythtv/analogsignalmonitor.cpp

    old new  
    22// Copyright (c) 2005, Daniel Thor Kristjansson 
    33 
    44#include <cerrno> 
    55#include <unistd.h> 
    66#include <sys/ioctl.h> 
     7#include <poll.h> 
    78 
    89#include "videodev_myth.h" 
    910#include "mythcontext.h" 
    1011#include "analogsignalmonitor.h" 
    1112#include "v4lchannel.h" 
    1213 
    1314#define LOC QString("AnalogSM(%1): ").arg(channel->GetDevice()) 
    1415#define LOC_ERR QString("AnalogSM(%1), Error: ").arg(channel->GetDevice()) 
    1516 
    16 AnalogSignalMonitor::AnalogSignalMonitor( 
    17     int db_cardnum, V4LChannel *_channel, uint64_t _flags) : 
     17AnalogSignalMonitor::AnalogSignalMonitor(int db_cardnum, 
     18                                         V4LChannel *_channel, 
     19                                         uint64_t _flags) : 
    1820    SignalMonitor(db_cardnum, _channel, _flags), 
    19     usingv4l2(false) 
     21    m_usingv4l2(false), 
     22    m_stage(0) 
    2023{ 
    2124    int videofd = channel->GetFd(); 
    2225    if (videofd >= 0) 
    23         usingv4l2 = CardUtil::hasV4L2(videofd); 
     26    { 
     27        m_usingv4l2 = CardUtil::hasV4L2(videofd); 
     28        CardUtil::GetV4LInfo(videofd, m_card, m_driver, m_version); 
     29        VERBOSE(VB_RECORD, LOC + QString("card '%1' driver '%2' version '%3'") 
     30                .arg(m_card).arg(m_driver).arg(m_version)); 
     31    } 
     32} 
     33 
     34bool AnalogSignalMonitor::handleHDPVR(int videofd) 
     35{ 
     36    struct v4l2_encoder_cmd command; 
     37    struct pollfd polls; 
     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        { 
     50            VERBOSE(VB_IMPORTANT, LOC_ERR + "Start encoding failed" + ENO); 
     51            command.cmd = V4L2_ENC_CMD_STOP; 
     52            ioctl(videofd, VIDIOC_ENCODER_CMD, &command); 
     53        } 
     54    } 
     55 
     56    if (m_stage == 1) 
     57    { 
     58        VERBOSE(VB_RECORD, LOC + "hd-pvr wait for data"); 
     59 
     60        polls.fd      = videofd; 
     61        polls.events  = POLLIN; 
     62        polls.revents = 0; 
     63 
     64        if (poll(&polls, 1, 1500) > 0) 
     65        { 
     66            m_stage = 2; 
     67            QMutexLocker locker(&statusLock); 
     68            signalStrength.SetValue(25); 
     69        } 
     70        else 
     71        { 
     72            VERBOSE(VB_RECORD, LOC + "Poll timed-out.  Resetting"); 
     73            memset(&command, 0, sizeof(struct v4l2_encoder_cmd)); 
     74            command.cmd = V4L2_ENC_CMD_STOP; 
     75            ioctl(videofd, VIDIOC_ENCODER_CMD, &command); 
     76            m_stage = 0; 
     77 
     78            QMutexLocker locker(&statusLock); 
     79            signalStrength.SetValue(0); 
     80        } 
     81    } 
     82 
     83    if (m_stage == 2) 
     84    { 
     85        VERBOSE(VB_RECORD, LOC + "hd-pvr data ready.  Stop encoding"); 
     86 
     87        command.cmd = V4L2_ENC_CMD_STOP; 
     88        if (ioctl(videofd, VIDIOC_ENCODER_CMD, &command) == 0) 
     89            m_stage = 3; 
     90        else 
     91        { 
     92            QMutexLocker locker(&statusLock); 
     93            signalStrength.SetValue(50); 
     94        } 
     95    } 
     96    else 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); 
    24117} 
    25118 
    26119void AnalogSignalMonitor::UpdateValues(void) 
    27120{ 
    28121    if (!running || exit) 
    void AnalogSignalMonitor::UpdateValues(v 
    34127 
    35128    if (!IsChannelTuned()) 
    36129        return; 
    37130 
    38131    bool isLocked = false; 
    39     if (usingv4l2) 
     132    if (m_usingv4l2) 
    40133    { 
    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); 
    49136        else 
    50137        { 
    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            } 
    52150        } 
    53151    } 
    54152    else 
    55153    { 
    56154        struct video_tuner tuner; 
    void AnalogSignalMonitor::UpdateValues(v 
    68166    } 
    69167 
    70168    { 
    71169        QMutexLocker locker(&statusLock); 
    72170        signalLock.SetValue(isLocked); 
    73         signalStrength.SetValue(isLocked ? 100 : 0); 
     171        if (isLocked) 
     172            signalStrength.SetValue(100); 
    74173    } 
    75174 
    76175    EmitStatus(); 
    77176    if (IsAllGood()) 
    78177        SendMessageAllGood(); 
  • libs/libmythtv/analogsignalmonitor.h

    old new class AnalogSignalMonitor : public Signa 
    1717        uint64_t _flags = kSigMon_WaitForSig); 
    1818 
    1919    virtual void UpdateValues(void); 
    2020 
    2121  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; 
    2329}; 
    2430 
    2531#endif // _ANALOG_SIGNAL_MONITOR_H_ 
  • libs/libmythtv/mpegrecorder.cpp

    old new void MpegRecorder::StartRecording(void) 
    10421042    _last_gop_seen = 0; 
    10431043    _frames_written_count = 0; 
    10441044 
    10451045    if (driver == "hdpvr") 
    10461046    { 
    1047         if (curRecording->recgroup == "LiveTV") 
    1048         { 
    1049             // Don't bother checking resolution, always use best bitrate 
    1050             int maxbitrate = std::max(high_mpeg4peakbitrate, 
    1051                                       high_mpeg4avgbitrate); 
    1052             SetBitrate(high_mpeg4avgbitrate, maxbitrate, "LiveTV"); 
    1053         } 
    1054  
    10551047        int progNum = 1; 
    10561048        MPEGStreamData *sd = new MPEGStreamData(progNum, true); 
    10571049        sd->SetRecordingType(_recording_type); 
    10581050        SetStreamData(sd); 
    10591051 
    bool MpegRecorder::StartEncoding(int fd) 
    15231515 
    15241516    struct v4l2_encoder_cmd command; 
    15251517    memset(&command, 0, sizeof(struct v4l2_encoder_cmd)); 
    15261518    command.cmd = V4L2_ENC_CMD_START; 
    15271519 
    1528     if (driver == "hdpvr" && curRecording->recgroup != "LiveTV") 
     1520    if (driver == "hdpvr") 
    15291521        HandleResolutionChanges(); 
    15301522 
    15311523    VERBOSE(VB_RECORD, LOC + "StartEncoding"); 
    15321524 
    15331525    if (ioctl(fd, VIDIOC_ENCODER_CMD, &command) == 0) 
    void MpegRecorder::HandleSingleProgramPM 
    16321624 
    16331625    for (uint i = 0; i < _scratch.size(); i++) 
    16341626        DTVRecorder::BufferedWrite(_scratch[i]); 
    16351627} 
    16361628 
    1637 /// After a resolution change, it can take the HD-PVR a few 
    1638 /// seconds before it is usable again. 
    1639 bool MpegRecorder::WaitFor_HDPVR(void) 
    1640 { 
    1641     struct v4l2_encoder_cmd command; 
    1642     struct v4l2_format vfmt; 
    1643     struct pollfd polls; 
    1644     int    idx; 
    1645  
    1646     // Tell it to start encoding, then wait for it to actually feed us 
    1647     // some data. 
    1648     QMutexLocker locker(&start_stop_encoding_lock); 
    1649  
    1650     // Sleep any less than 1.5 seconds, and the HD-PVR will 
    1651     // return the old resolution, when the resolution is changing. 
    1652     usleep(1500 * 1000); 
    1653  
    1654     memset(&command, 0, sizeof(struct v4l2_encoder_cmd)); 
    1655     command.cmd = V4L2_ENC_CMD_START; 
    1656  
    1657     for (idx = 0; idx < 20; ++idx) 
    1658     { 
    1659         if (ioctl(readfd, VIDIOC_ENCODER_CMD, &command) == 0) 
    1660             break; 
    1661         usleep(100 * 1000); 
    1662     } 
    1663  
    1664     if (idx == 20) 
    1665         return false; 
    1666  
    1667     polls.fd      = readfd; 
    1668     polls.events  = POLLIN; 
    1669     polls.revents = 0; 
    1670  
    1671     if (poll(&polls, 1, 5000) <= 0) 
    1672         return false; 
    1673  
    1674     // HD-PVR should now be "ready" 
    1675     command.cmd = V4L2_ENC_CMD_STOP; 
    1676  
    1677     if (ioctl(readfd, VIDIOC_ENCODER_CMD, &command) < 0) 
    1678         return false; 
    1679  
    1680     memset(&vfmt, 0, sizeof(vfmt)); 
    1681     vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 
    1682  
    1683     for (idx = 0; idx < 20; ++idx) 
    1684     { 
    1685         if (0 == ioctl(chanfd, VIDIOC_G_FMT, &vfmt)) 
    1686             return true; 
    1687         // Typically takes 0.9 seconds after a resolution change 
    1688         usleep(100 * 1000); 
    1689     } 
    1690  
    1691     VERBOSE(VB_RECORD, LOC + "WaitForHDPVR failed"); 
    1692     return false; 
    1693 } 
    1694  
    16951629void MpegRecorder::SetBitrate(int bitrate, int maxbitrate, 
    16961630                              const QString & reason) 
    16971631{ 
    16981632    if (maxbitrate == bitrate) 
    16991633    { 
    void MpegRecorder::HandleResolutionChang 
    17271661    uint pix = 0; 
    17281662    struct v4l2_format vfmt; 
    17291663    memset(&vfmt, 0, sizeof(vfmt)); 
    17301664    vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 
    17311665 
    1732     if (driver == "hdpvr") 
    1733         WaitFor_HDPVR(); 
    1734  
    17351666    if (0 == ioctl(chanfd, VIDIOC_G_FMT, &vfmt)) 
    17361667    { 
    17371668        VERBOSE(VB_RECORD, LOC + QString("Got Resolution %1x%2") 
    17381669                .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height)); 
    17391670        pix = vfmt.fmt.pix.width * vfmt.fmt.pix.height; 
  • libs/libmythtv/mpegrecorder.h

    old new class MpegRecorder : public DTVRecorder, 
    8484    bool StartEncoding(int fd); 
    8585    bool StopEncoding(int fd); 
    8686 
    8787    void ResetForNewFile(void); 
    8888 
    89     bool WaitFor_HDPVR(void); 
    9089    void SetBitrate(int bitrate, int maxbitrate, const QString & reason); 
    9190    void HandleResolutionChanges(void); 
    9291 
    9392    inline bool CheckCC(uint pid, uint cc); 
    9493 
  • libs/libmythtv/signalmonitor.cpp

    old new SignalMonitor *SignalMonitor::Init(QStri 
    9494            signalMonitor = new DVBSignalMonitor(db_cardnum, dvbc); 
    9595    } 
    9696#endif 
    9797 
    9898#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") 
    102100    { 
    103101        V4LChannel *chan = dynamic_cast<V4LChannel*>(channel); 
    104102        if (chan) 
    105103            signalMonitor = new AnalogSignalMonitor(db_cardnum, chan); 
    106104    } 
    107105#endif 
    108 #endif 
    109106 
    110107#ifdef USING_HDHOMERUN 
    111108    if (cardtype.toUpper() == "HDHOMERUN") 
    112109    { 
    113110        HDHRChannel *hdhrc = dynamic_cast<HDHRChannel*>(channel); 
  • libs/libmythtv/signalmonitor.h

    old new inline QString sm_flags_to_string(uint64 
    304304inline bool SignalMonitor::IsRequired(const QString &cardtype) 
    305305{ 
    306306    return (CardUtil::IsDVBCardType(cardtype) || 
    307307            (cardtype.toUpper() == "HDTV")      || 
    308308            (cardtype.toUpper() == "HDHOMERUN") || 
     309            (cardtype.toUpper() == "HDPVR") || 
    309310            (cardtype.toUpper() == "FIREWIRE")  || 
    310311            (cardtype.toUpper() == "FREEBOX")); 
    311312} 
    312313 
    313314inline bool SignalMonitor::IsSupported(const QString &cardtype)