Ticket #5443: mpegrecorder-drb-poll.patch

File mpegrecorder-drb-poll.patch, 13.7 KB (added by jppoet@…, 16 years ago)

Use DeviceReadBuffer? in mpegrecorder

  • libs/libmythtv/mpegrecorder.h

     
    66#include "dtvrecorder.h"
    77#include "tspacket.h"
    88#include "mpegstreamdata.h"
     9#include "DeviceReadBuffer.h"
    910
    1011struct AVFormatContext;
    1112struct AVPacket;
     
    1314class MpegRecorder : public DTVRecorder,
    1415                     public MPEGSingleProgramStreamListener,
    1516                     public TSPacketListener,
    16                      public TSPacketListenerAV
     17                     public TSPacketListenerAV,
     18                     public ReaderPausedCB
    1719{
    1820  public:
    1921    MpegRecorder(TVRec*);
     
    5860    void HandleSingleProgramPAT(ProgramAssociationTable *pat);
    5961    void HandleSingleProgramPMT(ProgramMapTable *pmt);
    6062
     63    // ReaderPausedCB
     64    virtual void ReaderPaused(int fd) { paused = true; pauseWait.wakeAll(); }
     65
    6166  private:
    6267    bool OpenMpegFileAsInput(void);
    6368    bool OpenV4L2DeviceAsInput(void);
     
    116121    static const char *aspectRatio[];
    117122    static const unsigned int kBuildBufferMaxSize;
    118123
     124    // Buffer device reads
     125    DeviceReadBuffer *_device_read_buffer;
     126
    119127    // TS
    120128    MPEGStreamData *_stream_data;
    121129    unsigned char   _stream_id[0x1fff  + 1];
  • libs/libmythtv/mpegrecorder.cpp

     
    9595    audvolume(80),            language(0),
    9696    // Input file descriptors
    9797    chanfd(-1),               readfd(-1),
     98    _device_read_buffer(NULL),
    9899    // TS packet handling
    99     _stream_data(NULL)                                   
     100    _stream_data(NULL)
    100101{
    101102}
    102103
     
    107108
    108109void MpegRecorder::TeardownAll(void)
    109110{
     111    StopRecording();
     112
    110113    if (chanfd >= 0)
    111114    {
    112115        close(chanfd);
     
    352355            .arg(usingv4l2).arg(has_v4l2_vbi).arg(has_buggy_vbi));
    353356
    354357
    355     if ((driver != "hdpvr") && !SetFormat(chanfd))
     358    if (driver == "hdpvr")
     359    {
     360        struct v4l2_format vfmt;
     361        bzero(&vfmt, sizeof(vfmt));
     362           
     363        vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     364           
     365        if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) == 0)
     366            VERBOSE(VB_RECORD, QString("HD-PVR video resolution %1 x %2")
     367                    .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
     368        else
     369            VERBOSE(VB_IMPORTANT,
     370                    LOC_ERR + "HD-PVR driver did not return video resolution.");
     371    }
     372    else if (!SetFormat(chanfd))
    356373        return false;
    357374
    358375    if (driver != "hdpvr")
     
    384401        return false;
    385402    }
    386403
     404    if (_device_read_buffer)
     405    {
     406        if (_device_read_buffer->IsRunning())
     407            _device_read_buffer->Stop();
     408       
     409        delete _device_read_buffer;
     410        _device_read_buffer = NULL;
     411    }
     412
     413    _device_read_buffer = new DeviceReadBuffer(this);
     414   
     415    if (!_device_read_buffer)
     416    {
     417        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to allocate DRB buffer");
     418        _error = true;
     419        return false;   
     420    }
     421
     422    if (!_device_read_buffer->Setup(vdevice.constData(), readfd))
     423    {
     424        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to allocate DRB buffer");
     425        _error = true;
     426        return false;
     427    }
     428
     429    VERBOSE(VB_RECORD, LOC + "DRB ready");
     430
    387431    return true;
    388432}
    389433
     
    842886        return;
    843887    }
    844888
     889    bool has_select = true;
     890   
     891#if defined(__FreeBSD__)
     892    // HACK. FreeBSD PVR150/500 driver doesn't currently support select()
     893    has_select = false;
     894#endif
     895
    845896    _start_code = 0xffffffff;
    846897    _last_gop_seen = 0;
    847898    _frames_written_count = 0;
     
    877928
    878929    if (deviceIsMpegFile)
    879930        elapsedTimer.start();
     931    else if (_device_read_buffer)
     932        _device_read_buffer->Start();
    880933
    881934    QByteArray vdevice = videodevice.toAscii();
    882     while (encoding)
     935    while (encoding && !_error)
    883936    {
    884937        if (PauseAndWait(100))
    885938            continue;
    886939
    887         if ((deviceIsMpegFile) && (GetFramesWritten()))
     940        if (deviceIsMpegFile)
    888941        {
    889             elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
    890             while ((GetFramesWritten() / elapsed) > 30)
     942            if (GetFramesWritten())
    891943            {
    892                 usleep(50000);
    893944                elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
     945                while ((GetFramesWritten() / elapsed) > 30)
     946                {
     947                    usleep(50000);
     948                    elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
     949                }
    894950            }
    895951        }
     952        else
     953        {
     954            if (readfd < 0)
     955            {
     956                if (!Open())
     957                {
     958                    _error = true;
     959                    return;
     960                }
    896961
    897         if (readfd < 0)
    898             readfd = open(vdevice.constData(), O_RDWR);
     962                if (readfd < 0)
     963                {
     964                    VERBOSE(VB_IMPORTANT, LOC_ERR +
     965                            QString("Failed to open device '%1'")
     966                            .arg(videodevice));
     967                    continue;
     968                }
     969            }
     970        }
    899971
    900         if (readfd < 0)
     972
     973        if (_device_read_buffer)
    901974        {
    902             VERBOSE(VB_IMPORTANT, LOC_ERR +
    903                     QString("Failed to open device '%1'").arg(videodevice));
    904             continue;
    905         }
     975            len = _device_read_buffer->Read(
     976                    &(buffer[remainder]), bufferSize - remainder);
    906977
    907         bool has_select = true;
     978            // Check for DRB errors
     979            if (_device_read_buffer->IsErrored())
     980            {
     981                VERBOSE(VB_IMPORTANT, LOC_ERR + "Device error detected");
    908982
    909 #if defined(__FreeBSD__)
    910         // HACK. FreeBSD PVR150/500 driver doesn't currently support select()
    911         has_select = false;
    912 #endif
    913 
    914         if (has_select)
     983                _device_read_buffer->Stop();
     984                StopEncoding(readfd);
     985                usleep(1000);
     986                if (StartEncoding(readfd))
     987                {
     988                    _device_read_buffer->Start();
     989                    // Make sure the next things in the file are a PAT & PMT
     990                    _wait_for_keyframe_option = false;
     991                    HandleSingleProgramPAT(_stream_data->PATSingleProgram());
     992                    HandleSingleProgramPMT(_stream_data->PMTSingleProgram());
     993                    _wait_for_keyframe_option = true;
     994                }
     995                else
     996                {
     997                    if (close(readfd) != 0)
     998                        VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO);
     999                   
     1000                    // Force card to be reopened on next iteration..
     1001                    readfd = -1;
     1002                }
     1003            }
     1004            else if (_device_read_buffer->IsEOF())
     1005            {
     1006                VERBOSE(VB_IMPORTANT, LOC_ERR + "Device EOF detected");
     1007                _error = true;
     1008            }
     1009        }
     1010        else
    9151011        {
    916             tv.tv_sec = 5;
    917             tv.tv_usec = 0;
    918             FD_ZERO(&rdset);
    919             FD_SET(readfd, &rdset);
     1012            if (has_select)
     1013            {
     1014                tv.tv_sec = 5;
     1015                tv.tv_usec = 0;
     1016                FD_ZERO(&rdset);
     1017                FD_SET(readfd, &rdset);
    9201018
    921             switch (select(readfd + 1, &rdset, NULL, NULL, &tv))
    922             {
    923                 case -1:
     1019                switch (select(readfd + 1, &rdset, NULL, NULL, &tv))
     1020                {
     1021                  case -1:
    9241022                    if (errno == EINTR)
    9251023                        continue;
    9261024
    9271025                    VERBOSE(VB_IMPORTANT, LOC_ERR + "Select error" + ENO);
    9281026                    continue;
    9291027
    930                 case 0:
     1028                  case 0:
    9311029                    VERBOSE(VB_IMPORTANT, LOC_ERR + "select timeout - "
    9321030                            "driver has stopped responding");
    9331031
     
    9411039
    9421040                    continue;
    9431041               
    944                 default: break;
     1042                  default: break;
     1043                }
    9451044            }
    946         }
    9471045
    948         len = read(readfd, &(buffer[remainder]), bufferSize - remainder);
     1046            len = read(readfd, &(buffer[remainder]), bufferSize - remainder);
    9491047
    950         if (len < 0 && !has_select)
    951         {
    952             usleep(25 * 1000);
    953             continue;
    954         }
    955 
    956         if ((len == 0) && (deviceIsMpegFile))
    957         {
    958             close(readfd);
    959             readfd = open(vdevice.constData(), O_RDONLY);
    960 
    961             if (readfd >= 0)
     1048            if (len < 0 && !has_select)
    9621049            {
    963                 len = read(readfd,
    964                            &(buffer[remainder]), bufferSize - remainder);
     1050                usleep(25 * 1000);
     1051                continue;
    9651052            }
    966 
    967             if (len <= 0)
     1053           
     1054            if ((len == 0) && (deviceIsMpegFile))
    9681055            {
    969                 encoding = false;
     1056                close(readfd);
     1057                readfd = open(vdevice.constData(), O_RDONLY);
     1058               
     1059                if (readfd >= 0)
     1060                {
     1061                    len = read(readfd,
     1062                               &(buffer[remainder]), bufferSize - remainder);
     1063                }
     1064               
     1065                if (len <= 0)
     1066                {
     1067                    encoding = false;
     1068                    continue;
     1069                }
     1070            }
     1071            else if (len < 0 && errno != EAGAIN)
     1072            {
     1073                VERBOSE(VB_IMPORTANT,
     1074                        LOC_ERR + QString("error reading from: %1")
     1075                        .arg(videodevice) + ENO);
    9701076                continue;
    9711077            }
    9721078        }
    973         else if (len < 0 && errno != EAGAIN)
    974         {
    975             VERBOSE(VB_IMPORTANT, LOC_ERR + QString("error reading from: %1")
    976                     .arg(videodevice) + ENO);
    9771079
    978             continue;
    979         }
    980         else if (len > 0)
     1080        if (len > 0)
    9811081        {
    9821082            len += remainder;
    983 
     1083               
    9841084            if (driver == "hdpvr") {
    9851085                remainder = _stream_data->ProcessData(buffer, len);
    9861086                int start_remain = len - remainder;
     
    9961096        }
    9971097    }
    9981098
     1099    if (_device_read_buffer)
     1100    {
     1101        if (_device_read_buffer->IsRunning())
     1102            _device_read_buffer->Stop();
     1103
     1104        delete _device_read_buffer;
     1105        _device_read_buffer = NULL;
     1106    }
     1107
    9991108    FinishRecording();
    10001109
    10011110    delete[] buffer;
     
    10951204void MpegRecorder::StopRecording(void)
    10961205{
    10971206    encoding = false;
     1207    if (_device_read_buffer)
     1208        _device_read_buffer->Stop();
     1209    StopEncoding(readfd);
    10981210}
    10991211
    11001212void MpegRecorder::ResetForNewFile(void)
     
    11331245    if (request_pause)
    11341246    {
    11351247        QMutex waitlock;
     1248        waitlock.lock();
     1249
    11361250        if (!paused)
    11371251        {
     1252            if (_device_read_buffer)
     1253            {
     1254                QMutex drb_lock;
     1255                drb_lock.lock();
     1256
     1257                _device_read_buffer->SetRequestPause(true);
     1258
     1259                pauseWait.wait(&drb_lock, timeout);
     1260            }
     1261            else
     1262            {
     1263                paused = true;
     1264                pauseWait.wakeAll();
     1265            }
     1266
    11381267            // Some drivers require streaming to be disabled before
    11391268            // an input switch and other channel format setting.
    11401269            if (requires_special_pause)
    11411270                StopEncoding(readfd);
    11421271
    1143             paused = true;
    1144             pauseWait.wakeAll();
    11451272            if (tvrec)
    11461273                tvrec->RecorderPaused();
    11471274        }
    1148         waitlock.lock();
     1275
    11491276        unpauseWait.wait(&waitlock, timeout);
    11501277    }
    11511278    if (!request_pause)
     
    11571284            if (requires_special_pause)
    11581285                StartEncoding(readfd);
    11591286
     1287            if (_device_read_buffer)
     1288                _device_read_buffer->SetRequestPause(false);
     1289
    11601290            if (_stream_data)
    11611291                _stream_data->Reset(_stream_data->DesiredProgram());
    11621292        }
     
    11671297
    11681298bool MpegRecorder::StartEncoding(int fd)
    11691299{
     1300    int idx;
     1301
     1302    VERBOSE(VB_RECORD, LOC + "StartEncoding");
     1303
     1304    if (driver == "hdpvr")
     1305    {
     1306        VERBOSE(VB_RECORD, LOC + "Waiting for HD-PVR");
     1307        // Make sure it is ready to stream
     1308        struct v4l2_format vfmt;
     1309       
     1310        for (idx = 0; idx < 40; ++idx)
     1311        {
     1312            bzero(&vfmt, sizeof(vfmt));
     1313           
     1314            vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     1315           
     1316            if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) == 0)
     1317                break;
     1318           
     1319            usleep(250 * 1000);
     1320        }
     1321       
     1322        if (idx == 400)
     1323        {
     1324            VERBOSE(VB_IMPORTANT, LOC_ERR +
     1325                    "StartEncoding - HD-PVR not ready, giving up" + ENO);
     1326            return false;
     1327        }
     1328
     1329        VERBOSE(VB_RECORD, QString("HD-PVR video resolution %1 x %2")
     1330                .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
     1331    }
     1332
    11701333    struct v4l2_encoder_cmd command;
    11711334    memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
    11721335    command.cmd = V4L2_ENC_CMD_START;
    11731336
    1174     for (int idx = 0; idx < 10; ++idx)
     1337    for (idx = 0; idx < 40; ++idx)
    11751338    {
    11761339        if (ioctl(fd, VIDIOC_ENCODER_CMD, &command) == 0)
     1340        {
     1341            VERBOSE(VB_RECORD, LOC + "Encoding started");
    11771342            return true;
     1343        }
    11781344
    11791345        if (errno != EAGAIN)
    11801346        {
     
    11951361    memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
    11961362    command.cmd = V4L2_ENC_CMD_STOP;
    11971363
     1364    VERBOSE(VB_RECORD, LOC + "StopEncoding");
     1365
    11981366    for (int idx = 0; idx < 10; ++idx)
    11991367    {
    12001368
    12011369        if (ioctl(fd, VIDIOC_ENCODER_CMD, &command) == 0)
     1370        {
     1371            VERBOSE(VB_RECORD, LOC + "Encoding stopped");
    12021372            return true;
     1373        }
    12031374
    12041375        if (errno != EAGAIN)
    12051376        {