Serialize channel switching to prevent device allocation failures.

This commit is contained in:
Rolf Ahrenberg 2017-11-13 22:12:10 +02:00
parent dbe67a2242
commit 72c3247dc2
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),
bytesDeliveredM(0),
@ -23,7 +25,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);
@ -43,6 +45,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);
@ -345,6 +349,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());
@ -362,6 +367,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;
}
}
@ -373,6 +380,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;
int bytesDeliveredM;
@ -40,7 +41,7 @@ private:
cSatipTuner *pTunerM;
cSatipSectionFilterHandler *pSectionFilterHandlerM;
cTimeMs createdM;
cMutex mutexM;
cCondVar tunedM;
// constructor & destructor
public:
@ -109,6 +110,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

@ -127,6 +127,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;