[mythtv] [PATCH] Remove use of deprecated DVB events.
Stuart Auchterlonie
stuarta at squashedfrog.net
Thu Sep 1 17:02:56 UTC 2005
On Thu, Sep 01, 2005 at 04:54:45PM +0100, Stuart Auchterlonie wrote:
>
> Hmmm, changing between channels on the same mplex the backend
> gets stuck in select waiting for an event. This leads to the conclusion
> that we are eating too many events. How or why I'm not sure at the
> moment.
>
Okay I have worked out what is going on.
When we are in TuneTransport there are 3 types of events that
are delivered.
1) Event with freq = old_tuned_freq && status == 0
2) Event with freq = old_tuned_freq && status != 0
3) Event with freq = new_freq && (status & FE_HAS_LOCK)
The trick is that the 3rd type of event is never delivered
if new_freq == old_tuned_freq.
Those of us using DVB-T normally get either 2 or 3 events in total.
One of each of the first 2, and then one of the third if we are
changing frequency (& hence mplex)
Those using DVB-S will get lots of events of type 1 & 2 before
getting any of type 3.
Here's an updated patch which includes suggestion by others.
Stuart
-------------- next part --------------
Index: libs/libmythtv/dvbchannel.cpp
===================================================================
--- libs/libmythtv/dvbchannel.cpp (revision 115)
+++ libs/libmythtv/dvbchannel.cpp (working copy)
@@ -42,6 +42,9 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/poll.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
#include "RingBuffer.h"
#include "recorderbase.h"
@@ -57,9 +60,6 @@
#include "dvbdiseqc.h"
#include "dvbcam.h"
-#define USE_BROKEN_DVB_DRIVER_HACK 1
-#define DVB_GET_EVENT_TIMEOUT 500 /* ms */
-
#if (DVB_API_VERSION_MINOR <= 3 && DVB_API_VERSION_MINOR == 0)
# define FE_ATSC (FE_OFDM+1)
# define FE_CAN_8VSB 0x200000
@@ -68,10 +68,7 @@
# define VSB_16 (QAM_AUTO+2)
#endif
-bool flush_dvb_events(int fd, struct dvb_frontend_event &event);
-bool get_dvb_event(int fd, struct dvb_frontend_event &event,
- bool block = true, int timeout = -1);
-QString dvb_event_to_string(const struct dvb_frontend_event &event);
+QString dvb_status_to_string(const fe_status_t &status);
/** \class DVBChannel
* \brief Provides interface to the tuning hardware when using DVB drivers
@@ -569,10 +566,15 @@
*
* \param channel Info on transport to tune to
* \param all If true frequency tuning is done even if not strictly needed.
+ * \param timeout Time in ms to wait for tuning to succeed
*/
-bool DVBChannel::TuneTransport(const dvb_channel_t& channel, bool all, int)
+bool DVBChannel::TuneTransport(const dvb_channel_t& channel, bool all, int timeout)
{
DVBTuning tuning = channel.tuning;
+ fe_status_t status = (fe_status_t) 0;
+ fd_set fds;
+ struct timeval tv;
+ struct dvb_frontend_event event;
if (fd_frontend < 0)
{
@@ -592,17 +594,34 @@
first_tune = false;
}
- while (true)
+ if (ioctl(fd_frontend, FE_READ_STATUS, &status) == 0 &&
+ !(status & FE_HAS_LOCK))
+ reset = true;
+
+ while(true)
{
if (tune)
{
- struct dvb_frontend_parameters old_params;
- struct dvb_frontend_event event;
- bool chk = flush_dvb_events(fd_frontend, event);
- if (chk)
- old_params = event.parameters;
- else
- chk = (0 == ioctl(fd_frontend, FE_GET_FRONTEND, &old_params));
+ /*
+ * The following events arrive
+ * 1) Event with freq = old_tuned_freq && status == 0
+ * 2) Event with freq = old_tuned_freq && status != 0
+ *
+ * If the freq being tuned to is != old_tuned_freq then we get
+ * 3) Event with freq = new_freq && (status & FE_HAS_LOCK)
+ *
+ * Notes:
+ * - DVB-T
+ * - Receives 2 events if freq is the same
+ * - Receives 3 events if freq changes (ie mplex change)
+ * - DVB-S
+ * - Receives multiple events of type 1 & 2 before #3
+ */
+ while (ioctl(fd_frontend, FE_GET_EVENT, &event) == 0)
+ {
+ if (event.parameters.frequency == tuning.Frequency())
+ break;
+ }
switch(info.type)
{
@@ -625,27 +644,35 @@
break;
#endif
}
- bool frequency_unchanged =
- ((old_params.frequency + 500000) > tuning.params.frequency) &&
- (old_params.frequency < (tuning.params.frequency + 500000));
- if (!chk || !frequency_unchanged)
+ }
+
+ tune = false;
+ reset = false;
+
+ FD_ZERO(&fds);
+ FD_SET(fd_frontend, &fds);
+ tv.tv_sec=0;
+ tv.tv_usec=timeout*1000;
+
+ if (select(fd_frontend+1, &fds, NULL, NULL, &tv) > 0)
+ {
+ if(ioctl(fd_frontend, FE_READ_STATUS, &status) < 0)
{
- CHANNEL("Waiting for event");
- if (get_dvb_event(fd_frontend, event, DVB_GET_EVENT_TIMEOUT))
- CHANNEL(dvb_event_to_string(event));
+ CHANNEL(QString("failed to get status %1")
+ .arg(strerror(errno)));
+ return false;
}
-
- if (havetuned == false)
+ CHANNEL(QString("Tune status=0x%1, %2")
+ .arg(status,2,16)
+ .arg(dvb_status_to_string(status)));
+ if (status & FE_HAS_LOCK)
+ {
+ CHANNEL("DVBChannel::TuneTransport() LOCK!");
return true;
-
- tune = false;
- reset = false;
-
- CHANNEL("Waiting for frontend event after tune.");
+ }
}
-
- return true;
}
+ return true;
}
/** \fn DVBChannel::GetTuningParams(DVBTuning& tuning) const
@@ -853,104 +880,15 @@
ChannelBase::GetCachedPids(chanid, pid_cache);
}
-bool flush_dvb_events(int fd, struct dvb_frontend_event &last_event)
+QString dvb_status_to_string(const fe_status_t &status)
{
- bool have_event = false;
- do
- {
- if (0 == ioctl(fd, FE_GET_EVENT, &last_event))
- {
- VERBOSE(VB_CHANNEL, "DVBEvents: Flushing "
- <<dvb_event_to_string(last_event));
- have_event = true;
- }
- } while (errno != EWOULDBLOCK);
- return have_event;
-}
-
-bool get_dvb_event(int fd, struct dvb_frontend_event &event,
- bool block, int timeout)
-{
- QTime timer;
- timer.start();
-
- while ((timeout <= 0) || (timer.elapsed() < timeout))
- {
- if (0 == ioctl(fd, FE_GET_EVENT, &event))
- return true;
- int ret = errno;
-
- if (EWOULDBLOCK == ret)
- {
- if (!block)
- return false;
- usleep(50); // it would be nicer to use select...
- }
- else if (EOVERFLOW == ret)
- {
- VERBOSE(VB_IMPORTANT, "DVBEvents: Oops, we lost some events...");
- }
- else if (EBADF == ret)
- {
- VERBOSE(VB_IMPORTANT,
- "DVBEvents: fd("<<fd<<") is a bad file descriptor" );
- return false;
- }
- else if (EFAULT == ret)
- {
- VERBOSE(VB_IMPORTANT, "DVBEvents: &event is a bad pointer");
- return false;
- }
- else
- {
- VERBOSE(VB_IMPORTANT, "DVBEvents: unknown error... "<<ret);
- return false; // unknown error...
- }
- }
-
-#if USE_BROKEN_DVB_DRIVER_HACK
- if (timer.elapsed() >= timeout)
- {
- VERBOSE(
- VB_IMPORTANT, "\n"
- "*****************************************************************"
- "\n"
- " WARNING!! MythTV timeout out waiting for a required DVB event!\n"
- " Most likely you are using a broken driver and should upgrade to\n"
- " to the latest DVB driver immediately. This bug in your driver\n"
- " will result in lost recordings and reduced functionality, and\n"
- " indicates a DVB driver unsuitable for production use.\n"
- "*****************************************************************"
- "\n");
-
- fe_status_t tmp_stat;
- if (ioctl(fd, FE_READ_STATUS, &tmp_stat))
- {
- if (tmp_stat & FE_HAS_LOCK)
- {
- VERBOSE(VB_IMPORTANT, "MythTV HACK for BROKEN DVB drivers "
- "appears to have worked. Please upgrade DVB drivers.");
- return true;
- }
- }
- VERBOSE(VB_IMPORTANT, "MythTV HACK for BROKEN DVB drivers "
- "FAILED! Upgrade your DVB drivers.");
- }
-#endif // USE_BROKEN_DVB_DRIVER_HACK
-
- return false;
-}
-
-QString dvb_event_to_string(const struct dvb_frontend_event &event)
-{
QString str("");
- if (FE_HAS_SIGNAL & event.status) str += "Signal,";
- if (FE_HAS_CARRIER & event.status) str += "Carrier,";
- if (FE_HAS_VITERBI & event.status) str += "FEC Stable,";
- if (FE_HAS_SYNC & event.status) str += "Sync,";
- if (FE_HAS_LOCK & event.status) str += "Lock,";
- if (FE_TIMEDOUT & event.status) str += "Timed Out,";
- if (FE_REINIT & event.status) str += "Reinit,";
- return QString("Event Status(%1) frequency(%2 Hz)")
- .arg(str).arg(event.parameters.frequency);
+ if (FE_HAS_SIGNAL & status) str += "Signal,";
+ if (FE_HAS_CARRIER & status) str += "Carrier,";
+ if (FE_HAS_VITERBI & status) str += "FEC Stable,";
+ if (FE_HAS_SYNC & status) str += "Sync,";
+ if (FE_HAS_LOCK & status) str += "Lock,";
+ if (FE_TIMEDOUT & status) str += "Timed Out,";
+ if (FE_REINIT & status) str += "Reinit,";
+ return str;
}
More information about the mythtv-dev
mailing list