Ticket #5866: hdpvr-fix-channel-changes.patch

File hdpvr-fix-channel-changes.patch, 13.2 KB (added by jppoet@…, 15 years ago)

Fix HD-PVR channel changes on the backend

  • libs/libmythtv/mpegrecorder.

    old new  
    8686
    8787    void ResetForNewFile(void);
    8888
     89    bool WaitFor_HDPVR(void);
    8990    void HandleResolutionChanges(void);
    9091
    9192    inline bool CheckCC(uint pid, uint cc);
    9293
    9394    bool deviceIsMpegFile;
    9495    int bufferSize;
    95     useconds_t ioctl_recovery;
    9696
    9797    // Driver info
    9898    QString  card;
  • libs/libmythtv/mpegrecorder.

    old new  
    1919#include <sys/stat.h>
    2020#include <sys/ioctl.h>
    2121#include <sys/time.h>
     22#include <sys/poll.h>
    2223
    2324// avlib headers
    2425extern "C" {
     
    389390            has_buggy_vbi = true;
    390391            requires_special_pause =
    391392                (version >= IVTV_KERNEL_VERSION(0, 10, 0));
    392             ioctl_recovery = 0;
    393393        }
    394394        else if (driver == "pvrusb2")
    395395        {
     
    398398            has_v4l2_vbi  = true;
    399399            has_buggy_vbi = true;
    400400            requires_special_pause = true;
    401             ioctl_recovery = 0;
    402401        }
    403402        else if (driver == "hdpvr")
    404403        {
     
    409408            bzero(_stream_id,  sizeof(_stream_id));
    410409            bzero(_pid_status, sizeof(_pid_status));
    411410            memset(_continuity_counter, 0xff, sizeof(_continuity_counter));
    412             ioctl_recovery = 1000;
    413411        }
    414412        else
    415413        {
     
    417415            bufferSize    = 4096;
    418416            usingv4l2     = has_v4l2_vbi = true;
    419417            has_buggy_vbi = requires_special_pause = false;
    420             ioctl_recovery = 0;
    421418        }
    422419    }
    423420
     
    491488
    492489bool MpegRecorder::SetFormat(int chanfd)
    493490{
     491    uint   idx;
    494492    struct v4l2_format vfmt;
    495493    bzero(&vfmt, sizeof(vfmt));
    496494
    497495    vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    498496
    499     if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) < 0)
     497    for (idx = 0; idx < 20; ++idx)
     498    {
     499        if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) == 0)
     500            break;
     501        usleep(100 * 1000);
     502    }
     503
     504    if (idx == 10)
    500505    {
    501506        VERBOSE(VB_IMPORTANT, LOC_ERR + "Error getting format" + ENO);
    502507        return false;
    503508    }
    504     usleep(ioctl_recovery);
    505509
    506510    vfmt.fmt.pix.width = width;
    507511    vfmt.fmt.pix.height = height;
    508512
    509     if (ioctl(chanfd, VIDIOC_S_FMT, &vfmt) < 0)
     513    for (idx = 0; idx < 20; ++idx)
     514    {
     515        if (ioctl(chanfd, VIDIOC_S_FMT, &vfmt) == 0)
     516            break;
     517        usleep(100 * 1000);
     518    }
     519
     520    if (idx == 20)
    510521    {
    511522        VERBOSE(VB_IMPORTANT, LOC_ERR + "Error setting format" + ENO);
    512523        return false;
    513524    }
    514     usleep(ioctl_recovery);
    515525
    516526    return true;
    517527}
     
    519529/// Set audio language mode
    520530bool MpegRecorder::SetLanguageMode(int chanfd)
    521531{
     532    uint   idx;
    522533    struct v4l2_tuner vt;
    523534    bzero(&vt, sizeof(struct v4l2_tuner));
    524     if (ioctl(chanfd, VIDIOC_G_TUNER, &vt) < 0)
     535
     536    for (idx = 0; idx < 20; ++idx)
     537    {
     538        if (ioctl(chanfd, VIDIOC_G_TUNER, &vt) == 0)
     539            break;
     540        usleep(100 * 1000);
     541    }
     542
     543    if (idx == 20)
    525544    {
    526545        VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get audio mode" + ENO);
    527546        return false;
    528547    }
    529     usleep(ioctl_recovery);
    530548
    531549    switch (language)
    532550    {
     
    556574        success = false;
    557575    }
    558576
    559     if (ioctl(chanfd, VIDIOC_S_TUNER, &vt) < 0)
     577    for (idx = 0; idx < 20; ++idx)
     578    {
     579        if (ioctl(chanfd, VIDIOC_S_TUNER, &vt) == 0)
     580            break;
     581        usleep(100 * 1000);
     582    }
     583
     584    if (idx == 20)
    560585    {
    561586        VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to set audio mode" + ENO);
    562587        success = false;
    563588    }
    564     usleep(ioctl_recovery);
    565589
    566590    return success;
    567591}
     
    569593bool MpegRecorder::SetRecordingVolume(int chanfd)
    570594{
    571595    // Get volume min/max values
     596    uint   idx;
    572597    struct v4l2_queryctrl qctrl;
    573598    qctrl.id = V4L2_CID_AUDIO_VOLUME;
    574     if (ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) < 0)
     599
     600    for (idx = 0; idx < 20; ++idx)
     601    {
     602        if (ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) == 0)
     603            break;
     604        usleep(100 * 1000);
     605    }
     606
     607    if (idx == 20)
    575608    {
    576609        VERBOSE(VB_IMPORTANT, LOC_WARN +
    577610                "Unable to get recording volume parameters(max/min)" + ENO +
     
    579612        qctrl.maximum = 65535;
    580613        qctrl.minimum = 0;
    581614    }
    582     usleep(ioctl_recovery);
    583615
    584616    // calculate volume in card units.
    585617    int range = qctrl.maximum - qctrl.minimum;
     
    591623    ctrl.id = V4L2_CID_AUDIO_VOLUME;
    592624    ctrl.value = ctrl_volume;
    593625
    594     if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) < 0)
     626    for (idx = 0; idx < 20; ++idx)
     627    {
     628        if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) == 0)
     629            break;
     630        usleep(100 * 1000);
     631    }
     632
     633    if (idx == 20)
    595634    {
    596635        VERBOSE(VB_IMPORTANT, LOC_WARN +
    597636                "Unable to set recording volume" + ENO + "\n\t\t\t" +
    598637                "If you are using an AverMedia M179 card this is normal.");
    599638        return false;
    600639    }
    601     usleep(ioctl_recovery);
    602640
    603641    return true;
    604642}
     
    746784    ctrl_list.push_back(tmp_ctrl);
    747785}
    748786
    749 static void set_ctrls(int fd, vector<struct v4l2_ext_control> &ext_ctrls,
    750                       useconds_t ioctl_recovery)
     787static void set_ctrls(int fd, vector<struct v4l2_ext_control> &ext_ctrls)
    751788{
    752789    static QMutex control_description_lock;
    753790    static QMap<uint32_t,QString> control_description;
     
    776813
    777814    for (uint i = 0; i < ext_ctrls.size(); i++)
    778815    {
     816        uint   idx;
    779817        struct v4l2_ext_controls ctrls;
    780818        bzero(&ctrls, sizeof(struct v4l2_ext_controls));
    781819
     
    785823        ctrls.count       = 1;
    786824        ctrls.controls    = &ext_ctrls[i];
    787825           
    788         if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
     826        for (idx = 0; idx < 20; ++idx)
     827        {
     828            if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) == 0)
     829                break;
     830            usleep(100 * 1000);
     831        }
     832
     833        if (idx == 20)
    789834        {
    790835            QMutexLocker locker(&control_description_lock);
    791836            VERBOSE(VB_IMPORTANT, QString("mpegrecorder.cpp:set_ctrls(): ") +
     
    793838                    .arg(control_description[ext_ctrls[i].id]).arg(value) +
    794839                    ENO);
    795840        }
    796         usleep(ioctl_recovery);
    797841    }
    798842}
    799843
     
    828872        bitrate    = high_mpeg4avgbitrate;
    829873
    830874        // query supported audio codecs and prefer AC3
     875        uint   idx;
    831876        struct v4l2_queryctrl qctrl;
    832877        qctrl.id = V4L2_CID_MPEG_AUDIO_ENCODING;
    833         if (ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) < 0)
     878
     879        for (idx = 0; idx < 20; ++idx)
     880        {
     881            if (ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) == 0)
     882                break;
     883            usleep(100 * 1000);
     884        }
     885
     886        if (idx == 20)
    834887        {
    835888            VERBOSE(VB_IMPORTANT, LOC_WARN +
    836889                    "Unable to get supported audio codecs." + ENO);
    837890        }
    838891        else
    839892        {
    840             usleep(ioctl_recovery);
    841893            if (qctrl.minimum != qctrl.maximum)
    842894                add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_ENCODING,
    843895                             qctrl.maximum);
     
    859911    add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
    860912                 maxbitrate * 1000);
    861913
    862     set_ctrls(chanfd, ext_ctrls, ioctl_recovery);
     914    set_ctrls(chanfd, ext_ctrls);
    863915
    864916    bool ok;
    865917    int audioinput = audiodevice.toUInt(&ok);
    866918    if (ok)
    867919    {
     920        uint   idx;
    868921        struct v4l2_audio ain;
    869922        bzero(&ain, sizeof(ain));
    870923        ain.index = audioinput;
    871         if (ioctl(chanfd, VIDIOC_ENUMAUDIO, &ain) < 0)
     924
     925        for (idx = 0; idx < 20; ++idx)
     926        {
     927            if (ioctl(chanfd, VIDIOC_ENUMAUDIO, &ain) == 0)
     928                break;
     929            usleep(100 * 1000);
     930        }
     931
     932        if (idx == 20)
    872933        {
    873934            VERBOSE(VB_IMPORTANT, LOC_WARN +
    874935                    "Unable to get audio input.");
    875936        }
    876937        else
    877938        {
    878             usleep(ioctl_recovery);
    879939            ain.index = audioinput;
    880             if (ioctl(chanfd, VIDIOC_S_AUDIO, &ain) < 0)
     940
     941            for (idx = 0; idx < 20; ++idx)
     942            {
     943                if (ioctl(chanfd, VIDIOC_S_AUDIO, &ain) == 0)
     944                    break;
     945                usleep(100 * 1000);
     946            }
     947
     948            if (idx == 20)
    881949            {
    882950                VERBOSE(VB_IMPORTANT, LOC_WARN +
    883951                        "Unable to set audio input.");
    884952            }
    885             usleep(ioctl_recovery);
    886953        }
    887954    }
    888955
     
    14151482    if (!request_pause && paused)
    14161483    {
    14171484        VERBOSE(VB_RECORD, LOC + "PauseAndWait unpause");
     1485
     1486        if (driver == "hdpvr")
     1487        {
     1488            h264_parser.Reset();
     1489            _wait_for_keyframe_option = true;
     1490            _seen_sps = false;
     1491
     1492            // Sleep any less than 1.5 seconds, and the HD-PVR will
     1493            // return the old resolution, when the resolution is changing.
     1494            usleep(1500 * 1000);
     1495        }
     1496
    14181497        // Some drivers require streaming to be disabled before
    14191498        // an input switch and other channel format setting.
    14201499        if (requires_special_pause)
     
    14511530        HandleSingleProgramPMT(_stream_data->PMTSingleProgram());
    14521531    }
    14531532   
    1454     _wait_for_keyframe_option = true;
    14551533    if (StartEncoding(readfd))
    14561534    {
    14571535        _device_read_buffer->Start();
     
    14781556
    14791557    VERBOSE(VB_RECORD, LOC + "StartEncoding");
    14801558
    1481     for (int idx = 0; idx < 10; ++idx)
     1559    for (int idx = 0; idx < 20; ++idx)
    14821560    {
    14831561        if (ioctl(fd, VIDIOC_ENCODER_CMD, &command) == 0)
    14841562        {
     1563            if (driver == "hdpvr")
     1564            {
     1565                h264_parser.Reset();
     1566                _wait_for_keyframe_option = true;
     1567                _seen_sps = false;
     1568            }
     1569
    14851570            VERBOSE(VB_RECORD, LOC + "Encoding started");
    1486             usleep(ioctl_recovery);
    14871571            return true;
    14881572        }
    14891573
     
    14931577            return false;
    14941578        }
    14951579
    1496         usleep(250 * 1000);
     1580        usleep(100 * 1000);
    14971581    }
    14981582
    14991583    VERBOSE(VB_IMPORTANT, LOC_ERR + "StartEncoding - giving up" + ENO);
     
    15101594
    15111595    VERBOSE(VB_RECORD, LOC + "StopEncoding");
    15121596
    1513     for (int idx = 0; idx < 10; ++idx)
     1597    for (int idx = 0; idx < 20; ++idx)
    15141598    {
    15151599        if (ioctl(fd, VIDIOC_ENCODER_CMD, &command) == 0)
    15161600        {
    1517             usleep(ioctl_recovery);
    15181601            VERBOSE(VB_RECORD, LOC + "Encoding stopped");
    15191602            return true;
    15201603        }
     
    15251608            return false;
    15261609        }
    15271610
    1528         usleep(250 * 1000);
     1611        usleep(100 * 1000);
    15291612    }
    15301613
    15311614    VERBOSE(VB_IMPORTANT, LOC_ERR + "StopEncoding - giving up" + ENO);
     
    15931676void MpegRecorder::HandleSingleProgramPMT(ProgramMapTable *pmt)
    15941677{
    15951678    if (!pmt)
    1596 {
     1679    {
    15971680        return;
    15981681    }
    15991682
     
    16131696        DTVRecorder::BufferedWrite(*(reinterpret_cast<TSPacket*>(&buf[i])));
    16141697}
    16151698
     1699bool MpegRecorder::WaitFor_HDPVR(void)
     1700{
     1701    // After a resolution change, it can take the HD-PVR a few
     1702    // seconds before it is usable again.
     1703
     1704    // Tell it to start encoding, then wait for it to actually feed us
     1705    // some data.
     1706    QMutexLocker locker(&start_stop_encoding_lock);
     1707
     1708    struct v4l2_encoder_cmd command;
     1709    struct pollfd polls;
     1710    int    idx;
     1711
     1712    memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
     1713    command.cmd = V4L2_ENC_CMD_START;
     1714
     1715    for (idx = 0; idx < 20; ++idx)
     1716    {
     1717        if (ioctl(readfd, VIDIOC_ENCODER_CMD, &command) == 0)
     1718            break;
     1719        usleep(100 * 1000);
     1720    }
     1721
     1722    if (idx == 20)
     1723        return false;
     1724
     1725    polls.fd      = readfd;
     1726    polls.events  = POLLIN;
     1727    polls.revents = 0;
     1728
     1729    for (idx = 0; idx < 10; ++idx)
     1730    {
     1731        if (poll(&polls, 1, 250) > 0)
     1732            break;
     1733    }
     1734
     1735    if (idx == 10)
     1736        return false;
     1737
     1738    // HD-PVR should now be "ready"
     1739    command.cmd = V4L2_ENC_CMD_STOP;
     1740
     1741    for (idx = 0; idx < 20; ++idx)
     1742    {
     1743        if (ioctl(readfd, VIDIOC_ENCODER_CMD, &command) == 0)
     1744            return true;
     1745        usleep(100 * 1000);
     1746    }
     1747
     1748    return false;
     1749}
     1750
    16161751void MpegRecorder::HandleResolutionChanges(void)
    16171752{
    16181753    VERBOSE(VB_RECORD, LOC + "Checking Resolution");
     
    16201755    memset(&vfmt, 0, sizeof(vfmt));
    16211756    vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    16221757           
     1758    if (driver == "hdpvr")
     1759        WaitFor_HDPVR();
     1760
     1761    uint idx;
    16231762    uint pix = 0;
     1763
     1764    for (idx = 0; idx < 20; ++idx)
     1765    {
    16241766    if (0 == ioctl(chanfd, VIDIOC_G_FMT, &vfmt))
    16251767    {
    16261768        VERBOSE(VB_RECORD, LOC + QString("Got Resolution %1x%2")
    16271769                .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
    16281770        pix = vfmt.fmt.pix.width * vfmt.fmt.pix.height;
     1771            break;
     1772        }
     1773        // Typically takes 0.9 seconds after a resolution change
     1774        usleep(100 * 1000);
    16291775    }
    16301776
    16311777    if (!pix)
     1778    {
     1779        VERBOSE(VB_RECORD, LOC + "Giving up detecting resolution");
    16321780        return; // nothing to do, we don't have a resolution yet
     1781    }
    16331782
    16341783    int old_max = maxbitrate, old_avg = bitrate;
    16351784    if (pix <= 768*568)
     
    16871836        add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
    16881837                     maxbitrate * 1000);
    16891838
    1690         set_ctrls(readfd, ext_ctrls, ioctl_recovery);
     1839        set_ctrls(readfd, ext_ctrls);
     1840
    16911841    }
    16921842}