[mythtv] dvb zero length record
Tom Hughes
tom at compton.nu
Sun May 22 23:08:21 UTC 2005
In message <7EF2F2C5-3D31-4F20-8D4E-F8F00A1DFCAD at cse.unsw.edu.au>
William Uther <willu.mailingLists at cse.unsw.edu.au> wrote:
> On Fri, 20 May 2005 09:01:32 +0100, Tom Hughes <tom at compton.nu> wrote:
>
> > None of those sounds like my case which was reported in the other
> > thread that somebody referred you to. Those look like this:
>
> [snip]
>
> > 2005-05-09 13:38:10.289 DVB#0 Recorder: Card opened successfully
> > (using PS mode).
>
> [snip]
>
> > I believe I now understand what is causing those ones, and I've been
> > running with a fix since last Sunday and haven't lost anything yet. I
> > was only loosing one or two a week though so I want to run it for
> > another week or two before pronouncing it fixed for sure.
>
> Do you know if your fix is PS/TS specific?
It shouldn't be specific to either mode - the problem is in
tuning the card to the right channel. How the data is read once
tuning is complete is irrelevant.
> I'd be happy to help test that for you (in TS mode) if you want to
> post a patch...
The basic problem is that sometime betwen 2.6.8 and 2.6.11 the
way in which tuning is handled for DVB cards changed.
It used to be that when the FE_SET_FRONTEND ioctl was called the
tuning was done by the frontend driver for the card you were using
which (at least for the TwinHan DST cards I use) changed channel
synchronously and didn't return from the ioctl until it had either
retuned or had failed to tune.
So when Myth then did an FE_READ_STATUS to check for the FE_HAS_LOCK
flag a lock would mean that the card had successfully tuned to the
new channel.
What happens now is that the generic part of the DVB code does the
tuning using a kernel thread which will potentially supply several
different sets of tuning parameters to the frontend driver if some
of the fields were left at auto in the FE_SET_FRONTEND call.
What this means is that tuning now happens in the background, but
because FE_READ_STATUS interrogates the frontend directly it can
see a lock for the old channel if the kernel thread hasn't started
tuning yet. Myth may then read a PMT from that multiplex and fail
to find the service it is looking for.
The fix I am using is to use FE_GET_EVENT instead which gets events
from the background kernel thread so only reports a lock when tuning
is really complete. So far it seems to be working.
If FE_GET_EVENT fails with EOPNOTSUPP due to running on an older
kernel then my patch falls back to FE_READ_STATUS instead.
The patch is attached if you want to try it.
Tom
--
Tom Hughes (tom at compton.nu)
http://www.compton.nu/
-------------- next part --------------
Index: libs/libmythtv/dvbchannel.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/dvbchannel.cpp,v
retrieving revision 1.34
diff -u -u -r1.34 dvbchannel.cpp
--- libs/libmythtv/dvbchannel.cpp 15 May 2005 16:39:29 -0000 1.34
+++ libs/libmythtv/dvbchannel.cpp 22 May 2005 23:01:33 -0000
@@ -922,21 +922,36 @@
CHANNEL("Waiting for frontend event after tune.");
}
- fe_status_t stat;
+ struct dvb_frontend_event event;
int timeout = 0;
QString status = "Status: ";
do {
- if (ioctl(fd_frontend, FE_READ_STATUS, &stat) < 0)
- perror("FE_READ_STATUS failed");
+ if (ioctl(fd_frontend, FE_GET_EVENT, &event) < 0)
+ {
+ if (errno == EOPNOTSUPP)
+ {
+ if (ioctl(fd_frontend, FE_READ_STATUS, &event.status) < 0)
+ {
+ perror("FE_READ_STATUS failed");
+ event.status = (fe_status_t)0;
+ }
+ }
+ else
+ {
+ if (errno != EWOULDBLOCK && errno != EOVERFLOW)
+ perror("FE_GET_EVENT failed");
+ event.status = (fe_status_t)0;
+ }
+ }
if (fd_frontend < 0)
return false;
else if (!(timeout % (1000000/TUNER_INTERVAL)))
{
- uint16_t ss;
- uint16_t snr;
- uint32_t ber;
- uint32_t ub;
+ uint16_t ss = 0;
+ uint16_t snr = 0;
+ uint32_t ber = 0;
+ uint32_t ub = 0;
ioctl(fd_frontend, FE_READ_SIGNAL_STRENGTH, &ss);
ioctl(fd_frontend, FE_READ_SNR, &snr);
ioctl(fd_frontend, FE_READ_BER, &ber);
@@ -945,7 +960,7 @@
GENERAL(msg);
}
- if (stat & FE_HAS_LOCK)
+ if (event.status & FE_HAS_LOCK)
{
status += "LOCK.";
GENERAL(status);
More information about the mythtv-dev
mailing list