Klaus Schmidinger wrote:
I really don't see why tuning to a particular channel should speed up the initial setup of the CAM communication.
I only know that EPG scan did help, and did help every time...
But, in the meantime I've built a new vdr/file -server, and guess what... yep, the delay is gone. I have no idea what was the real fix as I've changed almost everything (except dvb-hardware):
P2-350 -> Celeron-2.5G vdr-1.3.23 -> vdr-1.3.29 linux-2.4 -> linux-2.6 dvb-20041226 -> dvb in kernel etc...
But I guess there are still some people who have the same problem. Why not add an option to VDR to allow EPG scan to start right away?
Teemu
Rantanen Teemu wrote:
Klaus Schmidinger wrote:
I really don't see why tuning to a particular channel should speed up the initial setup of the CAM communication.
I only know that EPG scan did help, and did help every time...
But, in the meantime I've built a new vdr/file -server, and guess what... yep, the delay is gone. I have no idea what was the real fix as I've changed almost everything (except dvb-hardware):
P2-350 -> Celeron-2.5G vdr-1.3.23 -> vdr-1.3.29 linux-2.4 -> linux-2.6 dvb-20041226 -> dvb in kernel etc...
But I guess there are still some people who have the same problem. Why not add an option to VDR to allow EPG scan to start right away?
I strongly believe that the EPG scan thing was just a symptom, not the cause.
The attached patch makes VDR wait until all devices that have CAMs are ready to decrypt. With this I can start VDR right away with an encrypted channel, and it doesn't say "channel not available" any more.
Please test whether this works for you, too.
Klaus
--- ./ci.c 2005/08/20 12:16:23 1.25 +++ ./ci.c 2005/08/20 15:27:35 @@ -1354,6 +1354,8 @@ hasUserIO = false; for (int i = 0; i < MAX_CI_SESSION; i++) sessions[i] = NULL; + for (int i = 0; i < MAX_CI_SLOT; i++) + moduleReady[i] = false; tpl = new cCiTransportLayer(Fd, numSlots); tc = NULL; } @@ -1506,6 +1508,19 @@ return result; }
+bool cCiHandler::Ready(void) +{ + cMutexLock MutexLock(&mutex); + for (int Slot = 0; Slot < numSlots; Slot++) { + if (moduleReady[Slot]) { + cCiConditionalAccessSupport *cas = (cCiConditionalAccessSupport *)GetSessionByResourceId(RI_CONDITIONAL_ACCESS_SUPPORT, Slot); + if (!cas || !*cas->GetCaSystemIds()) + return false; + } + } + return true; +} + bool cCiHandler::Process(void) { bool result = true; @@ -1543,6 +1558,7 @@ } else if (tpl->ModuleReady(Slot)) { dbgprotocol("Module ready in slot %d\n", Slot); + moduleReady[Slot] = true; tpl->NewConnection(Slot); } } --- ./ci.h 2004/02/08 14:36:23 1.13 +++ ./ci.h 2005/08/20 14:56:11 @@ -77,6 +77,7 @@ };
#define MAX_CI_SESSION 16 //XXX +#define MAX_CI_SLOT 16
class cCiSession; class cCiTransportLayer; @@ -89,6 +90,7 @@ int numSlots; bool newCaSupport; bool hasUserIO; + bool moduleReady[MAX_CI_SLOT]; cCiSession *sessions[MAX_CI_SESSION]; cCiTransportLayer *tpl; cCiTransportConnection *tc; @@ -105,6 +107,7 @@ ~cCiHandler(); static cCiHandler *CreateCiHandler(const char *FileName); int NumSlots(void) { return numSlots; } + bool Ready(void); bool Process(void); bool HasUserIO(void) { return hasUserIO; } bool EnterMenu(int Slot); --- ./device.c 2005/08/14 10:52:08 1.105 +++ ./device.c 2005/08/20 15:31:53 @@ -195,6 +195,19 @@ delete pesAssembler; }
+void cDevice::WaitForAllDevicesReady(int Timeout) +{ + for (time_t t0 = time(NULL); time(NULL) - t0 < Timeout; ) { + bool ready = true; + for (int i = 0; i < numDevices; i++) { + if (device[i] && !device[i]->Ready()) + ready = false; + } + if (ready) + break; + } +} + void cDevice::SetUseDevice(int n) { if (n < MAXDEVICES) @@ -1103,6 +1116,11 @@ XXX*/ }
+bool cDevice::Ready(void) +{ + return true; +} + int cDevice::ProvidesCa(const cChannel *Channel) const { int Ca = Channel->Ca(); --- ./device.h 2005/08/13 11:44:13 1.61 +++ ./device.h 2005/08/20 15:38:49 @@ -102,6 +102,9 @@ public: static int NumDevices(void) { return numDevices; } ///< Returns the total number of devices. + static void WaitForAllDevicesReady(int Timeout = 0); + ///< Waits until all devices have become ready, or the given Timeout + ///< (seconds) has expired. static void SetUseDevice(int n); ///< Sets the 'useDevice' flag of the given device. ///< If this function is not called before initializing, all devices @@ -136,6 +139,9 @@ protected: cDevice(void); virtual ~cDevice(); + virtual bool Ready(void); + ///< Returns true if this device is ready. Devices with conditional + ///< access hardware may need some time until they are up and running. static int NextCardIndex(int n = 0); ///< Calculates the next card index. ///< Each device in a given machine must have a unique card index, which --- ./dvbdevice.c 2005/08/15 14:05:23 1.134 +++ ./dvbdevice.c 2005/08/20 15:22:36 @@ -478,6 +478,15 @@ return fd_video >= 0 && fd_audio >= 0; }
+bool cDvbDevice::Ready(void) +{ + if (ciHandler) { + ciHandler->Process(); + return ciHandler->Ready(); + } + return true; +} + int cDvbDevice::ProvidesCa(const cChannel *Channel) const { if (Channel->Ca() >= 0x0100 && ciHandler) { --- ./dvbdevice.h 2005/02/20 11:17:07 1.34 +++ ./dvbdevice.h 2005/08/20 15:20:15 @@ -42,6 +42,7 @@ public: cDvbDevice(int n); virtual ~cDvbDevice(); + virtual bool Ready(void); virtual int ProvidesCa(const cChannel *Channel) const; virtual bool HasDecoder(void) const;
--- ./vdr.c 2005/08/20 11:24:42 1.210 +++ ./vdr.c 2005/08/20 15:33:12 @@ -520,6 +520,7 @@
// Channel:
+ cDevice::WaitForAllDevicesReady(30); Channels.SwitchTo(Setup.CurrentChannel); if (MuteAudio) cDevice::PrimaryDevice()->ToggleMute();