Ticket #5866: mpegrecorder-hdpvr-v2.patch

File mpegrecorder-hdpvr-v2.patch, 18.5 KB (added by jppoet@…, 12 years ago)

This version should always get the bitrate right.

  • libs/libmythtv/mpegrecorder.h

     
    8080    uint GetFilteredAudioLayer(void) const;
    8181    uint GetFilteredAudioBitRate(uint audio_layer) const;
    8282
     83    void RestartEncoding(void);
    8384    bool StartEncoding(int fd);
    8485    bool StopEncoding(int fd);
    8586
    8687    void ResetForNewFile(void);
    8788
     89    bool WaitFor_HDPVR(void);
    8890    void HandleResolutionChanges(void);
    8991
    9092    inline bool CheckCC(uint pid, uint cc);
     
    104106    // State
    105107    bool recording;
    106108    bool encoding;
    107     bool needs_resolution;
    108109    mutable QMutex start_stop_encoding_lock;
    109110    QMutex recording_wait_lock;
    110111    QWaitCondition recording_wait;
     
    113114    bool cleartimeonpause;
    114115
    115116    // Encoding info
    116     int width, height;
     117    uint width, height;
    117118    int bitrate, maxbitrate, streamtype, aspectratio;
    118119    int audtype, audsamplerate, audbitratel1, audbitratel2, audbitratel3;
    119120    int audvolume;
  • libs/libmythtv/mpegrecorder.cpp

     
    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" {
     
    8687    requires_special_pause(false),
    8788    // State
    8889    recording(false),         encoding(false),
    89     needs_resolution(false),  start_stop_encoding_lock(QMutex::Recursive),
     90    start_stop_encoding_lock(QMutex::Recursive),
    9091    recording_wait_lock(),    recording_wait(),
    9192    // Pausing state
    9293    cleartimeonpause(false),
     
    487488
    488489bool MpegRecorder::SetFormat(int chanfd)
    489490{
     491    uint   idx;
    490492    struct v4l2_format vfmt;
    491493    bzero(&vfmt, sizeof(vfmt));
    492494
    493495    vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    494496
    495     if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) < 0)
     497    for (idx = 0; idx < 20; ++idx)
    496498    {
     499        if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) == 0)
     500            break;
     501        usleep(100 * 1000);
     502    }
     503
     504    if (idx == 10)
     505    {
    497506        VERBOSE(VB_IMPORTANT, LOC_ERR + "Error getting format" + ENO);
    498507        return false;
    499508    }
     
    501510    vfmt.fmt.pix.width = width;
    502511    vfmt.fmt.pix.height = height;
    503512
    504     if (ioctl(chanfd, VIDIOC_S_FMT, &vfmt) < 0)
     513    for (idx = 0; idx < 20; ++idx)
    505514    {
     515        if (ioctl(chanfd, VIDIOC_S_FMT, &vfmt) == 0)
     516            break;
     517        usleep(100 * 1000);
     518    }
     519
     520    if (idx == 20)
     521    {
    506522        VERBOSE(VB_IMPORTANT, LOC_ERR + "Error setting format" + ENO);
    507523        return false;
    508524    }
     
    513529/// Set audio language mode
    514530bool MpegRecorder::SetLanguageMode(int chanfd)
    515531{
     532    uint   idx;
    516533    struct v4l2_tuner vt;
    517534    bzero(&vt, sizeof(struct v4l2_tuner));
    518     if (ioctl(chanfd, VIDIOC_G_TUNER, &vt) < 0)
     535
     536    for (idx = 0; idx < 20; ++idx)
    519537    {
     538        if (ioctl(chanfd, VIDIOC_G_TUNER, &vt) == 0)
     539            break;
     540        usleep(100 * 1000);
     541    }
     542
     543    if (idx == 20)
     544    {
    520545        VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get audio mode" + ENO);
    521546        return false;
    522547    }
     
    549574        success = false;
    550575    }
    551576
    552     if (ioctl(chanfd, VIDIOC_S_TUNER, &vt) < 0)
     577    for (idx = 0; idx < 20; ++idx)
    553578    {
     579        if (ioctl(chanfd, VIDIOC_S_TUNER, &vt) == 0)
     580            break;
     581        usleep(100 * 1000);
     582    }
     583
     584    if (idx == 20)
     585    {
    554586        VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to set audio mode" + ENO);
    555587        success = false;
    556588    }
     
    561593bool MpegRecorder::SetRecordingVolume(int chanfd)
    562594{
    563595    // Get volume min/max values
     596    uint   idx;
    564597    struct v4l2_queryctrl qctrl;
    565598    qctrl.id = V4L2_CID_AUDIO_VOLUME;
    566     if (ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) < 0)
     599
     600    for (idx = 0; idx < 20; ++idx)
    567601    {
     602        if (ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) == 0)
     603            break;
     604        usleep(100 * 1000);
     605    }
     606
     607    if (idx == 20)
     608    {
    568609        VERBOSE(VB_IMPORTANT, LOC_WARN +
    569610                "Unable to get recording volume parameters(max/min)" + ENO +
    570611                "\n\t\t\tusing default range [0,65535].");
     
    582623    ctrl.id = V4L2_CID_AUDIO_VOLUME;
    583624    ctrl.value = ctrl_volume;
    584625
    585     if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) < 0)
     626    for (idx = 0; idx < 20; ++idx)
    586627    {
     628        if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) == 0)
     629            break;
     630        usleep(100 * 1000);
     631    }
     632
     633    if (idx == 20)
     634    {
    587635        VERBOSE(VB_IMPORTANT, LOC_WARN +
    588636                "Unable to set recording volume" + ENO + "\n\t\t\t" +
    589637                "If you are using an AverMedia M179 card this is normal.");
     
    765813
    766814    for (uint i = 0; i < ext_ctrls.size(); i++)
    767815    {
     816        uint   idx;
    768817        struct v4l2_ext_controls ctrls;
    769818        bzero(&ctrls, sizeof(struct v4l2_ext_controls));
    770819
     
    774823        ctrls.count       = 1;
    775824        ctrls.controls    = &ext_ctrls[i];
    776825           
    777         if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
     826        for (idx = 0; idx < 20; ++idx)
    778827        {
     828            if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) == 0)
     829                break;
     830            usleep(100 * 1000);
     831        }
     832
     833        if (idx == 20)
     834        {
    779835            QMutexLocker locker(&control_description_lock);
    780836            VERBOSE(VB_IMPORTANT, QString("mpegrecorder.cpp:set_ctrls(): ") +
    781837                    QString("Could not set %1 to %2")
     
    814870    {
    815871        maxbitrate = high_mpeg4peakbitrate;
    816872        bitrate    = high_mpeg4avgbitrate;
     873
     874        // query supported audio codecs and prefer AC3
     875        uint   idx;
     876        struct v4l2_queryctrl qctrl;
     877        qctrl.id = V4L2_CID_MPEG_AUDIO_ENCODING;
     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)
     887        {
     888            VERBOSE(VB_IMPORTANT, LOC_WARN +
     889                    "Unable to get supported audio codecs." + ENO);
     890        }
     891        else
     892        {
     893            if (qctrl.minimum != qctrl.maximum)
     894                add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_ENCODING,
     895                             qctrl.maximum);
     896        }
    817897    }
    818898    maxbitrate = std::max(maxbitrate, bitrate);
    819899
     
    837917    int audioinput = audiodevice.toUInt(&ok);
    838918    if (ok)
    839919    {
     920        uint   idx;
    840921        struct v4l2_audio ain;
    841922        bzero(&ain, sizeof(ain));
    842923        ain.index = audioinput;
    843         if (ioctl(chanfd, VIDIOC_ENUMAUDIO, &ain) < 0)
     924
     925        for (idx = 0; idx < 20; ++idx)
    844926        {
     927            if (ioctl(chanfd, VIDIOC_ENUMAUDIO, &ain) == 0)
     928                break;
     929            usleep(100 * 1000);
     930        }
     931
     932        if (idx == 20)
     933        {
    845934            VERBOSE(VB_IMPORTANT, LOC_WARN +
    846935                    "Unable to get audio input.");
    847936        }
    848937        else
    849938        {
    850939            ain.index = audioinput;
    851             if (ioctl(chanfd, VIDIOC_S_AUDIO, &ain) < 0)
     940
     941            for (idx = 0; idx < 20; ++idx)
    852942            {
     943                if (ioctl(chanfd, VIDIOC_S_AUDIO, &ain) == 0)
     944                    break;
     945                usleep(100 * 1000);
     946            }
     947
     948            if (idx == 20)
     949            {
    853950                VERBOSE(VB_IMPORTANT, LOC_WARN +
    854951                        "Unable to set audio input.");
    855952            }
     
    10361133    if (deviceIsMpegFile)
    10371134        elapsedTimer.start();
    10381135    else if (_device_read_buffer)
    1039         _device_read_buffer->Start();
     1136    {
     1137        VERBOSE(VB_RECORD, LOC + "Initial startup of recorder");
    10401138
    1041     needs_resolution = (driver == "hdpvr");
     1139        if (StartEncoding(readfd))
     1140            _device_read_buffer->Start();
     1141        else
     1142        {
     1143            VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to start recording");
     1144            recording = false;
     1145            QMutexLocker locker(&recording_wait_lock);
     1146            recording_wait.wakeAll();
     1147            _error = true;
     1148        }
     1149    }
    10421150
    10431151    QByteArray vdevice = videodevice.toAscii();
    10441152    while (encoding && !_error)
    10451153    {
    10461154        if (PauseAndWait(100))
    10471155            continue;
    1048 
    1049         HandleResolutionChanges();
    10501156       
    10511157        if (deviceIsMpegFile)
    10521158        {
     
    10901196            {
    10911197                VERBOSE(VB_IMPORTANT, LOC_ERR + "Device error detected");
    10921198
    1093                 _device_read_buffer->Stop();
    1094 
    1095                 QMutexLocker locker(&start_stop_encoding_lock);
    1096 
    1097                 StopEncoding(readfd);
    1098 
    1099                 // Make sure the next things in the file are a PAT & PMT
    1100                 if (_stream_data->PATSingleProgram() &&
    1101                     _stream_data->PMTSingleProgram())
    1102                 {
    1103                     bool tmp = _wait_for_keyframe_option;
    1104                     _wait_for_keyframe_option = false;
    1105                     HandleSingleProgramPAT(_stream_data->PATSingleProgram());
    1106                     HandleSingleProgramPMT(_stream_data->PMTSingleProgram());
    1107                     _wait_for_keyframe_option = tmp;
    1108                 }
    1109 
    1110                 if (StartEncoding(readfd))
    1111                 {
    1112                     _device_read_buffer->Start();
    1113                 }
    1114                 else
    1115                 {
    1116                     if (0 != close(readfd))
    1117                         VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO);
    1118                    
    1119                     // Force card to be reopened on next iteration..
    1120                     readfd = -1;
    1121                 }
     1199                RestartEncoding();
    11221200            }
    11231201            else if (_device_read_buffer->IsEOF())
    11241202            {
     
    12161294        }
    12171295    }
    12181296
     1297    VERBOSE(VB_RECORD, LOC + "StartRecording finishing up");
     1298
    12191299    if (_device_read_buffer)
    12201300    {
    12211301        if (_device_read_buffer->IsRunning())
     
    12241304        delete _device_read_buffer;
    12251305        _device_read_buffer = NULL;
    12261306    }
     1307
    12271308    StopEncoding(readfd);
    12281309
    12291310    FinishRecording();
     
    13731454
    13741455        if (!paused)
    13751456        {
     1457            VERBOSE(VB_RECORD, LOC + "PauseAndWait pause");
     1458
    13761459            if (_device_read_buffer)
    13771460            {
    13781461                QMutex drb_lock;
    13791462                drb_lock.lock();
    1380 
    13811463                _device_read_buffer->SetRequestPause(true);
    1382 
    1383                 pauseWait.wait(&drb_lock, timeout);
     1464                _device_read_buffer->WaitForPaused(4000);
    13841465            }
    1385             else
    1386             {
    1387                 paused = true;
    1388                 pauseWait.wakeAll();
    1389             }
    13901466
    13911467            // Some drivers require streaming to be disabled before
    13921468            // an input switch and other channel format setting.
    13931469            if (requires_special_pause)
    13941470                StopEncoding(readfd);
    13951471
     1472            paused = true;
     1473            pauseWait.wakeAll();
     1474
    13961475            if (tvrec)
    13971476                tvrec->RecorderPaused();
    13981477        }
    13991478
    14001479        unpauseWait.wait(&waitlock, timeout);
    14011480    }
    1402     if (!request_pause)
     1481
     1482    if (!request_pause && paused)
    14031483    {
    1404         if (paused)
     1484        VERBOSE(VB_RECORD, LOC + "PauseAndWait unpause");
     1485
     1486        if (driver == "hdpvr")
    14051487        {
    1406             // Some drivers require streaming to be disabled before
    1407             // an input switch and other channel format setting.
    1408             if (requires_special_pause)
    1409                 StartEncoding(readfd);
     1488            m_h264_parser.Reset();
     1489            _wait_for_keyframe_option = true;
     1490            _seen_sps = false;
     1491        }
    14101492
    1411             if (_device_read_buffer)
    1412                 _device_read_buffer->SetRequestPause(false);
     1493        // Some drivers require streaming to be disabled before
     1494        // an input switch and other channel format setting.
     1495        if (requires_special_pause)
     1496            StartEncoding(readfd);
     1497       
     1498        if (_device_read_buffer)
     1499            _device_read_buffer->SetRequestPause(false);
     1500       
     1501        if (_stream_data)
     1502            _stream_data->Reset(_stream_data->DesiredProgram());
    14131503
    1414             if (_stream_data)
    1415                 _stream_data->Reset(_stream_data->DesiredProgram());
    1416         }
    14171504        paused = false;
    14181505    }
     1506
    14191507    return paused;
    14201508}
    14211509
     1510void MpegRecorder::RestartEncoding(void)
     1511{
     1512    VERBOSE(VB_RECORD, LOC + "RestartEncoding");
     1513
     1514    _device_read_buffer->Stop();
     1515   
     1516    QMutexLocker locker(&start_stop_encoding_lock);
     1517   
     1518    StopEncoding(readfd);
     1519   
     1520    // Make sure the next things in the file are a PAT & PMT
     1521    if (_stream_data->PATSingleProgram() &&
     1522        _stream_data->PMTSingleProgram())
     1523    {
     1524        _wait_for_keyframe_option = false;
     1525        HandleSingleProgramPAT(_stream_data->PATSingleProgram());
     1526        HandleSingleProgramPMT(_stream_data->PMTSingleProgram());
     1527    }
     1528   
     1529    if (StartEncoding(readfd))
     1530    {
     1531        _device_read_buffer->Start();
     1532    }
     1533    else
     1534    {
     1535        if (0 != close(readfd))
     1536            VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO);
     1537       
     1538        readfd = -1;
     1539    }
     1540}
     1541
    14221542bool MpegRecorder::StartEncoding(int fd)
    14231543{
    14241544    QMutexLocker locker(&start_stop_encoding_lock);
     
    14271547    memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
    14281548    command.cmd = V4L2_ENC_CMD_START;
    14291549
     1550    if (driver == "hdpvr")
     1551        HandleResolutionChanges();
     1552
    14301553    VERBOSE(VB_RECORD, LOC + "StartEncoding");
    1431     needs_resolution = (driver == "hdpvr");
    14321554
    1433     for (int idx = 0; idx < 10; ++idx)
     1555    for (int idx = 0; idx < 20; ++idx)
    14341556    {
    14351557        if (ioctl(fd, VIDIOC_ENCODER_CMD, &command) == 0)
    14361558        {
     1559            if (driver == "hdpvr")
     1560            {
     1561                m_h264_parser.Reset();
     1562                _wait_for_keyframe_option = true;
     1563                _seen_sps = false;
     1564            }
     1565
    14371566            VERBOSE(VB_RECORD, LOC + "Encoding started");
    14381567            return true;
    14391568        }
     
    14441573            return false;
    14451574        }
    14461575
    1447         usleep(250 * 1000);
     1576        usleep(100 * 1000);
    14481577    }
    14491578
    14501579    VERBOSE(VB_IMPORTANT, LOC_ERR + "StartEncoding - giving up" + ENO);
     
    14611590
    14621591    VERBOSE(VB_RECORD, LOC + "StopEncoding");
    14631592
    1464     for (int idx = 0; idx < 10; ++idx)
     1593    for (int idx = 0; idx < 20; ++idx)
    14651594    {
    1466 
    14671595        if (ioctl(fd, VIDIOC_ENCODER_CMD, &command) == 0)
    14681596        {
    14691597            VERBOSE(VB_RECORD, LOC + "Encoding stopped");
     
    14761604            return false;
    14771605        }
    14781606
    1479         usleep(250 * 1000);
     1607        usleep(100 * 1000);
    14801608    }
    14811609
    14821610    VERBOSE(VB_IMPORTANT, LOC_ERR + "StopEncoding - giving up" + ENO);
     
    15441672void MpegRecorder::HandleSingleProgramPMT(ProgramMapTable *pmt)
    15451673{
    15461674    if (!pmt)
    1547 {
     1675    {
    15481676        return;
    15491677    }
    15501678
     
    15641692        DTVRecorder::BufferedWrite(*(reinterpret_cast<TSPacket*>(&buf[i])));
    15651693}
    15661694
     1695bool MpegRecorder::WaitFor_HDPVR(void)
     1696{
     1697    // After a resolution change, it can take the HD-PVR a few
     1698    // seconds before it is usable again.
     1699
     1700    // Tell it to start encoding, then wait for it to actually feed us
     1701    // some data.
     1702    QMutexLocker locker(&start_stop_encoding_lock);
     1703
     1704
     1705    // Sleep any less than 1.5 seconds, and the HD-PVR will
     1706    // return the old resolution, when the resolution is changing.
     1707    usleep(1500 * 1000);
     1708
     1709    struct v4l2_encoder_cmd command;
     1710    struct pollfd polls;
     1711    int    idx;
     1712
     1713    memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
     1714    command.cmd = V4L2_ENC_CMD_START;
     1715
     1716    for (idx = 0; idx < 20; ++idx)
     1717    {
     1718        if (ioctl(readfd, VIDIOC_ENCODER_CMD, &command) == 0)
     1719            break;
     1720        usleep(100 * 1000);
     1721    }
     1722
     1723    if (idx == 20)
     1724        return false;
     1725
     1726    polls.fd      = readfd;
     1727    polls.events  = POLLIN;
     1728    polls.revents = 0;
     1729
     1730    for (idx = 0; idx < 10; ++idx)
     1731    {
     1732        if (poll(&polls, 1, 250) > 0)
     1733            break;
     1734    }
     1735
     1736    if (idx == 10)
     1737        return false;
     1738
     1739    // HD-PVR should now be "ready"
     1740    command.cmd = V4L2_ENC_CMD_STOP;
     1741
     1742    for (idx = 0; idx < 20; ++idx)
     1743    {
     1744        if (ioctl(readfd, VIDIOC_ENCODER_CMD, &command) == 0)
     1745            return true;
     1746        usleep(100 * 1000);
     1747    }
     1748
     1749    return false;
     1750}
     1751
    15671752void MpegRecorder::HandleResolutionChanges(void)
    15681753{
    1569     if (!needs_resolution)
    1570         return;
    1571 
    15721754    VERBOSE(VB_RECORD, LOC + "Checking Resolution");
    15731755    struct v4l2_format vfmt;
    15741756    memset(&vfmt, 0, sizeof(vfmt));
    15751757    vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    15761758           
     1759    if (driver == "hdpvr")
     1760        WaitFor_HDPVR();
     1761
     1762    uint idx;
    15771763    uint pix = 0;
     1764
     1765    for (idx = 0; idx < 20; ++idx)
     1766    {
    15781767    if (0 == ioctl(chanfd, VIDIOC_G_FMT, &vfmt))
    15791768    {
    15801769        VERBOSE(VB_RECORD, LOC + QString("Got Resolution %1x%2")
    15811770                .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
    15821771        pix = vfmt.fmt.pix.width * vfmt.fmt.pix.height;
    1583         needs_resolution = false;
     1772            break;
     1773        }
     1774        // Typically takes 0.9 seconds after a resolution change
     1775        usleep(100 * 1000);
    15841776    }
    15851777
    15861778    if (!pix)
     1779    {
     1780        VERBOSE(VB_RECORD, LOC + "Giving up detecting resolution");
    15871781        return; // nothing to do, we don't have a resolution yet
     1782    }
    15881783
    15891784    int old_max = maxbitrate, old_avg = bitrate;
    15901785    if (pix <= 768*568)
     
    16421837                     maxbitrate * 1000);
    16431838
    16441839        set_ctrls(readfd, ext_ctrls);
     1840
    16451841    }
    1646 
    1647     // Restart streaming. Shouldn't be needed? seems to be with current driver.
    1648     QMutexLocker locker(&start_stop_encoding_lock);
    1649     StopEncoding(readfd);
    1650     StartEncoding(readfd);
    1651 
    1652     needs_resolution = false;
    16531842}
  • libs/libmythtv/DeviceReadBuffer.

    old new  
    4242
    4343    void SetRequestPause(bool request);
    4444    bool IsPaused(void) const;
    45     bool WaitForUnpause(int timeout);
     45    bool WaitForUnpause(unsigned long timeout);
     46    bool WaitForPaused(unsigned long timeout);
    4647   
    4748    bool IsErrored(void) const { return error; }
    4849    bool IsEOF(void)     const { return eof;   }
  • libs/libmythtv/DeviceReadBuffer.

    old new  
    169169    return paused;
    170170}
    171171
    172 bool DeviceReadBuffer::WaitForUnpause(int timeout)
     172bool DeviceReadBuffer::WaitForPaused(unsigned long timeout)
     173{
     174    QMutexLocker locker(&lock);
     175
     176    if (!paused)
     177        pauseWait.wait(&lock, timeout);
     178
     179    return paused;
     180}
     181
     182bool DeviceReadBuffer::WaitForUnpause(unsigned long timeout)
    173183{
    174184    QMutexLocker locker(&lock);
    175185