summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKlaus Schmidinger <vdr@tvdr.de>2017-05-01 09:32:32 +0200
committerKlaus Schmidinger <vdr@tvdr.de>2017-05-01 09:32:32 +0200
commit073268bd45a4a36e0d20ba1a60d585e9cae13e30 (patch)
tree65f8eba2ba526aeac251d1d1756abfac18cfee3d
parent7cfce2fffa067a702af4e3b18e52e7d631dc006c (diff)
downloadvdr-073268bd45a4a36e0d20ba1a60d585e9cae13e30.tar.gz
vdr-073268bd45a4a36e0d20ba1a60d585e9cae13e30.tar.bz2
CAMs are now sent a generated EIT packet that contains a single 'present event' for the current SID, in order to avoid any parental rating dialogs
-rw-r--r--HISTORY5
-rw-r--r--ci.c13
-rw-r--r--ci.h13
-rw-r--r--config.h10
-rw-r--r--device.c19
-rw-r--r--mtd.c29
-rw-r--r--mtd.h3
-rw-r--r--receiver.c4
-rw-r--r--receiver.h4
-rw-r--r--remux.c89
-rw-r--r--remux.h19
11 files changed, 182 insertions, 26 deletions
diff --git a/HISTORY b/HISTORY
index a79eef11..3c3b7605 100644
--- a/HISTORY
+++ b/HISTORY
@@ -8990,3 +8990,8 @@ Video Disk Recorder Revision History
- If 0 is given as the channel number in the SVDRP command LSTC, the data of the
current channel is listed.
- Fixed a possible crash when pulling the CAM while decrypting a channel with MTD.
+
+2017-05-01: Version 2.3.5
+
+- CAMs are now sent a generated EIT packet that contains a single 'present event' for
+ the current SID, in order to avoid any parental rating dialogs.
diff --git a/ci.c b/ci.c
index f64c17e3..def1530a 100644
--- a/ci.c
+++ b/ci.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: ci.c 4.13 2017/04/26 09:18:26 kls Exp $
+ * $Id: ci.c 4.14 2017/05/01 09:26:12 kls Exp $
*/
#include "ci.h"
@@ -2424,6 +2424,17 @@ uchar *cCamSlot::Decrypt(uchar *Data, int &Count)
return Data;
}
+bool cCamSlot::Inject(uchar *Data, int Count)
+{
+ return true;
+}
+
+void cCamSlot::InjectEit(int Sid)
+{
+ cEitGenerator Eit(Sid);
+ Inject(Eit.Data(), Eit.Length());
+}
+
// --- cCamSlots -------------------------------------------------------------
cCamSlots CamSlots;
diff --git a/ci.h b/ci.h
index 8d1323ac..342cfb96 100644
--- a/ci.h
+++ b/ci.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: ci.h 4.6 2017/04/10 09:17:56 kls Exp $
+ * $Id: ci.h 4.7 2017/05/01 09:21:22 kls Exp $
*/
#ifndef __CI_H
@@ -377,6 +377,17 @@ public:
///< A derived class that implements this function will also need
///< to set the WantsTsData parameter in the call to the base class
///< constructor to true in order to receive the TS data.
+ virtual bool Inject(uchar *Data, int Count);
+ ///< Sends all Count bytes of the given Data to the CAM, and returns true
+ ///< if this was possible. If the data can't be sent to the CAM completely,
+ ///< nothing shall be sent and the return value shall be false.
+ ///< No decrypted packet is returned by this function.
+ virtual void InjectEit(int Sid);
+ ///< Injects a generated EIT with a "present event" for the given Sid into
+ ///< the TS data stream sent to the CAM. This only applies to CAM slots that
+ ///< have WantsTsData set to true in their constructor.
+ ///< The default implementation sends an EIT with the minimum event
+ ///< necessary to disable the CAMs parental rating prompt.
};
class cCamSlots : public cList<cCamSlot> {
diff --git a/config.h b/config.h
index e9a9f11d..c67b990d 100644
--- a/config.h
+++ b/config.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: config.h 4.8 2017/03/30 13:42:15 kls Exp $
+ * $Id: config.h 4.9 2017/04/29 13:33:13 kls Exp $
*/
#ifndef __CONFIG_H
@@ -22,13 +22,13 @@
// VDR's own version number:
-#define VDRVERSION "2.3.4"
-#define VDRVERSNUM 20304 // Version * 10000 + Major * 100 + Minor
+#define VDRVERSION "2.3.5"
+#define VDRVERSNUM 20305 // Version * 10000 + Major * 100 + Minor
// The plugin API's version number:
-#define APIVERSION "2.3.4"
-#define APIVERSNUM 20304 // Version * 10000 + Major * 100 + Minor
+#define APIVERSION "2.3.5"
+#define APIVERSNUM 20305 // Version * 10000 + Major * 100 + Minor
// When loading plugins, VDR searches them by their APIVERSION, which
// may be smaller than VDRVERSION in case there have been no changes to
diff --git a/device.c b/device.c
index 25d16679..185565b5 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 4.15 2017/04/17 14:47:42 kls Exp $
+ * $Id: device.c 4.16 2017/05/01 09:24:49 kls Exp $
*/
#include "device.h"
@@ -1652,6 +1652,7 @@ bool cDevice::Receiving(bool Dummy) const
#define TS_SCRAMBLING_TIMEOUT 3 // seconds to wait until a TS becomes unscrambled
#define TS_SCRAMBLING_TIME_OK 10 // seconds before a Channel/CAM combination is marked as known to decrypt
+#define EIT_INJECTION_TIME 10 // seconds for which to inject EIT event
void cDevice::Action(void)
{
@@ -1697,6 +1698,18 @@ void cDevice::Action(void)
}
}
}
+ // Inject EIT event to avoid the CAMs parental rating prompt:
+ if (Receiver->startEitInjection) {
+ time_t Now = time(NULL);
+ if (cCamSlot *cs = CamSlot()) {
+ if (Now != Receiver->lastEitInjection) { // once per second
+ cs->InjectEit(Receiver->ChannelID().Sid());
+ Receiver->lastEitInjection = Now;
+ }
+ }
+ if (Now - Receiver->startEitInjection > EIT_INJECTION_TIME)
+ Receiver->startEitInjection = 0;
+ }
}
}
Unlock();
@@ -1755,6 +1768,10 @@ bool cDevice::AttachReceiver(cReceiver *Receiver)
Unlock();
if (camSlot && Receiver->priority > MINPRIORITY) { // priority check to avoid an infinite loop with the CAM slot's caPidReceiver
camSlot->StartDecrypting();
+ if (camSlot->WantsTsData()) {
+ Receiver->lastEitInjection = 0;
+ Receiver->startEitInjection = time(NULL);
+ }
if (CamSlots.NumReadyMasterSlots() > 1) { // don't try different CAMs if there is only one
Receiver->startScrambleDetection = time(NULL);
Receiver->scramblingTimeout = TS_SCRAMBLING_TIMEOUT;
diff --git a/mtd.c b/mtd.c
index 29fe520f..345288ec 100644
--- a/mtd.c
+++ b/mtd.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: mtd.c 1.10 2017/04/26 08:33:54 kls Exp $
+ * $Id: mtd.c 1.11 2017/05/01 09:19:52 kls Exp $
*/
#include "mtd.h"
@@ -64,22 +64,20 @@ int cMtdHandler::Put(const uchar *Data, int Count)
if (int Skipped = TS_SYNC(Data, Count))
return Used + Skipped;
int Pid = TsPid(Data);
- if (Pid != CATPID) { // the original CAT with mapped PIDs must be skipped here!
#ifdef KEEPPIDS
- int Index = 0;
+ int Index = 0;
#else
- int Index = (Pid >> UNIQ_PID_SHIFT) - 1;
+ int Index = (Pid >> UNIQ_PID_SHIFT) - 1;
#endif // KEEPPIDS
- if (Index >= 0 && Index < camSlots.Size()) {
- int w = camSlots[Index]->PutData(Data, TS_SIZE);
- if (w == 0)
- break;
- else if (w != TS_SIZE)
- esyslog("ERROR: incomplete MTD packet written (%d) in PID %d (%04X)", Index + 1, Pid, Pid);
- }
- else if (Index >= 0) // we silently ignore Index -1 (i.e. MTD number 0), since there are several hundred empty TS packets when switching to an encrypted channel for the first time since startup
- esyslog("ERROR: invalid MTD number (%d) in PID %d (%04X)", Index + 1, Pid, Pid);
+ if (Index >= 0 && Index < camSlots.Size()) {
+ int w = camSlots[Index]->PutData(Data, TS_SIZE);
+ if (w == 0)
+ break;
+ else if (w != TS_SIZE)
+ esyslog("ERROR: incomplete MTD packet written (%d) in PID %d (%04X)", Index + 1, Pid, Pid);
}
+ else if (Index >= 0) // anything with Index -1 (i.e. MTD number 0) is either garbage or an actual CAT or EIT, which need not be returned to the device
+ esyslog("ERROR: invalid MTD number (%d) in PID %d (%04X)", Index + 1, Pid, Pid);
Data += TS_SIZE;
Count -= TS_SIZE;
Used += TS_SIZE;
@@ -329,6 +327,11 @@ uchar *cMtdCamSlot::Decrypt(uchar *Data, int &Count)
return d;
}
+void cMtdCamSlot::InjectEit(int Sid)
+{
+ MasterSlot()->InjectEit(mtdMapper->RealToUniqSid(Sid));
+}
+
int cMtdCamSlot::PutData(const uchar *Data, int Count)
{
int Free = mtdBuffer->Free();
diff --git a/mtd.h b/mtd.h
index 7f2151a3..2be5f3dc 100644
--- a/mtd.h
+++ b/mtd.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: mtd.h 1.7 2017/04/26 09:17:08 kls Exp $
+ * $Id: mtd.h 1.8 2017/05/01 09:19:21 kls Exp $
*/
#ifndef __MTD_H
@@ -172,6 +172,7 @@ public:
virtual void StartDecrypting(void);
virtual void StopDecrypting(void);
virtual uchar *Decrypt(uchar *Data, int &Count);
+ virtual void InjectEit(int Sid);
int PutData(const uchar *Data, int Count);
int PutCat(const uchar *Data, int Count);
// The following functions shall not be called for a cMtdCamSlot:
diff --git a/receiver.c b/receiver.c
index ef3a5cd1..f664da4a 100644
--- a/receiver.c
+++ b/receiver.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: receiver.c 4.3 2017/04/02 10:08:49 kls Exp $
+ * $Id: receiver.c 4.4 2017/05/01 08:49:20 kls Exp $
*/
#include "receiver.h"
@@ -19,6 +19,8 @@ cReceiver::cReceiver(const cChannel *Channel, int Priority)
lastScrambledPacket = 0;
startScrambleDetection = 0;
scramblingTimeout = 0;
+ startEitInjection = 0;
+ lastEitInjection = 0;
SetPids(Channel);
}
diff --git a/receiver.h b/receiver.h
index 0ba8cb44..9bbc6bdb 100644
--- a/receiver.h
+++ b/receiver.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: receiver.h 4.2 2017/04/02 10:08:49 kls Exp $
+ * $Id: receiver.h 4.3 2017/05/01 08:48:34 kls Exp $
*/
#ifndef __RECEIVER_H
@@ -25,6 +25,8 @@ private:
time_t lastScrambledPacket;
time_t startScrambleDetection;
int scramblingTimeout;
+ time_t startEitInjection;
+ time_t lastEitInjection;
bool WantsPid(int Pid);
protected:
cDevice *Device(void) { return device; }
diff --git a/remux.c b/remux.c
index 4a3ff143..6993e9b7 100644
--- a/remux.c
+++ b/remux.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: remux.c 4.6 2017/04/24 14:59:39 kls Exp $
+ * $Id: remux.c 4.7 2017/04/29 12:25:09 kls Exp $
*/
#include "remux.h"
@@ -940,6 +940,93 @@ bool cPatPmtParser::GetVersions(int &PatVersion, int &PmtVersion) const
return patVersion >= 0 && pmtVersion >= 0;
}
+// --- cEitGenerator ---------------------------------------------------------
+
+cEitGenerator::cEitGenerator(int Sid)
+{
+ counter = 0;
+ version = 0;
+ if (Sid)
+ Generate(Sid);
+}
+
+uint16_t cEitGenerator::YMDtoMJD(int Y, int M, int D)
+{
+ int L = (M < 3) ? 1 : 0;
+ return 14956 + D + int((Y - L) * 365.25) + int((M + 1 + L * 12) * 30.6001);
+}
+
+uchar *cEitGenerator::AddParentalRatingDescriptor(uchar *p, uchar ParentalRating)
+{
+ *p++ = SI::ParentalRatingDescriptorTag;
+ *p++ = 0x04; // descriptor length
+ *p++ = 'D'; // country code
+ *p++ = 'E';
+ *p++ = 'U';
+ *p++ = ParentalRating;
+ return p;
+}
+
+uchar *cEitGenerator::Generate(int Sid)
+{
+ uchar *PayloadStart;
+ uchar *SectionStart;
+ uchar *DescriptorsStart;
+ memset(eit, 0xFF, sizeof(eit));
+ struct tm tm_r;
+ time_t t = time(NULL) - 3600; // let's have the event start one hour in the past
+ tm *tm = localtime_r(&t, &tm_r);
+ uint16_t MJD = YMDtoMJD(tm->tm_year, tm->tm_mon + 1, tm->tm_mday);
+ uchar *p = eit;
+ // TS header:
+ *p++ = TS_SYNC_BYTE;
+ *p++ = TS_PAYLOAD_START;
+ *p++ = EITPID;
+ *p++ = 0x10 | (counter++ & 0x0F); // continuity counter
+ *p++ = 0x00; // pointer field (payload unit start indicator is set)
+ // payload:
+ PayloadStart = p;
+ *p++ = 0x4E; // TID present/following event on this transponder
+ *p++ = 0xF0;
+ *p++ = 0x00; // section length
+ SectionStart = p;
+ *p++ = Sid >> 8;
+ *p++ = Sid & 0xFF;
+ *p++ = 0xC1 | (version << 1);
+ *p++ = 0x00; // section number
+ *p++ = 0x00; // last section number
+ *p++ = 0x00; // transport stream id
+ *p++ = 0x00; // ...
+ *p++ = 0x00; // original network id
+ *p++ = 0x00; // ...
+ *p++ = 0x00; // segment last section number
+ *p++ = 0x4E; // last table id
+ *p++ = 0x00; // event id
+ *p++ = 0x01; // ...
+ *p++ = MJD >> 8; // start time
+ *p++ = MJD & 0xFF; // ...
+ *p++ = tm->tm_hour; // ...
+ *p++ = tm->tm_min; // ...
+ *p++ = tm->tm_sec; // ...
+ *p++ = 0x24; // duration (one day, should cover everything)
+ *p++ = 0x00; // ...
+ *p++ = 0x00; // ...
+ *p++ = 0x90; // running status, free/CA mode
+ *p++ = 0x00; // descriptors loop length
+ DescriptorsStart = p;
+ p = AddParentalRatingDescriptor(p);
+ // fill in lengths:
+ *(SectionStart - 1) = p - SectionStart + 4; // +4 = length of CRC
+ *(DescriptorsStart - 1) = p - DescriptorsStart;
+ // checksum
+ int crc = SI::CRC32::crc32((char *)PayloadStart, p - PayloadStart, 0xFFFFFFFF);
+ *p++ = crc >> 24;
+ *p++ = crc >> 16;
+ *p++ = crc >> 8;
+ *p++ = crc;
+ return eit;
+}
+
// --- cTsToPes --------------------------------------------------------------
cTsToPes::cTsToPes(void)
diff --git a/remux.h b/remux.h
index 7dd5b163..1bd96d9b 100644
--- a/remux.h
+++ b/remux.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: remux.h 4.3 2017/03/26 13:06:37 kls Exp $
+ * $Id: remux.h 4.4 2017/04/29 11:56:21 kls Exp $
*/
#ifndef __REMUX_H
@@ -51,6 +51,7 @@ public:
#define PATPID 0x0000 // PAT PID (constant 0)
#define CATPID 0x0001 // CAT PID (constant 1)
+#define EITPID 0x0012 // EIT PID (constant 18)
#define MAXPID 0x2000 // for arrays that use a PID as the index
#define PTSTICKS 90000 // number of PTS ticks per second
@@ -431,6 +432,22 @@ public:
uint16_t AncillaryPageId(int i) const { return (0 <= i && i < MAXSPIDS) ? ancillaryPageIds[i] : uint16_t(0); }
};
+// EIT Generator:
+
+class cEitGenerator {
+private:
+ uchar eit[TS_SIZE];
+ int counter;
+ int version;
+ uint16_t YMDtoMJD(int Y, int M, int D);
+ uchar *AddParentalRatingDescriptor(uchar *p, uchar ParentalRating = 0);
+public:
+ cEitGenerator(int Sid = 0);
+ uchar *Generate(int Sid);
+ uchar *Data(void) { return eit; }
+ int Length(void) { return sizeof(eit); }
+ };
+
// TS to PES converter:
// Puts together the payload of several TS packets that form one PES
// packet.