Serialize channel switching to prevent device allocation failures.

This commit is contained in:
Rolf Ahrenberg 2017-11-13 22:12:10 +02:00
parent 364b4fbec7
commit f3fe1e9a13
4 changed files with 22 additions and 4 deletions

View File

@ -15,6 +15,8 @@
static cSatipDevice * SatipDevicesS[SATIP_MAX_DEVICES] = { NULL };
cMutex cSatipDevice::mutexS = cMutex();
cSatipDevice::cSatipDevice(unsigned int indexP)
: deviceIndexM(indexP),
isPacketDeliveredM(false),
@ -22,7 +24,7 @@ cSatipDevice::cSatipDevice(unsigned int indexP)
deviceNameM(*cString::sprintf("%s %d", *DeviceType(), deviceIndexM)),
channelM(),
createdM(0),
mutexM()
tunedM()
{
unsigned int bufsize = (unsigned int)SATIP_BUFFER_SIZE;
bufsize -= (bufsize % TS_SIZE);
@ -42,6 +44,8 @@ cSatipDevice::cSatipDevice(unsigned int indexP)
cSatipDevice::~cSatipDevice()
{
debug1("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
// Release immediately any pending conditional wait
tunedM.Broadcast();
// Stop section handler
StopSectionHandler();
DELETE_POINTER(pSectionFilterHandlerM);
@ -339,6 +343,7 @@ bool cSatipDevice::MaySwitchTransponder(const cChannel *channelP) const
bool cSatipDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP)
{
cMutexLock MutexLock(&mutexS); // Global lock to prevent any simultaneous zapping
debug9("%s (%d, %d) [device %u]", __PRETTY_FUNCTION__, channelP ? channelP->Number() : -1, liveViewP, deviceIndexM);
if (channelP) {
cDvbTransponderParameters dtp(channelP->Parameters());
@ -356,6 +361,8 @@ bool cSatipDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP)
if (pTunerM && pTunerM->SetSource(server, channelP->Transponder(), *params, deviceIndexM)) {
channelM = *channelP;
deviceNameM = cString::sprintf("%s %d %s", *DeviceType(), deviceIndexM, *cSatipDiscover::GetInstance()->GetServerString(server));
// Wait for actual channel tuning to prevent simultaneous frontend allocation failures
tunedM.TimedWait(mutexS, eTuningTimeoutMs);
return true;
}
}
@ -367,6 +374,13 @@ bool cSatipDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP)
return false;
}
void cSatipDevice::SetChannelTuned(void)
{
debug9("%s () [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
// Release immediately any pending conditional wait
tunedM.Broadcast();
}
bool cSatipDevice::SetPid(cPidHandle *handleP, int typeP, bool onP)
{
debug12("%s (%d, %d, %d) [device %u]", __PRETTY_FUNCTION__, handleP ? handleP->pid : -1, typeP, onP, deviceIndexM);

View File

@ -18,7 +18,7 @@
class cSatipDevice : public cDevice, public cSatipPidStatistics, public cSatipBufferStatistics, public cSatipDeviceIf {
// static ones
public:
static unsigned int deviceCount;
static cMutex mutexS;
static bool Initialize(unsigned int DeviceCount);
static void Shutdown(void);
static unsigned int Count(void);
@ -28,7 +28,8 @@ public:
// private parts
private:
enum {
eReadyTimeoutMs = 2000 // in milliseconds
eReadyTimeoutMs = 2000, // in milliseconds
eTuningTimeoutMs = 1000 // in milliseconds
};
unsigned int deviceIndexM;
bool isPacketDeliveredM;
@ -39,7 +40,7 @@ private:
cSatipTuner *pTunerM;
cSatipSectionFilterHandler *pSectionFilterHandlerM;
cTimeMs createdM;
cMutex mutexM;
cCondVar tunedM;
// constructor & destructor
public:
@ -107,6 +108,7 @@ public:
// for internal device interface
public:
virtual void WriteData(u_char *bufferP, int lengthP);
virtual void SetChannelTuned(void);
virtual int GetId(void);
virtual int GetPmtPid(void);
virtual int GetCISlot(void);

View File

@ -13,6 +13,7 @@ public:
cSatipDeviceIf() {}
virtual ~cSatipDeviceIf() {}
virtual void WriteData(u_char *bufferP, int lengthP) = 0;
virtual void SetChannelTuned(void) = 0;
virtual int GetId(void) = 0;
virtual int GetPmtPid(void) = 0;
virtual int GetCISlot(void) = 0;

View File

@ -126,6 +126,7 @@ void cSatipTuner::Action(void)
break;
case tsTuned:
debug4("%s: tsTuned [device %d]", __PRETTY_FUNCTION__, deviceIdM);
deviceM->SetChannelTuned();
reConnectM.Set(eConnectTimeoutMs);
idleCheck.Set(eIdleCheckTimeoutMs);
lastIdleStatus = false;