summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKlaus Schmidinger <vdr@tvdr.de>2014-02-18 13:12:39 +0100
committerKlaus Schmidinger <vdr@tvdr.de>2014-02-18 13:12:39 +0100
commit0de69c389993ca0c78c726fe567ae4e155c9a1b9 (patch)
treee51363f8e94b8c6d3073a176c764c11ed5096ea8
parent0238234c52eee5e7ef3642801ace30c7d5bd1a19 (diff)
downloadvdr-0de69c389993ca0c78c726fe567ae4e155c9a1b9.tar.gz
vdr-0de69c389993ca0c78c726fe567ae4e155c9a1b9.tar.bz2
Improved PAT/PMT scanning to speed up initial tuning to encrypted channels on transponders with many PAT entries
-rw-r--r--CONTRIBUTORS2
-rw-r--r--HISTORY4
-rw-r--r--device.c3
-rw-r--r--pat.c133
-rw-r--r--pat.h20
-rw-r--r--sdt.c6
6 files changed, 102 insertions, 66 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 7ebbdb69..9721f831 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -3262,6 +3262,8 @@ Christian Paulick <cpaulick@xeatre.tv>
Mariusz Bialonczyk <manio@skyboo.net>
for reporting a problem with live streaming of encrypted channels, when there are no
CA descriptors, yet, on initial tuning
+ for reporting that acquiring the CA descriptors takes way too long on transponders
+ with many PAT entries, and his help in debugging this
Tony Houghton <h@realh.co.uk>
for suggesting to add LinkageTypePremiere to libsi/si.h and eit.c to avoid a compiler
diff --git a/HISTORY b/HISTORY
index b697a6a7..d39d0dc0 100644
--- a/HISTORY
+++ b/HISTORY
@@ -8170,7 +8170,7 @@ Video Disk Recorder Revision History
- Fixed a superfluous call to the skin's SetRecording() function after renaming a
recording (reported by Christoph Haubrich).
-2014-02-15: Version 2.1.5
+2014-02-18: Version 2.1.5
- Now checking whether the primary device actually has a decoder before retuning the
current channel after a change in its parameters. This fixes broken recordings on
@@ -8197,3 +8197,5 @@ Video Disk Recorder Revision History
- Replaced the NULL pointer assignment in ~cReceiver() to force a segfault with
a call to abort() (suggested by Tony Houghten).
- Fixed learning keyboard remote control codes (thanks to Lars Hanisch).
+- Improved PAT/PMT scanning to speed up initial tuning to encrypted channels on
+ transponders with many PAT entries (reported by Mariusz Bialonczyk).
diff --git a/device.c b/device.c
index 9da5e7ff..901fa2b3 100644
--- a/device.c
+++ b/device.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: device.c 3.11 2014/01/21 11:12:01 kls Exp $
+ * $Id: device.c 3.12 2014/02/18 13:12:39 kls Exp $
*/
#include "device.h"
@@ -794,6 +794,7 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
if (SetChannelDevice(Channel, LiveView)) {
// Start section handling:
if (sectionHandler) {
+ patFilter->Trigger(Channel->Sid());
sectionHandler->SetChannel(Channel);
sectionHandler->SetStatus(true);
}
diff --git a/pat.c b/pat.c
index 5246e074..73dc32b6 100644
--- a/pat.c
+++ b/pat.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: pat.c 3.2 2014/01/04 11:17:24 kls Exp $
+ * $Id: pat.c 3.3 2014/02/18 13:03:19 kls Exp $
*/
#include "pat.h"
@@ -12,9 +12,8 @@
#include "channels.h"
#include "libsi/section.h"
#include "libsi/descriptor.h"
-#include "thread.h"
-#define PMT_SCAN_TIMEOUT 10 // seconds
+#define PMT_SCAN_TIMEOUT 1000 // ms
// --- cCaDescriptor ---------------------------------------------------------
@@ -273,94 +272,115 @@ int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds
// --- cPatFilter ------------------------------------------------------------
+//#define DEBUG_PAT_PMT
+#ifdef DEBUG_PAT_PMT
+#define DBGLOG(a...) { cString s = cString::sprintf(a); fprintf(stderr, "%s\n", *s); dsyslog("%s", *s); }
+#else
+#define DBGLOG(a...)
+#endif
+
cPatFilter::cPatFilter(void)
{
- pmtIndex = 0;
- pmtPid = 0;
- pmtSid = 0;
- lastPmtScan = 0;
- numPmtEntries = 0;
+ Trigger(0);
Set(0x00, 0x00); // PAT
}
void cPatFilter::SetStatus(bool On)
{
+ cMutexLock MutexLock(&mutex);
+ DBGLOG("PAT filter set status %d", On);
cFilter::SetStatus(On);
- pmtIndex = 0;
- pmtPid = 0;
- pmtSid = 0;
- lastPmtScan = 0;
- numPmtEntries = 0;
+ Trigger();
}
-void cPatFilter::Trigger(void)
+void cPatFilter::Trigger(int Sid)
{
+ cMutexLock MutexLock(&mutex);
+ patVersion = -1;
+ pmtIndex = -1;
numPmtEntries = 0;
+ if (Sid >= 0) {
+ sid = Sid;
+ DBGLOG("PAT filter trigger SID %d", Sid);
+ }
}
-bool cPatFilter::PmtVersionChanged(int PmtPid, int Sid, int Version)
+bool cPatFilter::PmtVersionChanged(int PmtPid, int Sid, int Version, bool SetNewVersion)
{
- uint64_t v = Version;
- v <<= 32;
- uint64_t id = (PmtPid | (Sid << 16)) & 0x00000000FFFFFFFFLL;
+ int Id = MakePmtId(PmtPid, Sid);
for (int i = 0; i < numPmtEntries; i++) {
- if ((pmtVersion[i] & 0x00000000FFFFFFFFLL) == id) {
- bool Changed = (pmtVersion[i] & 0x000000FF00000000LL) != v;
- if (Changed)
- pmtVersion[i] = id | v;
- return Changed;
+ if (pmtId[i] == Id) {
+ if (pmtVersion[i] != Version) {
+ if (SetNewVersion)
+ pmtVersion[i] = Version;
+ else
+ DBGLOG("PMT %d %2d %5d %2d -> %2d", Transponder(), i, PmtPid, pmtVersion[i], Version);
+ return true;
+ }
+ break;
}
}
- if (numPmtEntries < MAXPMTENTRIES)
- pmtVersion[numPmtEntries++] = id | v;
- return true;
+ return false;
+}
+
+void cPatFilter::SwitchToNextPmtPid(void)
+{
+ if (pmtIndex >= 0) {
+ Del(GetPmtPid(pmtIndex), SI::TableIdPMT);
+ pmtIndex = (pmtIndex + 1) % numPmtEntries;
+ Add(GetPmtPid(pmtIndex), SI::TableIdPMT);
+ }
}
void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
{
+ cMutexLock MutexLock(&mutex);
if (Pid == 0x00) {
- if (Tid == 0x00) {
- if (pmtPid && time(NULL) - lastPmtScan > PMT_SCAN_TIMEOUT) {
- Del(pmtPid, 0x02);
- pmtPid = 0;
- pmtIndex++;
- lastPmtScan = time(NULL);
- }
- if (!pmtPid) {
- SI::PAT pat(Data, false);
- if (!pat.CheckCRCAndParse())
- return;
+ if (Tid == SI::TableIdPAT) {
+ SI::PAT pat(Data, false);
+ if (!pat.CheckCRCAndParse())
+ return;
+ if (pat.getVersionNumber() != patVersion) {
+ DBGLOG("PAT %d/%d %d %d -> %d", pat.getSectionNumber(), pat.getLastSectionNumber(), Transponder(), patVersion, pat.getVersionNumber());
+ if (pmtIndex >= 0) {
+ Del(GetPmtPid(pmtIndex), SI::TableIdPMT);
+ pmtIndex = -1;
+ }
+ numPmtEntries = 0;
SI::PAT::Association assoc;
- int Index = 0;
for (SI::Loop::Iterator it; pat.associationLoop.getNext(assoc, it); ) {
- if (!assoc.isNITPid()) {
- if (Index++ >= pmtIndex && Channels.GetByServiceID(Source(), Transponder(), assoc.getServiceId())) {
- pmtPid = assoc.getPid();
- pmtSid = assoc.getServiceId();
- Add(pmtPid, 0x02);
- break;
+ if (!assoc.isNITPid() && numPmtEntries < MAXPMTENTRIES) {
+ DBGLOG(" PMT pid %2d %5d SID %5d", numPmtEntries, assoc.getPid(), assoc.getServiceId());
+ pmtId[numPmtEntries] = MakePmtId(assoc.getPid(), assoc.getServiceId());
+ pmtVersion[numPmtEntries] = -1;
+ if (sid == assoc.getServiceId()) {
+ pmtIndex = numPmtEntries;
+ DBGLOG("sid = %d pmtIndex = %d", sid, pmtIndex);
}
+ numPmtEntries++;
}
}
- if (!pmtPid)
+ if (numPmtEntries > 0 && pmtIndex < 0)
pmtIndex = 0;
+ Add(GetPmtPid(pmtIndex), SI::TableIdPMT);
+ patVersion = pat.getVersionNumber();
+ timer.Set(PMT_SCAN_TIMEOUT);
}
}
}
- else if (Pid == pmtPid && Tid == SI::TableIdPMT && Source() && Transponder()) {
+ else if (Tid == SI::TableIdPMT && Source() && Transponder()) {
+ timer.Set(PMT_SCAN_TIMEOUT);
SI::PMT pmt(Data, false);
if (!pmt.CheckCRCAndParse())
return;
- if (pmt.getServiceId() != pmtSid)
- return; // skip broken PMT records
- if (!PmtVersionChanged(pmtPid, pmt.getTableIdExtension(), pmt.getVersionNumber())) {
- lastPmtScan = 0; // this triggers the next scan
+ if (!PmtVersionChanged(Pid, pmt.getTableIdExtension(), pmt.getVersionNumber())) {
+ SwitchToNextPmtPid();
return;
}
- if (!Channels.Lock(true, 10)) {
- numPmtEntries = 0; // to make sure we try again
+ if (!Channels.Lock(true, 10))
return;
- }
+ PmtVersionChanged(Pid, pmt.getTableIdExtension(), pmt.getVersionNumber(), true);
+ SwitchToNextPmtPid();
cChannel *Channel = Channels.GetByServiceID(Source(), Transponder(), pmt.getServiceId());
if (Channel) {
SI::CaDescriptor *d;
@@ -596,7 +616,12 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
}
Channel->SetCaDescriptors(CaDescriptorHandler.AddCaDescriptors(CaDescriptors));
}
- lastPmtScan = 0; // this triggers the next scan
Channels.Unlock();
}
+ if (timer.TimedOut()) {
+ if (pmtIndex >= 0)
+ DBGLOG("PMT timeout %d", pmtIndex);
+ SwitchToNextPmtPid();
+ timer.Set(PMT_SCAN_TIMEOUT);
+ }
}
diff --git a/pat.h b/pat.h
index 7f04575e..993a9b96 100644
--- a/pat.h
+++ b/pat.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: pat.h 3.2 2014/01/04 11:16:48 kls Exp $
+ * $Id: pat.h 3.3 2014/02/18 11:22:34 kls Exp $
*/
#ifndef __PAT_H
@@ -12,24 +12,30 @@
#include <stdint.h>
#include "filter.h"
+#include "thread.h"
#define MAXPMTENTRIES 64
class cPatFilter : public cFilter {
private:
- time_t lastPmtScan;
+ cMutex mutex;
+ cTimeMs timer;
+ int patVersion;
int pmtIndex;
- int pmtPid;
- int pmtSid;
- uint64_t pmtVersion[MAXPMTENTRIES];
+ int pmtId[MAXPMTENTRIES];
+ int pmtVersion[MAXPMTENTRIES];
int numPmtEntries;
- bool PmtVersionChanged(int PmtPid, int Sid, int Version);
+ int sid;
+ int GetPmtPid(int Index) { return pmtId[Index] & 0x0000FFFF; }
+ int MakePmtId(int PmtPid, int Sid) { return PmtPid | (Sid << 16); }
+ bool PmtVersionChanged(int PmtPid, int Sid, int Version, bool SetNewVersion = false);
+ void SwitchToNextPmtPid(void);
protected:
virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length);
public:
cPatFilter(void);
virtual void SetStatus(bool On);
- void Trigger(void);
+ void Trigger(int Sid = -1);
};
int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
diff --git a/sdt.c b/sdt.c
index c6d0ce54..44c6c9d9 100644
--- a/sdt.c
+++ b/sdt.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: sdt.c 3.1 2014/01/04 15:02:31 kls Exp $
+ * $Id: sdt.c 3.2 2014/02/18 10:37:50 kls Exp $
*/
#include "sdt.h"
@@ -94,7 +94,7 @@ void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
}
else if (*pn && Setup.UpdateChannels >= 4) {
channel = Channels.NewChannel(Channel(), pn, ps, pp, sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId());
- patFilter->Trigger();
+ patFilter->Trigger(SiSdtService.getServiceId());
}
}
default: ;
@@ -120,7 +120,7 @@ void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
cChannel *link = Channels.GetByChannelID(tChannelID(Source(), Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId()));
if (!link && Setup.UpdateChannels >= 4) {
link = Channels.NewChannel(Channel(), "NVOD", "", "", Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId());
- patFilter->Trigger();
+ patFilter->Trigger(Service.getServiceId());
}
if (link) {
if (!LinkChannels)