Ticket #5443: mpegrecorder-drb.patch

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

Add DeviceReadBuffer? to mpegrecorder class

  • 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);
    899 
    900         if (readfd < 0)
    901         {
    902             VERBOSE(VB_IMPORTANT, LOC_ERR +
    903                     QString("Failed to open device '%1'").arg(videodevice));
    904             continue;
     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            }
    905970        }
    906971
    907         bool has_select = true;
    908972
    909 #if defined(__FreeBSD__)
    910         // HACK. FreeBSD PVR150/500 driver doesn't currently support select()
    911         has_select = false;
    912 #endif
     973        if (_device_read_buffer)
     974        {
     975            len = _device_read_buffer->Read(
     976                    &(buffer[remainder]), bufferSize - remainder);
    913977
    914         if (has_select)
     978            // Check for DRB errors
     979            if (_device_read_buffer->IsErrored())
     980            {
     981                VERBOSE(VB_IMPORTANT, LOC_ERR + "Device error detected");
     982                if (close(readfd) != 0)
     983                    VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO);
     984               
     985                // Force card to be reopened on next iteration..
     986//                _error = true;
     987                readfd = -1;
     988            }
     989           
     990            if (_device_read_buffer->IsEOF())
     991            {
     992                VERBOSE(VB_IMPORTANT, LOC_ERR + "Device EOF detected");
     993                _error = true;
     994            }
     995        }
     996        else
    915997        {
    916             tv.tv_sec = 5;
    917             tv.tv_usec = 0;
    918             FD_ZERO(&rdset);
    919             FD_SET(readfd, &rdset);
     998            if (has_select)
     999            {
     1000                tv.tv_sec = 5;
     1001                tv.tv_usec = 0;
     1002                FD_ZERO(&rdset);
     1003                FD_SET(readfd, &rdset);
    9201004
    921             switch (select(readfd + 1, &rdset, NULL, NULL, &tv))
    922             {
    923                 case -1:
     1005                switch (select(readfd + 1, &rdset, NULL, NULL, &tv))
     1006                {
     1007                  case -1:
    9241008                    if (errno == EINTR)
    9251009                        continue;
    9261010
    9271011                    VERBOSE(VB_IMPORTANT, LOC_ERR + "Select error" + ENO);
    9281012                    continue;
    9291013
    930                 case 0:
     1014                  case 0:
    9311015                    VERBOSE(VB_IMPORTANT, LOC_ERR + "select timeout - "
    9321016                            "driver has stopped responding");
    9331017
     
    9411025
    9421026                    continue;
    9431027               
    944                 default: break;
     1028                  default: break;
     1029                }
    9451030            }
    946         }
    9471031
    948         len = read(readfd, &(buffer[remainder]), bufferSize - remainder);
     1032            len = read(readfd, &(buffer[remainder]), bufferSize - remainder);
    9491033
    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)
     1034            if (len < 0 && !has_select)
    9621035            {
    963                 len = read(readfd,
    964                            &(buffer[remainder]), bufferSize - remainder);
     1036                usleep(25 * 1000);
     1037                continue;
    9651038            }
    966 
    967             if (len <= 0)
     1039           
     1040            if ((len == 0) && (deviceIsMpegFile))
    9681041            {
    969                 encoding = false;
     1042                close(readfd);
     1043                readfd = open(vdevice.constData(), O_RDONLY);
     1044               
     1045                if (readfd >= 0)
     1046                {
     1047                    len = read(readfd,
     1048                               &(buffer[remainder]), bufferSize - remainder);
     1049                }
     1050               
     1051                if (len <= 0)
     1052                {
     1053                    encoding = false;
     1054                    continue;
     1055                }
     1056            }
     1057            else if (len < 0 && errno != EAGAIN)
     1058            {
     1059                VERBOSE(VB_IMPORTANT,
     1060                        LOC_ERR + QString("error reading from: %1")
     1061                        .arg(videodevice) + ENO);
    9701062                continue;
    9711063            }
    9721064        }
    973         else if (len < 0 && errno != EAGAIN)
    974         {
    975             VERBOSE(VB_IMPORTANT, LOC_ERR + QString("error reading from: %1")
    976                     .arg(videodevice) + ENO);
    9771065
    978             continue;
    979         }
    980         else if (len > 0)
     1066        if (len > 0)
    9811067        {
    9821068            len += remainder;
    983 
     1069               
    9841070            if (driver == "hdpvr") {
    9851071                remainder = _stream_data->ProcessData(buffer, len);
    9861072                int start_remain = len - remainder;
     
    9961082        }
    9971083    }
    9981084
     1085    if (_device_read_buffer)
     1086    {
     1087        if (_device_read_buffer->IsRunning())
     1088            _device_read_buffer->Stop();
     1089
     1090        delete _device_read_buffer;
     1091        _device_read_buffer = NULL;
     1092    }
     1093
    9991094    FinishRecording();
    10001095
    10011096    delete[] buffer;
     
    10951190void MpegRecorder::StopRecording(void)
    10961191{
    10971192    encoding = false;
     1193    if (_device_read_buffer)
     1194        _device_read_buffer->Stop();
    10981195}
    10991196
    11001197void MpegRecorder::ResetForNewFile(void)
     
    11331230    if (request_pause)
    11341231    {
    11351232        QMutex waitlock;
     1233        waitlock.lock();
     1234
    11361235        if (!paused)
    11371236        {
     1237            if (_device_read_buffer)
     1238            {
     1239                QMutex drb_lock;
     1240                drb_lock.lock();
     1241
     1242                _device_read_buffer->SetRequestPause(true);
     1243
     1244                pauseWait.wait(&drb_lock, timeout);
     1245            }
     1246            else
     1247            {
     1248                paused = true;
     1249                pauseWait.wakeAll();
     1250            }
     1251
    11381252            // Some drivers require streaming to be disabled before
    11391253            // an input switch and other channel format setting.
    11401254            if (requires_special_pause)
    11411255                StopEncoding(readfd);
    11421256
    1143             paused = true;
    1144             pauseWait.wakeAll();
    11451257            if (tvrec)
    11461258                tvrec->RecorderPaused();
    11471259        }
    1148         waitlock.lock();
     1260
    11491261        unpauseWait.wait(&waitlock, timeout);
    11501262    }
    11511263    if (!request_pause)
     
    11571269            if (requires_special_pause)
    11581270                StartEncoding(readfd);
    11591271
     1272            if (_device_read_buffer)
     1273                _device_read_buffer->SetRequestPause(false);
     1274
    11601275            if (_stream_data)
    11611276                _stream_data->Reset(_stream_data->DesiredProgram());
    11621277        }
     
    11671282
    11681283bool MpegRecorder::StartEncoding(int fd)
    11691284{
     1285    int idx;
     1286
     1287    VERBOSE(VB_RECORD, LOC + "StartEncoding");
     1288
     1289    if (driver == "hdpvr")
     1290    {
     1291        VERBOSE(VB_RECORD, LOC + "Waiting for HD-PVR");
     1292        // Make sure it is ready to stream
     1293        struct v4l2_format vfmt;
     1294       
     1295        for (idx = 0; idx < 40; ++idx)
     1296        {
     1297            bzero(&vfmt, sizeof(vfmt));
     1298           
     1299            vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     1300           
     1301            if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) == 0)
     1302                break;
     1303           
     1304            usleep(250 * 1000);
     1305        }
     1306       
     1307        if (idx == 400)
     1308        {
     1309            VERBOSE(VB_IMPORTANT, LOC_ERR +
     1310                    "StartEncoding - HD-PVR not ready, giving up" + ENO);
     1311            return false;
     1312        }
     1313
     1314        VERBOSE(VB_RECORD, QString("HD-PVR video resolution %1 x %2")
     1315                .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
     1316    }
     1317
    11701318    struct v4l2_encoder_cmd command;
    11711319    memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
    11721320    command.cmd = V4L2_ENC_CMD_START;
    11731321
    1174     for (int idx = 0; idx < 10; ++idx)
     1322    for (idx = 0; idx < 40; ++idx)
    11751323    {
    11761324        if (ioctl(fd, VIDIOC_ENCODER_CMD, &command) == 0)
     1325        {
     1326            VERBOSE(VB_RECORD, LOC + "Encoding started");
    11771327            return true;
     1328        }
    11781329
    11791330        if (errno != EAGAIN)
    11801331        {
     
    11951346    memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
    11961347    command.cmd = V4L2_ENC_CMD_STOP;
    11971348
     1349    VERBOSE(VB_RECORD, LOC + "StopEncoding");
     1350
    11981351    for (int idx = 0; idx < 10; ++idx)
    11991352    {
    12001353
    12011354        if (ioctl(fd, VIDIOC_ENCODER_CMD, &command) == 0)
     1355        {
     1356            VERBOSE(VB_RECORD, LOC + "Encoding stopped");
    12021357            return true;
     1358        }
    12031359
    12041360        if (errno != EAGAIN)
    12051361        {