mirror of
https://projects.vdr-developer.org/git/vdr-plugin-streamdev.git
synced 2023-10-10 19:16:51 +02:00
Set device occupied when streamdev switches away LiveTV on the server, to
reduce the risk that the VDR main loop immediately switches back, resulting in a black screen on the client (reported by hummel99)
This commit is contained in:
parent
458a21a62a
commit
1d4a7e06b4
@ -223,4 +223,5 @@ hivdr
|
||||
for suggesting to add the HTTP "Server" header
|
||||
|
||||
hummel99
|
||||
for helping to debug channel switch issues with priority > 0
|
||||
for reporting and helping to debug channel switch issues with priority > 0
|
||||
for reporting a race condition when switching the server's LiveTV device
|
||||
|
5
HISTORY
5
HISTORY
@ -1,7 +1,10 @@
|
||||
VDR Plugin 'streamdev' Revision History
|
||||
---------------------------------------
|
||||
|
||||
- Fixed channel switch issues with priority > 0
|
||||
- Set device occupied when streamdev switches away LiveTV on the server, to
|
||||
reduce the risk that the VDR main loop immediately switches back, resulting
|
||||
in a black screen on the client (reported by hummel99)
|
||||
- Fixed channel switch issues with priority > 0 (reported by hummel99)
|
||||
- Removed noisy debug messages
|
||||
- Fixed HTTP menu destruction
|
||||
- API change of VDR 2.1.2
|
||||
|
@ -14,6 +14,11 @@
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
|
||||
// device occupied timeout to prevent VDR main loop to immediately switch back
|
||||
// when streamdev switched the live TV channel.
|
||||
// Note that there is still a gap between the GetDevice() and SetOccupied()
|
||||
// calls where the VDR main loop could strike
|
||||
#define STREAMDEVTUNETIMEOUT 5
|
||||
|
||||
cServerConnection::cServerConnection(const char *Protocol, int Type):
|
||||
cTBSocket(Type),
|
||||
@ -23,6 +28,7 @@ cServerConnection::cServerConnection(const char *Protocol, int Type):
|
||||
m_ReadBytes(0),
|
||||
m_WriteBytes(0),
|
||||
m_WriteIndex(0),
|
||||
m_OccupiedDev(NULL),
|
||||
m_SwitchTo(NULL)
|
||||
{
|
||||
}
|
||||
@ -204,7 +210,7 @@ bool cServerConnection::UsedByLiveTV(cDevice *device)
|
||||
(device->IsPrimaryDevice() && device->HasDecoder() && !device->Replaying());
|
||||
}
|
||||
|
||||
cDevice *cServerConnection::GetDevice(const cChannel *Channel, int Priority)
|
||||
cDevice *cServerConnection::SwitchDevice(const cChannel *Channel, int Priority)
|
||||
{
|
||||
// turn off the streams of this connection
|
||||
Detach();
|
||||
@ -216,8 +222,22 @@ cDevice *cServerConnection::GetDevice(const cChannel *Channel, int Priority)
|
||||
dsyslog("streamdev: GetDevice failed for channel %d (%s) at priority %d (PrimaryDevice=%d, ActualDevice=%d)", Channel->Number(), Channel->Name(), Priority, cDevice::PrimaryDevice()->CardIndex(), cDevice::ActualDevice()->CardIndex());
|
||||
}
|
||||
else if (!device->IsTunedToTransponder(Channel) && UsedByLiveTV(device)) {
|
||||
// switched away live TV
|
||||
m_SwitchTo = Channel;
|
||||
// make sure VDR main loop doesn't switch back
|
||||
device->SetOccupied(STREAMDEVTUNETIMEOUT);
|
||||
if (device->SwitchChannel(Channel, false)) {
|
||||
// switched away live TV
|
||||
m_OccupiedDev = device;
|
||||
m_SwitchTo = Channel;
|
||||
}
|
||||
else {
|
||||
dsyslog("streamdev: SwitchChannel (live) failed for channel %d (%s) at priority %d (PrimaryDevice=%d, ActualDevice=%d, device=%d)", Channel->Number(), Channel->Name(), Priority, cDevice::PrimaryDevice()->CardIndex(), cDevice::ActualDevice()->CardIndex(), device->CardIndex());
|
||||
device->SetOccupied(0);
|
||||
device = NULL;
|
||||
}
|
||||
}
|
||||
else if (!device->SwitchChannel(Channel, false)) {
|
||||
dsyslog("streamdev: SwitchChannel failed for channel %d (%s) at priority %d (PrimaryDevice=%d, ActualDevice=%d, device=%d)", Channel->Number(), Channel->Name(), Priority, cDevice::PrimaryDevice()->CardIndex(), cDevice::ActualDevice()->CardIndex(), device->CardIndex());
|
||||
device = NULL;
|
||||
}
|
||||
return device;
|
||||
}
|
||||
@ -240,6 +260,7 @@ void cServerConnection::MainThreadHook()
|
||||
Channels.SwitchTo(m_SwitchTo->Number());
|
||||
Skins.Message(mtInfo, tr("Streaming active"));
|
||||
}
|
||||
m_OccupiedDev->SetOccupied(0);
|
||||
m_SwitchTo = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,8 @@ private:
|
||||
uint m_WriteBytes;
|
||||
uint m_WriteIndex;
|
||||
|
||||
/* Set to occupied device when live TV was interrupted */
|
||||
cDevice *m_OccupiedDev;
|
||||
/* Set to this connection's current channel when live TV was interrupted */
|
||||
const cChannel *m_SwitchTo;
|
||||
|
||||
@ -106,10 +108,8 @@ public:
|
||||
channel. This call has no side effects. */
|
||||
static cDevice *CheckDevice(const cChannel *Channel, int Priority, bool LiveView, const cDevice *AvoidDevice = NULL);
|
||||
|
||||
/* Will retrieve an unused device for transmitting data. Receivers have
|
||||
already been attached from the device if necessary. Use the returned
|
||||
cDevice in a following call to StartTransfer */
|
||||
cDevice *GetDevice(const cChannel *Channel, int Priority);
|
||||
/* Find a suitable device and tune it to the requested channel. */
|
||||
cDevice *SwitchDevice(const cChannel *Channel, int Priority);
|
||||
|
||||
/* Test if a call to GetDevice would return a usable device. */
|
||||
bool ProvidesChannel(const cChannel *Channel, int Priority);
|
||||
|
@ -177,9 +177,8 @@ bool cConnectionHTTP::ProcessRequest(void)
|
||||
else if (m_Channel != NULL) {
|
||||
cDevice *device = NULL;
|
||||
if (ProvidesChannel(m_Channel, StreamdevServerSetup.HTTPPriority))
|
||||
device = GetDevice(m_Channel, StreamdevServerSetup.HTTPPriority);
|
||||
device = SwitchDevice(m_Channel, StreamdevServerSetup.HTTPPriority);
|
||||
if (device != NULL) {
|
||||
device->SwitchChannel(m_Channel, false);
|
||||
cStreamdevLiveStreamer* liveStreamer = new cStreamdevLiveStreamer(StreamdevServerSetup.HTTPPriority, this);
|
||||
m_Streamer = liveStreamer;
|
||||
if (liveStreamer->SetChannel(m_Channel, m_StreamType, m_Apid[0] ? m_Apid : NULL, m_Dpid[0] ? m_Dpid : NULL)) {
|
||||
|
@ -44,9 +44,8 @@ void cConnectionIGMP::Welcome()
|
||||
{
|
||||
cDevice *device = NULL;
|
||||
if (ProvidesChannel(m_Channel, StreamdevServerSetup.IGMPPriority))
|
||||
device = GetDevice(m_Channel, StreamdevServerSetup.IGMPPriority);
|
||||
device = SwitchDevice(m_Channel, StreamdevServerSetup.IGMPPriority);
|
||||
if (device != NULL) {
|
||||
device->SwitchChannel(m_Channel, false);
|
||||
m_LiveStreamer = new cStreamdevLiveStreamer(StreamdevServerSetup.IGMPPriority, this);
|
||||
if (m_LiveStreamer->SetChannel(m_Channel, m_StreamType)) {
|
||||
m_LiveStreamer->SetDevice(device);
|
||||
@ -61,7 +60,7 @@ void cConnectionIGMP::Welcome()
|
||||
}
|
||||
}
|
||||
else
|
||||
esyslog("streamdev-server IGMP: GetDevice failed");
|
||||
esyslog("streamdev-server IGMP: SwitchDevice failed");
|
||||
}
|
||||
|
||||
bool cConnectionIGMP::Close()
|
||||
|
@ -1118,11 +1118,8 @@ bool cConnectionVTP::CmdTUNE(char *Opts)
|
||||
if (!ProvidesChannel(chan, prio))
|
||||
return Respond(560, "Channel not available (ProvidesChannel)");
|
||||
}
|
||||
if ((dev = GetDevice(chan, prio)) == NULL)
|
||||
return Respond(560, "Channel not available (GetDevice)");
|
||||
|
||||
if (!dev->SwitchChannel(chan, false))
|
||||
return Respond(560, "Channel not available (SwitchChannel)");
|
||||
if ((dev = SwitchDevice(chan, prio)) == NULL)
|
||||
return Respond(560, "Channel not available (SwitchDevice)");
|
||||
|
||||
delete m_LiveStreamer;
|
||||
m_LiveStreamer = new cStreamdevLiveStreamer(prio, this);
|
||||
|
Loading…
Reference in New Issue
Block a user