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
|
for suggesting to add the HTTP "Server" header
|
||||||
|
|
||||||
hummel99
|
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
|
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
|
- Removed noisy debug messages
|
||||||
- Fixed HTTP menu destruction
|
- Fixed HTTP menu destruction
|
||||||
- API change of VDR 2.1.2
|
- API change of VDR 2.1.2
|
||||||
|
@ -14,6 +14,11 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <errno.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):
|
cServerConnection::cServerConnection(const char *Protocol, int Type):
|
||||||
cTBSocket(Type),
|
cTBSocket(Type),
|
||||||
@ -23,6 +28,7 @@ cServerConnection::cServerConnection(const char *Protocol, int Type):
|
|||||||
m_ReadBytes(0),
|
m_ReadBytes(0),
|
||||||
m_WriteBytes(0),
|
m_WriteBytes(0),
|
||||||
m_WriteIndex(0),
|
m_WriteIndex(0),
|
||||||
|
m_OccupiedDev(NULL),
|
||||||
m_SwitchTo(NULL)
|
m_SwitchTo(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -204,7 +210,7 @@ bool cServerConnection::UsedByLiveTV(cDevice *device)
|
|||||||
(device->IsPrimaryDevice() && device->HasDecoder() && !device->Replaying());
|
(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
|
// turn off the streams of this connection
|
||||||
Detach();
|
Detach();
|
||||||
@ -216,9 +222,23 @@ 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());
|
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)) {
|
else if (!device->IsTunedToTransponder(Channel) && UsedByLiveTV(device)) {
|
||||||
|
// make sure VDR main loop doesn't switch back
|
||||||
|
device->SetOccupied(STREAMDEVTUNETIMEOUT);
|
||||||
|
if (device->SwitchChannel(Channel, false)) {
|
||||||
// switched away live TV
|
// switched away live TV
|
||||||
|
m_OccupiedDev = device;
|
||||||
m_SwitchTo = Channel;
|
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;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,6 +260,7 @@ void cServerConnection::MainThreadHook()
|
|||||||
Channels.SwitchTo(m_SwitchTo->Number());
|
Channels.SwitchTo(m_SwitchTo->Number());
|
||||||
Skins.Message(mtInfo, tr("Streaming active"));
|
Skins.Message(mtInfo, tr("Streaming active"));
|
||||||
}
|
}
|
||||||
|
m_OccupiedDev->SetOccupied(0);
|
||||||
m_SwitchTo = NULL;
|
m_SwitchTo = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,8 @@ private:
|
|||||||
uint m_WriteBytes;
|
uint m_WriteBytes;
|
||||||
uint m_WriteIndex;
|
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 */
|
/* Set to this connection's current channel when live TV was interrupted */
|
||||||
const cChannel *m_SwitchTo;
|
const cChannel *m_SwitchTo;
|
||||||
|
|
||||||
@ -106,10 +108,8 @@ public:
|
|||||||
channel. This call has no side effects. */
|
channel. This call has no side effects. */
|
||||||
static cDevice *CheckDevice(const cChannel *Channel, int Priority, bool LiveView, const cDevice *AvoidDevice = NULL);
|
static cDevice *CheckDevice(const cChannel *Channel, int Priority, bool LiveView, const cDevice *AvoidDevice = NULL);
|
||||||
|
|
||||||
/* Will retrieve an unused device for transmitting data. Receivers have
|
/* Find a suitable device and tune it to the requested channel. */
|
||||||
already been attached from the device if necessary. Use the returned
|
cDevice *SwitchDevice(const cChannel *Channel, int Priority);
|
||||||
cDevice in a following call to StartTransfer */
|
|
||||||
cDevice *GetDevice(const cChannel *Channel, int Priority);
|
|
||||||
|
|
||||||
/* Test if a call to GetDevice would return a usable device. */
|
/* Test if a call to GetDevice would return a usable device. */
|
||||||
bool ProvidesChannel(const cChannel *Channel, int Priority);
|
bool ProvidesChannel(const cChannel *Channel, int Priority);
|
||||||
|
@ -177,9 +177,8 @@ bool cConnectionHTTP::ProcessRequest(void)
|
|||||||
else if (m_Channel != NULL) {
|
else if (m_Channel != NULL) {
|
||||||
cDevice *device = NULL;
|
cDevice *device = NULL;
|
||||||
if (ProvidesChannel(m_Channel, StreamdevServerSetup.HTTPPriority))
|
if (ProvidesChannel(m_Channel, StreamdevServerSetup.HTTPPriority))
|
||||||
device = GetDevice(m_Channel, StreamdevServerSetup.HTTPPriority);
|
device = SwitchDevice(m_Channel, StreamdevServerSetup.HTTPPriority);
|
||||||
if (device != NULL) {
|
if (device != NULL) {
|
||||||
device->SwitchChannel(m_Channel, false);
|
|
||||||
cStreamdevLiveStreamer* liveStreamer = new cStreamdevLiveStreamer(StreamdevServerSetup.HTTPPriority, this);
|
cStreamdevLiveStreamer* liveStreamer = new cStreamdevLiveStreamer(StreamdevServerSetup.HTTPPriority, this);
|
||||||
m_Streamer = liveStreamer;
|
m_Streamer = liveStreamer;
|
||||||
if (liveStreamer->SetChannel(m_Channel, m_StreamType, m_Apid[0] ? m_Apid : NULL, m_Dpid[0] ? m_Dpid : NULL)) {
|
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;
|
cDevice *device = NULL;
|
||||||
if (ProvidesChannel(m_Channel, StreamdevServerSetup.IGMPPriority))
|
if (ProvidesChannel(m_Channel, StreamdevServerSetup.IGMPPriority))
|
||||||
device = GetDevice(m_Channel, StreamdevServerSetup.IGMPPriority);
|
device = SwitchDevice(m_Channel, StreamdevServerSetup.IGMPPriority);
|
||||||
if (device != NULL) {
|
if (device != NULL) {
|
||||||
device->SwitchChannel(m_Channel, false);
|
|
||||||
m_LiveStreamer = new cStreamdevLiveStreamer(StreamdevServerSetup.IGMPPriority, this);
|
m_LiveStreamer = new cStreamdevLiveStreamer(StreamdevServerSetup.IGMPPriority, this);
|
||||||
if (m_LiveStreamer->SetChannel(m_Channel, m_StreamType)) {
|
if (m_LiveStreamer->SetChannel(m_Channel, m_StreamType)) {
|
||||||
m_LiveStreamer->SetDevice(device);
|
m_LiveStreamer->SetDevice(device);
|
||||||
@ -61,7 +60,7 @@ void cConnectionIGMP::Welcome()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
esyslog("streamdev-server IGMP: GetDevice failed");
|
esyslog("streamdev-server IGMP: SwitchDevice failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cConnectionIGMP::Close()
|
bool cConnectionIGMP::Close()
|
||||||
|
@ -1118,11 +1118,8 @@ bool cConnectionVTP::CmdTUNE(char *Opts)
|
|||||||
if (!ProvidesChannel(chan, prio))
|
if (!ProvidesChannel(chan, prio))
|
||||||
return Respond(560, "Channel not available (ProvidesChannel)");
|
return Respond(560, "Channel not available (ProvidesChannel)");
|
||||||
}
|
}
|
||||||
if ((dev = GetDevice(chan, prio)) == NULL)
|
if ((dev = SwitchDevice(chan, prio)) == NULL)
|
||||||
return Respond(560, "Channel not available (GetDevice)");
|
return Respond(560, "Channel not available (SwitchDevice)");
|
||||||
|
|
||||||
if (!dev->SwitchChannel(chan, false))
|
|
||||||
return Respond(560, "Channel not available (SwitchChannel)");
|
|
||||||
|
|
||||||
delete m_LiveStreamer;
|
delete m_LiveStreamer;
|
||||||
m_LiveStreamer = new cStreamdevLiveStreamer(prio, this);
|
m_LiveStreamer = new cStreamdevLiveStreamer(prio, this);
|
||||||
|
Loading…
Reference in New Issue
Block a user