Ticket #10765: HD-PVR-signalmonitor-v2.patch

File HD-PVR-signalmonitor-v2.patch, 8.8 KB (added by jpoet, 12 years ago)

Fix a possible bus error

  • mythtv/libs/libmythtv/analogsignalmonitor.cpp

    diff --git a/mythtv/libs/libmythtv/analogsignalmonitor.cpp b/mythtv/libs/libmythtv/analogsignalmonitor.cpp
    index 4e0775d..b1d9bbb 100644
    a b  
    1919AnalogSignalMonitor::AnalogSignalMonitor(
    2020    int db_cardnum, V4LChannel *_channel, uint64_t _flags) :
    2121    SignalMonitor(db_cardnum, _channel, _flags),
    22     m_usingv4l2(false), m_stage(0)
     22    m_usingv4l2(false), m_width(0), m_lock_cnt(0)
    2323{
    2424    int videofd = channel->GetFd();
    2525    if (videofd >= 0)
    AnalogSignalMonitor::AnalogSignalMonitor( 
    3434        LOG(VB_RECORD, LOG_INFO, QString("card '%1' driver '%2' version '%3'")
    3535                .arg(m_card).arg(m_driver).arg(m_version));
    3636    }
     37    m_stable_time = 2000; // Desire a stable signal for 2 second
    3738}
    3839
    39 bool AnalogSignalMonitor::handleHDPVR(int videofd)
     40bool AnalogSignalMonitor::VerifyHDPVRaudio(int videofd)
    4041{
    41     struct v4l2_encoder_cmd command;
    42     struct pollfd polls;
     42    struct v4l2_queryctrl qctrl;
     43    qctrl.id = V4L2_CID_MPEG_AUDIO_ENCODING;
    4344
    44     if (m_stage == 0)
     45    int audtype = V4L2_MPEG_AUDIO_ENCODING_AC3;
     46
     47    if (ioctl(videofd, VIDIOC_QUERYCTRL, &qctrl) != 0)
    4548    {
    46         LOG(VB_RECORD, LOG_INFO, "hd-pvr start encoding");
    47         // Tell it to start encoding, then wait for it to actually feed us
    48         // some data.
    49         memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
    50         command.cmd = V4L2_ENC_CMD_START;
    51         if (ioctl(videofd, VIDIOC_ENCODER_CMD, &command) == 0)
    52             m_stage = 1;
    53         else
    54         {
    55             LOG(VB_GENERAL, LOG_ERR, "Start encoding failed" + ENO);
    56             command.cmd = V4L2_ENC_CMD_STOP;
    57             ioctl(videofd, VIDIOC_ENCODER_CMD, &command);
    58         }
     49        LOG(VB_GENERAL, LOG_ERR, LOC +
     50            "Unable to get supported audio codecs for verification." + ENO);
     51        return false;
    5952    }
    6053
    61     if (m_stage == 1)
     54    int  current_audio;
     55    uint audio_enc = max(min(audtype - 1, qctrl.maximum), qctrl.minimum);
     56
     57    struct v4l2_ext_control  ext_ctrl;
     58    struct v4l2_ext_controls ext_ctrls;
     59
     60    memset(&ext_ctrl, 0, sizeof(struct v4l2_ext_control));
     61    ext_ctrl.id = V4L2_CID_MPEG_AUDIO_ENCODING;
     62
     63    ext_ctrls.reserved[0] = ext_ctrls.reserved[1] = 0;
     64    ext_ctrls.count = 1;
     65    ext_ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
     66    ext_ctrls.controls = &ext_ctrl;
     67
     68    if (ioctl(videofd, VIDIOC_G_EXT_CTRLS, &ext_ctrls) != 0)
    6269    {
    63         LOG(VB_RECORD, LOG_INFO, "hd-pvr wait for data");
     70        LOG(VB_GENERAL, LOG_ERR, LOC +
     71            "Unable to get current audio codecs for verification." + ENO);
     72        return false;
     73    }
    6474
    65         polls.fd      = videofd;
    66         polls.events  = POLLIN;
    67         polls.revents = 0;
     75    current_audio = ext_ctrls.controls->value;
    6876
    69         if (poll(&polls, 1, 1500) > 0)
     77    if (audtype - 1 != current_audio)
     78    {
     79        LOG(VB_GENERAL, LOG_ERR, LOC + QString("Audio desired %1, current %2 "
     80                                               "min %3 max %4")
     81            .arg(audtype - 1)
     82            .arg(current_audio)
     83            .arg(qctrl.minimum)
     84            .arg(qctrl.maximum)
     85            );
     86
     87        ext_ctrl.id = V4L2_CID_MPEG_AUDIO_ENCODING;
     88        ext_ctrl.value = audtype - 1;
     89        if (ioctl(videofd, VIDIOC_S_EXT_CTRLS, &ext_ctrls) == 0)
    7090        {
    71             m_stage = 2;
    72             QMutexLocker locker(&statusLock);
    73             signalStrength.SetValue(25);
     91            LOG(VB_GENERAL, LOG_ERR, LOC + QString("Changed audio encoding "
     92                                                   "from %1 to %2.")
     93                .arg(current_audio)
     94                .arg(audtype - 1)
     95                );
    7496        }
    7597        else
    7698        {
    77             LOG(VB_RECORD, LOG_INFO, "Poll timed-out.  Resetting");
    78             memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
    79             command.cmd = V4L2_ENC_CMD_STOP;
    80             ioctl(videofd, VIDIOC_ENCODER_CMD, &command);
    81             m_stage = 0;
    82 
    83             QMutexLocker locker(&statusLock);
    84             signalStrength.SetValue(0);
     99            LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to changed audio "
     100                                                   "encoding from %1 to %2."
     101                                                   + ENO)
     102                .arg(current_audio)
     103                .arg(audtype - 1)
     104                );
    85105        }
     106
     107        return false;
    86108    }
    87109
    88     if (m_stage == 2)
    89     {
    90         LOG(VB_RECORD, LOG_INFO, "hd-pvr data ready.  Stop encoding");
     110    return true;
     111}
    91112
    92         command.cmd = V4L2_ENC_CMD_STOP;
    93         if (ioctl(videofd, VIDIOC_ENCODER_CMD, &command) == 0)
    94             m_stage = 3;
    95         else
    96         {
    97             QMutexLocker locker(&statusLock);
    98             signalStrength.SetValue(50);
    99         }
    100     }
     113bool AnalogSignalMonitor::handleHDPVR(int videofd)
     114{
     115    struct v4l2_encoder_cmd command;
     116    struct pollfd polls;
    101117
    102     if (m_stage == 3)
    103     {
    104         struct v4l2_format vfmt;
    105         memset(&vfmt, 0, sizeof(vfmt));
    106         vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     118    struct v4l2_format vfmt;
     119    memset(&vfmt, 0, sizeof(vfmt));
     120    vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    107121
    108         LOG(VB_RECORD, LOG_INFO, "hd-pvr waiting for valid resolution");
    109         if ((ioctl(videofd, VIDIOC_G_FMT, &vfmt) == 0) && vfmt.fmt.pix.width)
     122    if ((ioctl(videofd, VIDIOC_G_FMT, &vfmt) == 0) &&
     123        vfmt.fmt.pix.width && m_width == vfmt.fmt.pix.width &&
     124        VerifyHDPVRaudio(videofd))
     125    {
     126        if (!m_timer.isRunning())
     127        {
     128            LOG(VB_RECORD, LOG_ERR, QString("hd-pvr resolution %1 x %2")
     129                .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
     130            ++m_lock_cnt;
     131            m_timer.start();
     132        }
     133        else if (m_timer.elapsed() > m_stable_time)
    110134        {
    111             LOG(VB_RECORD, LOG_INFO, QString("hd-pvr resolution %1 x %2")
    112                     .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
    113             m_stage = 4;
     135            LOG(VB_RECORD, LOG_ERR, QString("hd-pvr stable at %1 x %2")
     136                .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
     137            m_timer.stop();
     138            return true;
    114139        }
    115140        else
    116141        {
    117142            QMutexLocker locker(&statusLock);
    118             signalStrength.SetValue(75);
     143            signalStrength.SetValue(60 + m_lock_cnt);
    119144        }
    120145    }
     146    else
     147    {
     148        LOG(VB_RECORD, LOG_ERR, "hd-pvr waiting for valid resolution");
     149        m_width = vfmt.fmt.pix.width;
     150        m_timer.stop();
     151        QMutexLocker locker(&statusLock);
     152        signalStrength.SetValue(20 + m_lock_cnt);
     153    }
    121154
    122     return (m_stage == 4);
     155    return false;
    123156}
    124157
    125158void AnalogSignalMonitor::UpdateValues(void)
  • mythtv/libs/libmythtv/analogsignalmonitor.h

    diff --git a/mythtv/libs/libmythtv/analogsignalmonitor.h b/mythtv/libs/libmythtv/analogsignalmonitor.h
    index dd0154c..97f0065 100644
    a b class AnalogSignalMonitor : public SignalMonitor 
    1919    virtual void UpdateValues(void);
    2020
    2121  private:
     22    bool VerifyHDPVRaudio(int videofd);
    2223    bool handleHDPVR(int videofd);
    2324
    2425    bool     m_usingv4l2;
    2526    QString  m_card;
    2627    QString  m_driver;
    2728    uint32_t m_version;
    28     int      m_stage;
     29    uint     m_width;
     30    uint     m_stable_time;
     31    uint     m_lock_cnt;
     32    MythTimer m_timer;
    2933};
    3034
    3135#endif // _ANALOG_SIGNAL_MONITOR_H_
  • mythtv/libs/libmythtv/mpegrecorder.cpp

    diff --git a/mythtv/libs/libmythtv/mpegrecorder.cpp b/mythtv/libs/libmythtv/mpegrecorder.cpp
    index 0e133ab..95673a5 100644
    a b void MpegRecorder::run(void) 
    10011001
    10021002        if (_device_read_buffer)
    10031003        {
    1004             len = _device_read_buffer->Read(
    1005                     &(buffer[remainder]), bufferSize - remainder);
     1004            len = _device_read_buffer->Read
     1005                  (&(buffer[remainder]), bufferSize - remainder);
    10061006
    10071007            // Check for DRB errors
    10081008            if (_device_read_buffer->IsErrored())
    bool MpegRecorder::StartEncoding(void) 
    13181318    if (_device_read_buffer)
    13191319    {
    13201320        _device_read_buffer->Reset(videodevice.toAscii().constData(), readfd);
     1321        _device_read_buffer->SetRequestPause(false);
    13211322        _device_read_buffer->Start();
    13221323    }
    13231324
    void MpegRecorder::StopEncoding(void) 
    13381339    command.cmd   = V4L2_ENC_CMD_STOP;
    13391340    command.flags = V4L2_ENC_CMD_STOP_AT_GOP_END;
    13401341
     1342    if (_device_read_buffer)
     1343        _device_read_buffer->SetRequestPause(true);
     1344
    13411345    bool stopped = 0 == ioctl(readfd, VIDIOC_ENCODER_CMD, &command);
    13421346    if (stopped)
    13431347    {
    void MpegRecorder::StopEncoding(void) 
    13621366    }
    13631367
    13641368    // close the fd so streamoff/streamon work in V4LChannel
    1365     close(readfd);   
     1369    close(readfd);
    13661370    readfd = -1;
    13671371}
    13681372