[mythtv] DVB channel flipping hang
Mark Weaver
mark-clist at npsl.co.uk
Thu Aug 25 00:34:12 UTC 2005
> Is it a reasonable solution just to do the ioctl and enter a select()
> loop at that point, with a timeout? I can see that the fd is used
> elsewhere (via GetFd()) but only FE_SET_FRONTEND appears to use
> FE_GET_EVENT according to the API docs, so it would seem ok. I have no
> idea what the actual code flow is so I could be missing something.
>
> I'll probably give it a go and see what happens, it doesn't seem like
> too much work!
>
This does seem to help, I've done 10 minutes of channel flipping with no
issues. The attached patch is what I used, would be good if someone
else could give it a whirl.
Thanks,
Mark
-------------- next part --------------
Index: dvbchannel.cpp
===================================================================
--- dvbchannel.cpp (revision 7121)
+++ dvbchannel.cpp (working copy)
@@ -666,11 +666,8 @@
prev_tuning.params.u.qpsk.symbol_rate != tuning.params.u.qpsk.symbol_rate ||
prev_tuning.params.u.qpsk.fec_inner != tuning.params.u.qpsk.fec_inner)
{
- if (ioctl(fd_frontend, FE_SET_FRONTEND, &tuning.params) < 0)
- {
- ERRNO("Setting Frontend failed.");
- return false;
- }
+ if (!SetFrontEnd(tuning))
+ return false;
prev_tuning.params.frequency = tuning.params.frequency;
prev_tuning.params.inversion = tuning.params.inversion;
@@ -691,11 +688,9 @@
prev_tuning.params.frequency != tuning.params.frequency ||
prev_tuning.params.u.vsb.modulation != tuning.params.u.vsb.modulation)
{
- if (ioctl(fd_frontend, FE_SET_FRONTEND, &tuning.params) < 0)
- {
- ERRNO("Setting Frontend failed.");
- return false;
- }
+ if (!SetFrontEnd(tuning))
+ return false;
+
prev_tuning.params.frequency = tuning.params.frequency;
prev_tuning.params.u.vsb.modulation = tuning.params.u.vsb.modulation;
havetuned = true;
@@ -717,11 +712,8 @@
prev_tuning.params.u.qam.fec_inner != tuning.params.u.qam.fec_inner ||
prev_tuning.params.u.qam.modulation != tuning.params.u.qam.modulation)
{
- if (ioctl(fd_frontend, FE_SET_FRONTEND, &tuning.params) < 0)
- {
- ERRNO("Setting Frontend failed.");
- return false;
- }
+ if (!SetFrontEnd(tuning))
+ return false;
prev_tuning.params.frequency = tuning.params.frequency;
prev_tuning.params.inversion = tuning.params.inversion;
@@ -747,11 +739,8 @@
prev_tuning.params.u.ofdm.guard_interval != tuning.params.u.ofdm.guard_interval ||
prev_tuning.params.u.ofdm.hierarchy_information != tuning.params.u.ofdm.hierarchy_information)
{
- if (ioctl(fd_frontend, FE_SET_FRONTEND, &tuning.params) < 0)
- {
- ERRNO("Setting Frontend failed.");
- return false;
- }
+ if (!SetFrontEnd(tuning))
+ return false;
prev_tuning.params.frequency = tuning.params.frequency;
prev_tuning.params.inversion = tuning.params.inversion;
@@ -811,6 +800,74 @@
return query.value(0).toInt();
}
+/** \fn DVBChannel::SetFrontEnd(DVBTuning &tuning)
+ * \brief Set the frontend tuning parameters
+ */
+bool DVBChannel::SetFrontEnd(DVBTuning &tuning)
+{
+ if (ioctl(fd_frontend, FE_SET_FRONTEND, &tuning.params) < 0)
+ {
+ ERRNO("Setting Frontend failed.");
+ return false;
+ }
+
+ struct pollfd pfd[1];
+ pfd[0].fd = fd_frontend;
+ pfd[0].events = POLLPRI | POLLIN;
+
+ struct dvb_frontend_event event;
+ event.status = (fe_status_t)0;
+
+ int timeouts = 0;
+ while ( timeouts < 10 &&
+ (event.status & FE_TIMEDOUT) == 0 &&
+ (event.status & FE_HAS_LOCK) == 0 )
+ {
+ int status = poll(pfd, 1, 1000);
+ if (status < 0)
+ {
+ ERRNO("poll failed.");
+ return false;
+ }
+ else if (status == 0)
+ {
+ ++timeouts;
+ }
+ else
+ {
+ status = ioctl(fd_frontend, FE_GET_EVENT, &event);
+ if (status < 0)
+ {
+ if (errno == EOVERFLOW)
+ {
+ CHANNEL("Overflow polling frontend events, continuing");
+ }
+ else
+ {
+ ERRNO("FE_GET_EVENT failed");
+ return false;
+ }
+ }
+ }
+ }
+
+ if (event.status & FE_HAS_LOCK)
+ {
+ CHANNEL("FE_HAS_LOCK after setting Frontend");
+ return true;
+ }
+
+ if (event.status & FE_TIMEDOUT)
+ {
+ CHANNEL("FE_TIMEDOUT setting frontend parameters");
+ }
+ else
+ {
+ CHANNEL("FE_SET_FRONTEND did not respond after 10s");
+ }
+ return false;
+}
+
void DVBChannel::SaveCachedPids(const pid_cache_t &pid_cache) const
{
int chanid = GetChanID();
Index: dvbchannel.h
===================================================================
--- dvbchannel.h (revision 7121)
+++ dvbchannel.h (working copy)
@@ -85,6 +85,7 @@
int GetChanID(void) const;
bool GetTransportOptions(int mplexid);
bool GetChannelOptions(const QString &channum);
+ bool SetFrontEnd(DVBTuning &tuning);
void CheckOptions();
bool CheckModulation(fe_modulation_t modulation) const;
More information about the mythtv-dev
mailing list