Ticket #1660: 1660-v1.patch

File 1660-v1.patch, 7.1 KB (added by danielk, 6 years ago)

use devicereadbuffer for ivtv

  • libs/libmythtv/mpegrecorder.h

     
    44#define MPEGRECORDER_H_ 
    55 
    66#include "recorderbase.h" 
     7#include "DeviceReadBuffer.h" 
    78 
    89struct AVFormatContext; 
    910struct AVPacket; 
    1011 
    11 class MpegRecorder : public RecorderBase 
     12class MpegRecorder : public RecorderBase, private ReaderPausedCB 
    1213{ 
    1314  public: 
    1415    MpegRecorder(TVRec*); 
     
    5657 
    5758    void ResetForNewFile(void); 
    5859 
     60    void ReaderPaused(int fd); 
     61    bool PauseAndWait(int timeout = 100); 
     62 
    5963    bool deviceIsMpegFile; 
    6064    int bufferSize; 
    6165 
    6266    // State 
    6367    bool recording; 
    64     bool encoding; 
     68    bool request_recording; 
    6569    bool errored; 
    6670 
    6771    // Pausing state 
     
    7983    // Input file descriptors 
    8084    int chanfd; 
    8185    int readfd; 
     86    DeviceReadBuffer *drb; 
    8287 
    8388    // Keyframe tracking inforamtion 
    8489    int keyframedist; 
  • libs/libmythtv/mpegrecorder.cpp

     
    7373    deviceIsMpegFile(false), 
    7474    bufferSize(4096), 
    7575    // State 
    76     recording(false),         encoding(false), 
     76    recording(false),         request_recording(false), 
    7777    errored(false), 
    7878    // Pausing state 
    7979    cleartimeonpause(false), 
     
    8888    audvolume(80), 
    8989    // Input file descriptors 
    9090    chanfd(-1),               readfd(-1), 
     91    drb(NULL), 
    9192    // Keyframe tracking inforamtion 
    9293    keyframedist(15),         gopset(false), 
    9394    leftovers(0),             lastpackheaderpos(0), 
     
    9899    buildbuffer(new unsigned char[kBuildBufferMaxSize + 1]), 
    99100    buildbuffersize(0) 
    100101{ 
     102    drb = new DeviceReadBuffer(this); 
    101103} 
    102104 
    103105MpegRecorder::~MpegRecorder() 
     
    113115        close(chanfd); 
    114116        chanfd = -1; 
    115117    } 
     118 
    116119    if (readfd >= 0) 
    117120    { 
    118121        close(readfd); 
    119122        readfd = -1; 
    120123    } 
     124 
     125    if (drb) 
     126    { 
     127        delete drb; 
     128        drb = NULL; 
     129    } 
    121130} 
    122131 
    123132void MpegRecorder::SetOption(const QString &opt, int value) 
     
    462471        return; 
    463472    } 
    464473 
    465     encoding = true; 
     474    request_recording = true; 
    466475    recording = true; 
    467476    unsigned char *buffer = new unsigned char[bufferSize + 1]; 
    468477    int ret; 
     
    470479    MythTimer elapsedTimer; 
    471480    float elapsed; 
    472481 
    473     struct timeval tv; 
    474     fd_set rdset; 
    475  
    476482    if (deviceIsMpegFile) 
    477483        elapsedTimer.start(); 
    478484 
    479     while (encoding) 
     485    while (deviceIsMpegFile && request_recording && !errored) 
    480486    { 
    481487        if (PauseAndWait(100)) 
    482488            continue; 
     
    494500        if (readfd < 0) 
    495501            readfd = open(videodevice.ascii(), O_RDWR); 
    496502 
    497         tv.tv_sec = 5; 
    498         tv.tv_usec = 0; 
    499         FD_ZERO(&rdset); 
    500         FD_SET(readfd, &rdset); 
    501  
    502         switch (select(readfd + 1, &rdset, NULL, NULL, &tv)) 
    503         { 
    504             case -1: 
    505                 if (errno == EINTR) 
    506                     continue; 
    507  
    508                 VERBOSE(VB_IMPORTANT, LOC_ERR + "Select error" + ENO); 
    509                 continue; 
    510  
    511             case 0: 
    512                 VERBOSE(VB_IMPORTANT, LOC_ERR + "select timeout - " 
    513                         "ivtv driver has stopped responding"); 
    514  
    515                 if (close(readfd) != 0) 
    516                 { 
    517                     VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO); 
    518                 } 
    519  
    520                 readfd = -1; // Force PVR card to be reopened on next iteration 
    521                 continue; 
    522  
    523            default: break; 
    524         } 
    525  
    526503        ret = read(readfd, buffer, bufferSize); 
    527504 
    528         if ((ret == 0) && 
    529             (deviceIsMpegFile)) 
     505        if (ret == 0) 
    530506        { 
    531507            close(readfd); 
    532508            readfd = open(videodevice.ascii(), O_RDONLY); 
     
    535511                ret = read(readfd, buffer, bufferSize); 
    536512            if (ret <= 0) 
    537513            { 
    538                 encoding = false; 
     514                request_recording = false; 
    539515                continue; 
    540516            } 
    541517        } 
     
    552528        } 
    553529    } 
    554530 
     531    if (!deviceIsMpegFile) 
     532    { 
     533        VERBOSE(VB_IMPORTANT, QString("DRB:Setup(%1, %2)") 
     534                .arg(videodevice).arg(readfd)); 
     535        if (!drb->Setup(videodevice, readfd)) 
     536        { 
     537            VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to allocate DRB buffer"); 
     538            //Close(); 
     539            errored = true; 
     540        } 
     541        else 
     542        { 
     543            drb->Start(); 
     544        } 
     545    } 
     546 
     547    while (request_recording && !errored && !deviceIsMpegFile) 
     548    { 
     549        if (PauseAndWait(100)) 
     550            continue; 
     551 
     552        ssize_t len = drb->Read(buffer, bufferSize); 
     553        if (len > 0) 
     554        { 
     555            ProcessData(buffer, len); 
     556        } 
     557        else if (len == 0) 
     558        { 
     559            // Recover from timeout error by reopening ivtv device. 
     560            VERBOSE(VB_IMPORTANT, LOC_ERR + "Driver has stopped responding."); 
     561            /* 
     562            drb->Stop(); 
     563            if (close(readfd) != 0) 
     564                VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO); 
     565            readfd = open(videodevice.ascii(), O_RDWR); 
     566            if (readfd < 0) 
     567                errored = true; 
     568            drb->Reset(videodevice, readfd); 
     569            drb->Start(); 
     570            */ 
     571        } 
     572 
     573        // Check for DRB errors 
     574        if (drb->IsErrored()) 
     575        { 
     576            VERBOSE(VB_IMPORTANT, LOC_ERR + "Device error detected"); 
     577            errored = true; 
     578        } 
     579 
     580        if (drb->IsEOF()) 
     581        { 
     582            VERBOSE(VB_IMPORTANT, LOC_ERR + "Device EOF detected"); 
     583            errored = true; 
     584        } 
     585    } 
     586 
     587    if (drb && drb->IsRunning()) 
     588        drb->Stop(); 
     589 
     590    //Close(); 
     591 
    555592    FinishRecording(); 
    556593 
    557594    delete[] buffer; 
    558595    recording = false; 
    559596} 
    560597 
     598void MpegRecorder::StopRecording(void) 
     599{ 
     600    request_recording = false; 
     601 
     602    if (drb && drb->IsRunning()) 
     603        drb->Stop(); 
     604 
     605    while (recording) 
     606        usleep(2000); 
     607} 
     608 
    561609bool MpegRecorder::SetupRecording(void) 
    562610{ 
    563611    leftovers = 0xFFFFFFFF; 
     
    664712    buildbuffersize += leftlen; 
    665713} 
    666714 
    667 void MpegRecorder::StopRecording(void) 
    668 { 
    669     encoding = false; 
    670 } 
    671  
    672715void MpegRecorder::ResetForNewFile(void) 
    673716{ 
    674717    errored = false; 
     
    694737void MpegRecorder::Pause(bool clear) 
    695738{ 
    696739    cleartimeonpause = clear; 
    697     paused = false; 
    698     request_pause = true; 
     740    RecorderBase::Pause(clear); 
    699741} 
    700742 
     743void MpegRecorder::ReaderPaused(int /*fd*/) 
     744{ 
     745    pauseWait.wakeAll(); 
     746    if (tvrec) 
     747        tvrec->RecorderPaused(); 
     748} 
     749 
     750bool MpegRecorder::PauseAndWait(int timeout) 
     751{ 
     752    if (request_pause) 
     753    { 
     754        paused = true; 
     755        if (!drb->IsPaused()) 
     756            drb->SetRequestPause(true); 
     757 
     758        unpauseWait.wait(timeout); 
     759    } 
     760    else if (drb->IsPaused()) 
     761    { 
     762        drb->SetRequestPause(false); 
     763        drb->WaitForUnpause(timeout); 
     764        paused = drb->IsPaused(); 
     765    } 
     766    else 
     767    { 
     768        paused = false; 
     769    } 
     770    return paused; 
     771} 
     772 
    701773long long MpegRecorder::GetKeyframePosition(long long desired) 
    702774{ 
    703775    QMutexLocker locker(&positionMapLock);