Ticket #1660: 1660-v1.patch

File 1660-v1.patch, 7.1 KB (added by danielk, 18 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);