summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Hanisch <dvb@flensrocker.de>2010-08-12 18:21:59 +0200
committerLars Hanisch <dvb@flensrocker.de>2010-08-12 18:21:59 +0200
commit2c3fec5ac120b88c17633ff8a0dfae0091a4964a (patch)
treecc8bd2a0a64db3a97f549b432dc924d828035369
parentb856f4fb464607fe195f34cb3523429d7d3f4d2f (diff)
parent643ebe816466891354cf511e9a570236a8884d7e (diff)
downloadvdr-plugin-pvrinput-2c3fec5ac120b88c17633ff8a0dfae0091a4964a.tar.gz
vdr-plugin-pvrinput-2c3fec5ac120b88c17633ff8a0dfae0091a4964a.tar.bz2
Merge branch 'reader-with-select'
Use select before read with timeout and reopen v4l2-device if select reports an error. Reading from the Hauppauge HD PVR hangs sometimes on bad video input and forces vdr to restart. With this workaround the vdr doesn't stop and there's only a few seconds missing in the recording.
-rwxr-xr-x[-rw-r--r--]device.c23
-rwxr-xr-x[-rw-r--r--]device.h1
-rwxr-xr-x[-rw-r--r--]pvrinput.c2
-rwxr-xr-x[-rw-r--r--]reader.c61
4 files changed, 72 insertions, 15 deletions
diff --git a/device.c b/device.c
index 049f553..c707fa2 100644..100755
--- a/device.c
+++ b/device.c
@@ -345,6 +345,29 @@ cPvrDevice *cPvrDevice::Get(int index)
return NULL;
}
+int cPvrDevice::ReOpen(void)
+{
+ log(pvrDEBUG1, "cPvrDevice::ReOpen /dev/video%d = %s (%s)", number, CARDNAME[cardname], DRIVERNAME[driver]);
+ int retry_count = 5;
+ cString devName = cString::sprintf("/dev/video%d", number);
+ retry:
+ close(v4l2_fd);
+ v4l2_fd = open(devName, O_RDWR);
+ if (v4l2_fd < 0) {
+ log(pvrERROR, "cPvrDevice::ReOpen: error reopening %s (%s): %d:%s",
+ CARDNAME[cardname], *devName, errno, strerror(errno));
+ retry_count--;
+ if (retry_count > 0) {
+ usleep(1000000);
+ goto retry;
+ }
+ }
+ else {
+ log(pvrDEBUG2, "cPvrDevice::ReOpen: %s (%s) successfully re-opened", *devName, CARDNAME[cardname]);
+ }
+ return v4l2_fd;
+}
+
void cPvrDevice::ReInit(void)
{
log(pvrDEBUG1, "cPvrDevice::ReInit /dev/video%d = %s (%s)", number, CARDNAME[cardname], DRIVERNAME[driver]);
diff --git a/device.h b/device.h
index a62f382..75daa71 100644..100755
--- a/device.h
+++ b/device.h
@@ -133,6 +133,7 @@ public:
virtual int NumProvidedSystems(void) const;
bool ParseChannel(const cChannel *Channel, int *input, uint64_t *norm, int *LinesPerFrame, int *card,
eInputType *inputType, int *apid, int *vpid, int *tpid) const;
+ int ReOpen(void);
void ReInit(void);
void StopReadThread(void);
void GetStandard(void);
diff --git a/pvrinput.c b/pvrinput.c
index 8e24eb9..f89b054 100644..100755
--- a/pvrinput.c
+++ b/pvrinput.c
@@ -6,7 +6,7 @@
#endif
#endif
-static const char *VERSION = "2010-04-14";
+static const char *VERSION = "2010-08-12";
static const char *DESCRIPTION = tr("use Hauppauge PVR as input device");
static const char *MAINMENUENTRY = tr("PVR picture settings");
diff --git a/reader.c b/reader.c
index debed07..9d4e152 100644..100755
--- a/reader.c
+++ b/reader.c
@@ -500,6 +500,10 @@ void cPvrReadThread::Action(void)
uint8_t *buffer = new uint8_t[bufferSize];
int r;
int retries = 3;
+ int reopen_retries = 5;
+ struct timeval selTimeout;
+ fd_set selSet;
+
log(pvrDEBUG1,"cPvrReadThread::Action(): Entering Action()");
// A derived cThread class must check Running()
// repeatedly to see whether it's time to stop.
@@ -543,21 +547,50 @@ void cPvrReadThread::Action(void)
}
retry:
while (Running() && parent->readThreadRunning) {
- r = read(parent->v4l2_fd, buffer, bufferSize);
- if (r < 0) {
- log(pvrERROR, "cPvrReadThread::Action():error reading from /dev/video%d: %d:%s %s",
- parent->number, errno, strerror(errno), (--retries > 0) ? " - retrying" : "");
- if (retries > 0) {
- usleep(100);
- goto retry;
+ selTimeout.tv_sec = 0;
+ selTimeout.tv_usec = 200000;
+ FD_ZERO(&selSet);
+ FD_SET(parent->v4l2_fd, &selSet);
+ r = select(parent->v4l2_fd + 1, &selSet, 0, 0, &selTimeout);
+ if ((r == 0) && (errno == 0)) {
+ log(pvrDEBUG1, "cPvrReadThread::Action():timeout on select from /dev/video%d: %d:%s %s",
+ parent->number, errno, strerror(errno), (retries > 0) ? " - retrying" : "");
+ }
+ else if ((r < 0) || (errno != 0)) {
+ log(pvrERROR, "cPvrReadThread::Action():error on select from /dev/video%d: %d:%s %s",
+ parent->number, errno, strerror(errno), (retries > 0) ? " - retrying" : "");
+ retries--;
+ if (retries > 0) {
+ usleep(100);
+ goto retry;
+ }
+ while (reopen_retries > 0) {
+ reopen_retries--;
+ if (parent->ReOpen() > 0) {
+ retries = 3;
+ goto retry;
+ }
+ }
+ break;
+ }
+ else if (FD_ISSET(parent->v4l2_fd, &selSet)) {
+ r = read(parent->v4l2_fd, buffer, bufferSize);
+ if (r < 0) {
+ log(pvrERROR, "cPvrReadThread::Action():error reading from /dev/video%d: %d:%s %s",
+ parent->number, errno, strerror(errno), (retries > 0) ? " - retrying" : "");
+ retries--;
+ if (retries > 0) {
+ usleep(100);
+ goto retry;
+ }
+ break;
+ }
+ if (r > 0) {
+ if (parent->streamType == V4L2_MPEG_STREAM_TYPE_MPEG2_TS)
+ PutData(buffer, r);
+ else
+ ParseProgramStream(buffer, r);
}
- break;
- }
- if (r > 0) {
- if (parent->streamType == V4L2_MPEG_STREAM_TYPE_MPEG2_TS)
- PutData(buffer, r);
- else
- ParseProgramStream(buffer, r);
}
}
delete [] buffer;