Implemented handling multi packet CATs with MTD

This commit is contained in:
Klaus Schmidinger 2020-07-10 09:06:21 +02:00
parent 568ca0e773
commit dd6077eb90
3 changed files with 45 additions and 29 deletions

View File

@ -3617,6 +3617,7 @@ Helmut Binder <cco@aon.at>
for reporting that the 'else if' branch in cDevice::GetDeviceForTransponder() hasn't for reporting that the 'else if' branch in cDevice::GetDeviceForTransponder() hasn't
been active since version 1.7.29 been active since version 1.7.29
for fixing handling inactive shared CA pids for fixing handling inactive shared CA pids
for implementing handling multi packet CATs with MTD
Ulrich Eckhardt <uli@uli-eckhardt.de> Ulrich Eckhardt <uli@uli-eckhardt.de>
for reporting a problem with shutdown after user inactivity in case a plugin is for reporting a problem with shutdown after user inactivity in case a plugin is

View File

@ -9499,7 +9499,7 @@ Video Disk Recorder Revision History
rendered the whole code branch inactive. Now this branch is only executed for devices rendered the whole code branch inactive. Now this branch is only executed for devices
that are not bonded. that are not bonded.
2020-07-01: 2020-07-10:
- Improved deleting plugins in case the plugin uses its own memory management (thanks - Improved deleting plugins in case the plugin uses its own memory management (thanks
to Winfried Köhler). Plugins that have been compiled with previous versions of VDR to Winfried Köhler). Plugins that have been compiled with previous versions of VDR
@ -9508,3 +9508,4 @@ Video Disk Recorder Revision History
~cDisplayChannel(), to avoid possible problems in case a plugin calls IsOpen() ~cDisplayChannel(), to avoid possible problems in case a plugin calls IsOpen()
(reported by Thomas Reufer). (reported by Thomas Reufer).
- Fixed handling inactive shared CA pids (thanks to Helmut Binder). - Fixed handling inactive shared CA pids (thanks to Helmut Binder).
- Implemented handling multi packet CATs with MTD (thanks to Helmut Binder).

