Ticket #5443: mpegrecorder-drb-poll.patch

File mpegrecorder-drb-poll.patch, 13.7 KB (added by jppoet@…, 4 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        {