client_device-vdr-1.5.1-fixes.patch by Petri Hintukainen (#219)

- VDR 1.5.0 calls some device members in different order and
  streamdev can't currently handle this.
- do not trust in OpenDvr/CloseDvr, instead keep count of active PIDs,
  open data connection when it is needed and close it only when there
  are no active PIDs
  (closing data connection unsubscribes all pids at server end)
- some sanity checks on server side
Modified Files:
	client/device.c client/device.h server/connectionVTP.c
This commit is contained in:
schmirl 2007-04-24 10:43:40 +00:00
parent 0553fce43c
commit d5a38b3213
3 changed files with 87 additions and 21 deletions

View File

@ -1,5 +1,5 @@
/* /*
* $Id: device.c,v 1.9 2007/04/23 11:42:16 schmirl Exp $ * $Id: device.c,v 1.10 2007/04/24 10:43:40 schmirl Exp $
*/ */
#include "client/device.h" #include "client/device.h"
@ -42,6 +42,8 @@ cStreamdevDevice::cStreamdevDevice(void) {
#endif #endif
m_Device = this; m_Device = this;
m_Pids = 0;
m_DvrClosed = true;
if (StreamdevClientSetup.SyncEPG) if (StreamdevClientSetup.SyncEPG)
ClientSocket.SynchronizeEPG(); ClientSocket.SynchronizeEPG();
@ -132,32 +134,85 @@ bool cStreamdevDevice::SetChannelDevice(const cChannel *Channel,
bool cStreamdevDevice::SetPid(cPidHandle *Handle, int Type, bool On) { bool cStreamdevDevice::SetPid(cPidHandle *Handle, int Type, bool On) {
Dprintf("SetPid, Pid=%d, Type=%d, On=%d, used=%d\n", Handle->pid, Type, On, Dprintf("SetPid, Pid=%d, Type=%d, On=%d, used=%d\n", Handle->pid, Type, On,
Handle->used); Handle->used);
if (Handle->pid && (On || !Handle->used)) LOCK_THREAD;
return ClientSocket.SetPid(Handle->pid, On);
return true; if (On && !m_TSBuffer) {
Dprintf("SetPid: no data connection -> OpenDvr()");
OpenDvrInt();
}
bool res = true;
if (Handle->pid && (On || !Handle->used)) {
res = ClientSocket.SetPid(Handle->pid, On);
m_Pids += (!res) ? 0 : On ? 1 : -1;
if (m_Pids < 0)
m_Pids = 0;
if(m_Pids < 1 && m_DvrClosed) {
Dprintf("SetPid: 0 pids left -> CloseDvr()");
CloseDvrInt();
}
}
return res;
}
bool cStreamdevDevice::OpenDvrInt(void) {
Dprintf("OpenDvrInt\n");
LOCK_THREAD;
CloseDvrInt();
if (m_TSBuffer) {
Dprintf("cStreamdevDevice::OpenDvrInt(): DVR connection already open\n");
return true;
}
Dprintf("cStreamdevDevice::OpenDvrInt(): Connecting ...\n");
if (ClientSocket.CreateDataConnection(siLive)) {
m_TSBuffer = new cTSBuffer(*ClientSocket.DataSocket(siLive), MEGABYTE(2), CardIndex() + 1);
return true;
}
esyslog("cStreamdevDevice::OpenDvrInt(): DVR connection FAILED");
return false;
} }
bool cStreamdevDevice::OpenDvr(void) { bool cStreamdevDevice::OpenDvr(void) {
Dprintf("OpenDvr\n"); Dprintf("OpenDvr\n");
CloseDvr(); LOCK_THREAD;
if (ClientSocket.CreateDataConnection(siLive)) {
//m_Assembler = new cStreamdevAssembler(ClientSocket.DataSocket(siLive)); m_DvrClosed = false;
//m_TSBuffer = new cTSBuffer(m_Assembler->ReadPipe(), MEGABYTE(2), CardIndex() + 1); return OpenDvrInt();
m_TSBuffer = new cTSBuffer(*ClientSocket.DataSocket(siLive), MEGABYTE(2), CardIndex() + 1); }
Dprintf("waiting\n");
//m_Assembler->WaitForFill(); void cStreamdevDevice::CloseDvrInt(void) {
Dprintf("resuming\n"); Dprintf("CloseDvrInt\n");
return true; LOCK_THREAD;
if (ClientSocket.CheckConnection()) {
if (!m_DvrClosed) {
Dprintf("cStreamdevDevice::CloseDvrInt(): m_DvrClosed=false -> not closing yet\n");
return;
}
if (m_Pids > 0) {
Dprintf("cStreamdevDevice::CloseDvrInt(): %d active pids -> not closing yet\n", m_Pids);
return;
}
} else {
Dprintf("cStreamdevDevice::CloseDvrInt(): Control connection gone !\n");
} }
return false;
Dprintf("cStreamdevDevice::CloseDvrInt(): Closing DVR connection\n");
DELETENULL(m_TSBuffer);
ClientSocket.CloseDvr();
} }
void cStreamdevDevice::CloseDvr(void) { void cStreamdevDevice::CloseDvr(void) {
Dprintf("CloseDvr\n"); Dprintf("CloseDvr\n");
LOCK_THREAD;
//DELETENULL(m_Assembler); m_DvrClosed = true;
DELETENULL(m_TSBuffer); CloseDvrInt();
ClientSocket.CloseDvr();
} }
bool cStreamdevDevice::GetTSPacket(uchar *&Data) { bool cStreamdevDevice::GetTSPacket(uchar *&Data) {

View File

@ -1,5 +1,5 @@
/* /*
* $Id: device.h,v 1.4 2007/04/23 11:42:16 schmirl Exp $ * $Id: device.h,v 1.5 2007/04/24 10:43:40 schmirl Exp $
*/ */
#ifndef VDR_STREAMDEV_DEVICE_H #ifndef VDR_STREAMDEV_DEVICE_H
@ -25,9 +25,14 @@ private:
#if VDRVERSNUM >= 10307 #if VDRVERSNUM >= 10307
cStreamdevFilters *m_Filters; cStreamdevFilters *m_Filters;
#endif #endif
int m_Pids;
bool m_DvrClosed;
static cStreamdevDevice *m_Device; static cStreamdevDevice *m_Device;
bool OpenDvrInt(void);
void CloseDvrInt(void);
protected: protected:
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView); virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);
virtual bool HasLock(int TimeoutMs) virtual bool HasLock(int TimeoutMs)

View File

@ -1,5 +1,5 @@
/* /*
* $Id: connectionVTP.c,v 1.9 2007/04/16 11:01:02 schmirl Exp $ * $Id: connectionVTP.c,v 1.10 2007/04/24 10:43:40 schmirl Exp $
*/ */
#include "server/connectionVTP.h" #include "server/connectionVTP.h"
@ -632,6 +632,10 @@ bool cConnectionVTP::CmdPORT(char *Opts)
isyslog("Streamdev: Setting data connection to %s:%d", dataip, dataport); isyslog("Streamdev: Setting data connection to %s:%d", dataip, dataport);
if(m_LiveSocket && m_LiveStreamer)
m_LiveStreamer->Stop();
delete m_LiveSocket;
m_LiveSocket = new cTBSocket(SOCK_STREAM); m_LiveSocket = new cTBSocket(SOCK_STREAM);
if (!m_LiveSocket->Connect(dataip, dataport)) { if (!m_LiveSocket->Connect(dataip, dataport)) {
esyslog("ERROR: Streamdev: Couldn't open data connection to %s:%d: %s", esyslog("ERROR: Streamdev: Couldn't open data connection to %s:%d: %s",
@ -640,10 +644,10 @@ bool cConnectionVTP::CmdPORT(char *Opts)
return Respond(551, "Couldn't open data connection"); return Respond(551, "Couldn't open data connection");
} }
if (id == siLive) if (m_LiveStreamer)
m_LiveStreamer->Start(m_LiveSocket); m_LiveStreamer->Start(m_LiveSocket);
return Respond(220, "Port command ok, data connection opened"); return Respond(220, "Port command ok, data connection opened");
} }
bool cConnectionVTP::CmdTUNE(char *Opts) bool cConnectionVTP::CmdTUNE(char *Opts)
@ -664,6 +668,8 @@ bool cConnectionVTP::CmdTUNE(char *Opts)
m_LiveStreamer = new cStreamdevLiveStreamer(1); m_LiveStreamer = new cStreamdevLiveStreamer(1);
m_LiveStreamer->SetChannel(chan, m_NoTSPIDS ? stTS : stTSPIDS); m_LiveStreamer->SetChannel(chan, m_NoTSPIDS ? stTS : stTSPIDS);
m_LiveStreamer->SetDevice(dev); m_LiveStreamer->SetDevice(dev);
if(m_LiveSocket)
m_LiveStreamer->Start(m_LiveSocket);
return Respond(220, "Channel tuned"); return Respond(220, "Channel tuned");
} }