70
ci.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: ci.c 4.30 2020/07/01 15:16:21 kls Exp $ * $Id: ci.c 4.31 2020/07/10 09:06:21 kls Exp $
*/ */
#include "ci.h" #include "ci.h"
@ -118,9 +118,11 @@ class cCaPidReceiver : public cReceiver {
private: private:
int catVersion; int catVersion;
cVector<int> emmPids; cVector<int> emmPids;
uchar buffer[2048]; // 11 bit length, max. 2048 byte uchar buffer[1024]; // CAT table length: 10 bit -> max. 1021 + 3 bytes
uchar *bufp; uchar *bufp;
uchar mtdCatBuffer[TS_SIZE]; // TODO: handle multi packet CATs! #define CAT_MAXPACKETS 6 // 6 * 184 = 1104 bytes for CAT table
uchar mtdCatBuffer[CAT_MAXPACKETS][TS_SIZE]; // TODO: handle multi table CATs!
int mtdNumCatPackets;
int length; int length;
cMutex mutex; cMutex mutex;
bool handlingPid; bool handlingPid;
@ -147,6 +149,7 @@ cCaPidReceiver::cCaPidReceiver(void)
{ {
catVersion = -1; catVersion = -1;
bufp = NULL; bufp = NULL;
mtdNumCatPackets = 0;
length = 0; length = 0;
handlingPid = false; handlingPid = false;
cMutexLock MutexLock(&mutex); cMutexLock MutexLock(&mutex);
@ -185,30 +188,34 @@ void cCaPidReceiver::Receive(const uchar *Data, int Length)
const uchar *p = NULL; const uchar *p = NULL;
if (TsPayloadStart(Data)) { if (TsPayloadStart(Data)) {
if (Data[5] == SI::TableIdCAT) { if (Data[5] == SI::TableIdCAT) {
length = (int(Data[6] & 0x03) << 8) | Data[7]; // section length length = (int(Data[6] & 0x0F) << 8) | Data[7]; // section length (12 bit field)
if (length > 5) { if (length > 5) {
int v = (Data[10] & 0x3E) >> 1; // version number int v = (Data[10] & 0x3E) >> 1; // version number
if (v != catVersion) { if (v != catVersion) {
if (Data[11] == 0 && Data[12] == 0) { // section number, last section number if (Data[11] == 0 && Data[12] == 0) { // section number, last section number
if (length > TS_SIZE - 8) { length += 3; // with TableIdCAT -> Data[5]
if (MtdCamSlot) if (length > TS_SIZE - 5) {
esyslog("ERROR: need to implement multi packet CAT handling for MTD!"); int n = TS_SIZE - 5;
int n = TS_SIZE - 13; memcpy(buffer, Data + 5, n);
memcpy(buffer, Data + 13, n);
bufp = buffer + n; bufp = buffer + n;
length -= n + 5; // 5 = header length -= n;
} }
else { else {
p = Data + 13; // no need to copy the data p = Data + 5; // no need to copy the data
length -= 5; // header }
if (MtdCamSlot) {
mtdNumCatPackets = 0;
memcpy(mtdCatBuffer[mtdNumCatPackets++], Data, TS_SIZE);
} }
} }
else else
dsyslog("multi table CAT section - unhandled!"); dsyslog("multi table CAT section - unhandled!");
catVersion = v; catVersion = v;
} }
else if (MtdCamSlot) else if (MtdCamSlot) {
MtdCamSlot->PutCat(mtdCatBuffer, TS_SIZE); for (int i = 0; i < mtdNumCatPackets; i++)
MtdCamSlot->PutCat(mtdCatBuffer[i], TS_SIZE);
}
} }
} }
} }
@ -222,6 +229,8 @@ void cCaPidReceiver::Receive(const uchar *Data, int Length)
p = buffer; p = buffer;
length = bufp - buffer; length = bufp - buffer;
} }
if (MtdCamSlot)
memcpy(mtdCatBuffer[mtdNumCatPackets++], Data, TS_SIZE);
} }
else { else {
esyslog("ERROR: buffer overflow in cCaPidReceiver::Receive()"); esyslog("ERROR: buffer overflow in cCaPidReceiver::Receive()");
@ -230,9 +239,9 @@ void cCaPidReceiver::Receive(const uchar *Data, int Length)
} }
} }
if (p) { if (p) {
if (!SI::CRC32::crc32((const char *)p - 8, length + 8, 0xFFFFFFFF)) { // <TableIdCAT,....,crc32> if (!SI::CRC32::crc32((const char *)p, length, 0xFFFFFFFF)) { // <TableIdCAT,....,crc32>
DelEmmPids(); DelEmmPids();
for (int i = 0; i < length - 4; i++) { // -4 = checksum for (int i = 8; i < length - 4; i++) { // -4 = checksum
if (p[i] == 0x09) { if (p[i] == 0x09) {
int CaId = int(p[i + 2] << 8) | p[i + 3]; int CaId = int(p[i + 2] << 8) | p[i + 3];
int EmmPid = Peek13(p + i + 4); int EmmPid = Peek13(p + i + 4);
@ -240,7 +249,7 @@ void cCaPidReceiver::Receive(const uchar *Data, int Length)
if (MtdCamSlot) if (MtdCamSlot)
MtdMapPid(const_cast<uchar *>(p + i + 4), MtdCamSlot->MtdMapper()); MtdMapPid(const_cast<uchar *>(p + i + 4), MtdCamSlot->MtdMapper());
switch (CaId >> 8) { switch (CaId >> 8) {
case 0x01: for (int j = i + 7; j < p[i + 1] + 2; j += 4) { case 0x01: for (int j = i + 7; j < i + p[i + 1] + 2; j += 4) {
EmmPid = Peek13(p + j); EmmPid = Peek13(p + j);
AddEmmPid(EmmPid); AddEmmPid(EmmPid);
if (MtdCamSlot) if (MtdCamSlot)
@ -252,17 +261,22 @@ void cCaPidReceiver::Receive(const uchar *Data, int Length)
} }
} }
if (MtdCamSlot) { if (MtdCamSlot) {
if (!bufp && length) { // update crc32
// update crc32 - but only single packet CAT is handled for now: uint32_t crc = SI::CRC32::crc32((const char *)p, length - 4, 0xFFFFFFFF); // <TableIdCAT....>[crc32]
uint32_t crc = SI::CRC32::crc32((const char *)p - 8, length + 8 - 4, 0xFFFFFFFF); // <TableIdCAT....>[crc32] uchar *c = const_cast<uchar *>(p + length - 4);
uchar *c = const_cast<uchar *>(p + length - 4); *c++ = crc >> 24;
*c++ = crc >> 24; *c++ = crc >> 16;
*c++ = crc >> 16; *c++ = crc >> 8;
*c++ = crc >> 8; *c++ = crc;
*c++ = crc; // modify CAT packets
} const uchar *t = p;
memcpy(mtdCatBuffer, Data, TS_SIZE); for (int i = 0, j = 5; i < mtdNumCatPackets; i++, j = 4) {
MtdCamSlot->PutCat(mtdCatBuffer, TS_SIZE); int n = min(length, TS_SIZE - j);
memcpy(mtdCatBuffer[i] + j, t, n);
t += n;
length -= n;
MtdCamSlot->PutCat(mtdCatBuffer[i], TS_SIZE);
}
} }
} }
else { else {