Now handling CAT sections that consist of more than one TS packet

This commit is contained in:
Klaus Schmidinger 2015-01-13 14:45:12 +01:00
parent 14e37ed124
commit 24b38eb812
2 changed files with 75 additions and 34 deletions

View File

@ -8357,3 +8357,4 @@ Video Disk Recorder Revision History
(reported by Dieter Ferdinand).
- Changed the German weekday names from "MonDieMitDonFreSamSon" to
"Mo.Di.Mi.Do.Fr.Sa.So." (thanks to Stefan Blochberger).
- Now handling CAT sections that consist of more than one TS packet.

108
ci.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: ci.c 3.15 2015/01/12 10:44:58 kls Exp $
* $Id: ci.c 3.16 2015/01/13 14:42:32 kls Exp $
*/
#include "ci.h"
@ -114,6 +114,9 @@ class cCaPidReceiver : public cReceiver {
private:
int catVersion;
cVector<int> emmPids;
uchar buffer[2048]; // 11 bit length, max. 2048 byte
uchar *bufp;
int length;
void AddEmmPid(int Pid);
void DelEmmPids(void);
protected:
@ -129,6 +132,8 @@ public:
cCaPidReceiver::cCaPidReceiver(void)
{
catVersion = -1;
bufp = NULL;
length = 0;
AddPid(CATPID);
}
@ -156,43 +161,78 @@ void cCaPidReceiver::Activate(bool On)
void cCaPidReceiver::Receive(uchar *Data, int Length)
{
if (TsPid(Data) == CATPID && Data[5] == SI::TableIdCAT) {
int l = (int(Data[6] & 0x03) << 8) | Data[7]; // section length
if (l > 5) {
int v = (Data[10] & 0x3E) >> 1; // version number
if (v != catVersion) {
if (Data[11] == 0 && Data[12] == 0) { // section number, last section number
if (l <= TS_SIZE - 8) {
cDevice *AttachedDevice = Device();
if (AttachedDevice)
AttachedDevice->Detach(this);
DelEmmPids();
for (int i = 13; i < l + 8 - 4; i++) { // +8 = header, -4 = checksum
if (Data[i] == 0x09) {
int CaId = int(Data[i + 2] << 8) | Data[i + 3];
int EmmPid = int(((Data[i + 4] & 0x1F) << 8)) | Data[i + 5];
AddEmmPid(EmmPid);
switch (CaId >> 8) {
case 0x01: for (int j = i + 7; j < Data[i + 1] + 2; j += 4) {
EmmPid = (int(Data[j] & 0x0F) << 8) | Data[j + 1];
AddEmmPid(EmmPid);
}
break;
}
i += Data[i + 1] - 1; // -1 to compensate for the loop increment
}
}
if (AttachedDevice)
AttachedDevice->AttachReceiver(this);
if (TsPid(Data) == CATPID) {
uchar *p = NULL;
if (TsPayloadStart(Data)) {
if (Data[5] == SI::TableIdCAT) {
length = (int(Data[6] & 0x03) << 8) | Data[7]; // section length
if (length > 5) {
int v = (Data[10] & 0x3E) >> 1; // version number
if (v != catVersion) {
if (Data[11] == 0 && Data[12] == 0) { // section number, last section number
if (length > TS_SIZE - 8) {
int n = TS_SIZE - 13;
memcpy(buffer, Data + 13, n);
bufp = buffer + n;
length -= n + 5; // 5 = header
}
else {
p = Data + 13; // no need to copy the data
length -= 5; // header
}
}
else
dsyslog("multi table CAT section - unhandled!");
catVersion = v;
}
else
dsyslog("multi packet CAT section - unhandled!");
}
else
dsyslog("multi table CAT section - unhandled!");
catVersion = v;
}
}
else if (bufp && length > 0) {
int n = min(length, TS_SIZE - 4);
if (bufp + n - buffer <= int(sizeof(buffer))) {
memcpy(bufp, Data + 4, n);
bufp += n;
length -= n;
if (length <= 0) {
p = buffer;
length = bufp - buffer;
}
}
else {
esyslog("ERROR: buffer overflow in cCaPidReceiver::Receive()");
bufp = 0;
length = 0;
}
}
if (p) {
int OldCatVersion = catVersion; // must preserve the current version number
cDevice *AttachedDevice = Device();
if (AttachedDevice)
AttachedDevice->Detach(this);
DelEmmPids();
for (int i = 0; i < length - 4; i++) { // -4 = checksum
if (p[i] == 0x09) {
int CaId = int(p[i + 2] << 8) | p[i + 3];
int EmmPid = int(((p[i + 4] & 0x1F) << 8)) | p[i + 5];
AddEmmPid(EmmPid);
switch (CaId >> 8) {
case 0x01: for (int j = i + 7; j < p[i + 1] + 2; j += 4) {
EmmPid = (int(p[j] & 0x0F) << 8) | p[j + 1];
AddEmmPid(EmmPid);
}
break;
}
i += p[i + 1] + 2 - 1; // -1 to compensate for the loop increment
}
}
if (AttachedDevice)
AttachedDevice->AttachReceiver(this);
catVersion = OldCatVersion;
p = NULL;
bufp = 0;
length = 0;
}
}
}