Ticket #5866: mpegrecorder-hdpvr.patch

File mpegrecorder-hdpvr.patch, 13.5 KB (added by jppoet@…, 15 years ago)

check resolution and set bitrate before starting encoding

  • 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
     
    9192
    9293    bool deviceIsMpegFile;
    9394    int bufferSize;
     95    useconds_t ioctl_recovery;
    9496
    9597    // Driver info
    9698    QString  card;
     
    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

     
    8686    requires_special_pause(false),
    8787    // State
    8888    recording(false),         encoding(false),
    89     needs_resolution(false),  start_stop_encoding_lock(QMutex::Recursive),
     89    start_stop_encoding_lock(QMutex::Recursive),
    9090    recording_wait_lock(),    recording_wait(),
    9191    // Pausing state
    9292    cleartimeonpause(false),
     
    389389            has_buggy_vbi = true;
    390390            requires_special_pause =
    391391                (version >= IVTV_KERNEL_VERSION(0, 10, 0));
     392            ioctl_recovery = 0;
    392393        }
    393394        else if (driver == "pvrusb2")
    394395        {
     
    397398            has_v4l2_vbi  = true;
    398399            has_buggy_vbi = true;
    399400            requires_special_pause = true;
     401            ioctl_recovery = 0;
    400402        }
    401403        else if (driver == "hdpvr")
    402404        {
     
    407409            bzero(_stream_id,  sizeof(_stream_id));
    408410            bzero(_pid_status, sizeof(_pid_status));
    409411            memset(_continuity_counter, 0xff, sizeof(_continuity_counter));
     412            ioctl_recovery = 1000;
    410413        }
    411414        else
    412415        {
     
    414417            bufferSize    = 4096;
    415418            usingv4l2     = has_v4l2_vbi = true;
    416419            has_buggy_vbi = requires_special_pause = false;
     420            ioctl_recovery = 0;
    417421        }
    418422    }
    419423
     
    497501        VERBOSE(VB_IMPORTANT, LOC_ERR + "Error getting format" + ENO);
    498502        return false;
    499503    }
     504    usleep(ioctl_recovery);
    500505
    501506    vfmt.fmt.pix.width = width;
    502507    vfmt.fmt.pix.height = height;
     
    506511        VERBOSE(VB_IMPORTANT, LOC_ERR + "Error setting format" + ENO);
    507512        return false;
    508513    }
     514    usleep(ioctl_recovery);
    509515
    510516    return true;
    511517}
     
    520526        VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get audio mode" + ENO);
    521527        return false;
    522528    }
     529    usleep(ioctl_recovery);
    523530
    524531    switch (language)
    525532    {
     
    554561        VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to set audio mode" + ENO);
    555562        success = false;
    556563    }
     564    usleep(ioctl_recovery);
    557565
    558566    return success;
    559567}
     
    571579        qctrl.maximum = 65535;
    572580        qctrl.minimum = 0;
    573581    }
     582    usleep(ioctl_recovery);
    574583
    575584    // calculate volume in card units.
    576585    int range = qctrl.maximum - qctrl.minimum;
     
    589598                "If you are using an AverMedia M179 card this is normal.");
    590599        return false;
    591600    }
     601    usleep(ioctl_recovery);
    592602
    593603    return true;
    594604}
     
    736746    ctrl_list.push_back(tmp_ctrl);
    737747}
    738748
    739 static void set_ctrls(int fd, vector<struct v4l2_ext_control> &ext_ctrls)
     749static void set_ctrls(int fd, vector<struct v4l2_ext_control> &ext_ctrls,
     750                      useconds_t ioctl_recovery)
    740751{
    741752    static QMutex control_description_lock;
    742753    static QMap<uint32_t,QString> control_description;
     
    782793                    .arg(control_description[ext_ctrls[i].id]).arg(value) +
    783794                    ENO);
    784795        }
     796        usleep(ioctl_recovery);
    785797    }
    786798}
    787799
     
    814826    {
    815827        maxbitrate = high_mpeg4peakbitrate;
    816828        bitrate    = high_mpeg4avgbitrate;
     829
     830        // query supported audio codecs and prefer AC3
     831        struct v4l2_queryctrl qctrl;
     832        qctrl.id = V4L2_CID_MPEG_AUDIO_ENCODING;
     833        if (ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) < 0)
     834        {
     835            VERBOSE(VB_IMPORTANT, LOC_WARN +
     836                    "Unable to get supported audio codecs." + ENO);
     837        }
     838        else
     839        {
     840            usleep(ioctl_recovery);
     841            if (qctrl.minimum != qctrl.maximum)
     842                add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_ENCODING,
     843                             qctrl.maximum);
     844        }
    817845    }
    818846    maxbitrate = std::max(maxbitrate, bitrate);
    819847
     
    831859    add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
    832860                 maxbitrate * 1000);
    833861
    834     set_ctrls(chanfd, ext_ctrls);
     862    set_ctrls(chanfd, ext_ctrls, ioctl_recovery);
    835863
    836864    bool ok;
    837865    int audioinput = audiodevice.toUInt(&ok);
     
    847875        }
    848876        else
    849877        {
     878            usleep(ioctl_recovery);
    850879            ain.index = audioinput;
    851880            if (ioctl(chanfd, VIDIOC_S_AUDIO, &ain) < 0)
    852881            {
    853882                VERBOSE(VB_IMPORTANT, LOC_WARN +
    854883                        "Unable to set audio input.");
    855884            }
     885            usleep(ioctl_recovery);
    856886        }
    857887    }
    858888
     
    10361066    if (deviceIsMpegFile)
    10371067        elapsedTimer.start();
    10381068    else if (_device_read_buffer)
    1039         _device_read_buffer->Start();
     1069    {
     1070        VERBOSE(VB_RECORD, LOC + "Initial startup of recorder");
    10401071
    1041     needs_resolution = (driver == "hdpvr");
     1072        if (StartEncoding(readfd))
     1073            _device_read_buffer->Start();
     1074        else
     1075        {
     1076            VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to start recording");
     1077            recording = false;
     1078            QMutexLocker locker(&recording_wait_lock);
     1079            recording_wait.wakeAll();
     1080            _error = true;
     1081        }
     1082    }
    10421083
    10431084    QByteArray vdevice = videodevice.toAscii();
    10441085    while (encoding && !_error)
    10451086    {
    10461087        if (PauseAndWait(100))
    10471088            continue;
    1048 
    1049         HandleResolutionChanges();
    10501089       
    10511090        if (deviceIsMpegFile)
    10521091        {
     
    10901129            {
    10911130                VERBOSE(VB_IMPORTANT, LOC_ERR + "Device error detected");
    10921131
    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                 }
     1132                RestartEncoding();
    11221133            }
    11231134            else if (_device_read_buffer->IsEOF())
    11241135            {
     
    12161227        }
    12171228    }
    12181229
     1230    VERBOSE(VB_RECORD, LOC + "StartRecording finishing up");
     1231
    12191232    if (_device_read_buffer)
    12201233    {
    12211234        if (_device_read_buffer->IsRunning())
     
    12241237        delete _device_read_buffer;
    12251238        _device_read_buffer = NULL;
    12261239    }
     1240
    12271241    StopEncoding(readfd);
    12281242
    12291243    FinishRecording();
     
    13731387
    13741388        if (!paused)
    13751389        {
     1390            VERBOSE(VB_RECORD, LOC + "PauseAndWait pause");
     1391
     1392            // Some drivers require streaming to be disabled before
     1393            // an input switch and other channel format setting.
     1394            if (requires_special_pause)
     1395                StopEncoding(readfd);
     1396
    13761397            if (_device_read_buffer)
    13771398            {
    13781399                QMutex drb_lock;
    13791400                drb_lock.lock();
    1380 
    13811401                _device_read_buffer->SetRequestPause(true);
    1382 
    13831402                pauseWait.wait(&drb_lock, timeout);
    13841403            }
    13851404            else
    1386             {
    1387                 paused = true;
    13881405                pauseWait.wakeAll();
    1389             }
    13901406
    1391             // Some drivers require streaming to be disabled before
    1392             // an input switch and other channel format setting.
    1393             if (requires_special_pause)
    1394                 StopEncoding(readfd);
    1395 
     1407            paused = true;
    13961408            if (tvrec)
    13971409                tvrec->RecorderPaused();
    13981410        }
    13991411
    14001412        unpauseWait.wait(&waitlock, timeout);
    14011413    }
    1402     if (!request_pause)
     1414
     1415    if (!request_pause && paused)
    14031416    {
    1404         if (paused)
    1405         {
    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);
     1417        VERBOSE(VB_RECORD, LOC + "PauseAndWait unpause");
     1418        // Some drivers require streaming to be disabled before
     1419        // an input switch and other channel format setting.
     1420        if (requires_special_pause)
     1421            StartEncoding(readfd);
     1422       
     1423        if (_device_read_buffer)
     1424            _device_read_buffer->SetRequestPause(false);
     1425       
     1426        if (_stream_data)
     1427            _stream_data->Reset(_stream_data->DesiredProgram());
    14101428
    1411             if (_device_read_buffer)
    1412                 _device_read_buffer->SetRequestPause(false);
    1413 
    1414             if (_stream_data)
    1415                 _stream_data->Reset(_stream_data->DesiredProgram());
    1416         }
    14171429        paused = false;
    14181430    }
     1431
    14191432    return paused;
    14201433}
    14211434
     1435void MpegRecorder::RestartEncoding(void)
     1436{
     1437    VERBOSE(VB_RECORD, LOC + "RestartEncoding");
     1438
     1439    _device_read_buffer->Stop();
     1440   
     1441    QMutexLocker locker(&start_stop_encoding_lock);
     1442   
     1443    StopEncoding(readfd);
     1444   
     1445    // Make sure the next things in the file are a PAT & PMT
     1446    if (_stream_data->PATSingleProgram() &&
     1447        _stream_data->PMTSingleProgram())
     1448    {
     1449        _wait_for_keyframe_option = false;
     1450        HandleSingleProgramPAT(_stream_data->PATSingleProgram());
     1451        HandleSingleProgramPMT(_stream_data->PMTSingleProgram());
     1452    }
     1453   
     1454    _wait_for_keyframe_option = true;
     1455    if (StartEncoding(readfd))
     1456    {
     1457        _device_read_buffer->Start();
     1458    }
     1459    else
     1460    {
     1461        if (0 != close(readfd))
     1462            VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO);
     1463       
     1464        readfd = -1;
     1465    }
     1466}
     1467
    14221468bool MpegRecorder::StartEncoding(int fd)
    14231469{
    14241470    QMutexLocker locker(&start_stop_encoding_lock);
     
    14271473    memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
    14281474    command.cmd = V4L2_ENC_CMD_START;
    14291475
     1476    if (driver == "hdpvr")
     1477        HandleResolutionChanges();
     1478
    14301479    VERBOSE(VB_RECORD, LOC + "StartEncoding");
    1431     needs_resolution = (driver == "hdpvr");
    14321480
    14331481    for (int idx = 0; idx < 10; ++idx)
    14341482    {
    14351483        if (ioctl(fd, VIDIOC_ENCODER_CMD, &command) == 0)
    14361484        {
    14371485            VERBOSE(VB_RECORD, LOC + "Encoding started");
     1486            usleep(ioctl_recovery);
    14381487            return true;
    14391488        }
    14401489
     
    14631512
    14641513    for (int idx = 0; idx < 10; ++idx)
    14651514    {
    1466 
    14671515        if (ioctl(fd, VIDIOC_ENCODER_CMD, &command) == 0)
    14681516        {
     1517            usleep(ioctl_recovery);
    14691518            VERBOSE(VB_RECORD, LOC + "Encoding stopped");
    14701519            return true;
    14711520        }
     
    15661615
    15671616void MpegRecorder::HandleResolutionChanges(void)
    15681617{
    1569     if (!needs_resolution)
    1570         return;
    1571 
    15721618    VERBOSE(VB_RECORD, LOC + "Checking Resolution");
    15731619    struct v4l2_format vfmt;
    15741620    memset(&vfmt, 0, sizeof(vfmt));
     
    15801626        VERBOSE(VB_RECORD, LOC + QString("Got Resolution %1x%2")
    15811627                .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
    15821628        pix = vfmt.fmt.pix.width * vfmt.fmt.pix.height;
    1583         needs_resolution = false;
    15841629    }
    15851630
    15861631    if (!pix)
     
    16091654        if (old_max == old_avg)
    16101655        {
    16111656            VERBOSE(VB_RECORD, LOC +
    1612                     QString("Old bitrate %1 CBR").arg(old_avg));
     1657                    QString("Old bitrate %1 CBR for %2x%3")
     1658                    .arg(old_avg).arg(width).arg(height));
    16131659        }
    16141660        else
    16151661        {
    16161662            VERBOSE(VB_RECORD, LOC +
    1617                     QString("Old bitrate %1/%2 VBR")
    1618                     .arg(old_avg).arg(old_max));
     1663                    QString("Old bitrate %1/%2 VBR for %3x%4")
     1664                    .arg(old_avg).arg(old_max).arg(width).arg(height));
    16191665        }
    16201666
    16211667        if (maxbitrate == bitrate)
     
    16411687        add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
    16421688                     maxbitrate * 1000);
    16431689
    1644         set_ctrls(readfd, ext_ctrls);
     1690        set_ctrls(readfd, ext_ctrls, ioctl_recovery);
    16451691    }
    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;
    16531692}