Fixed generating CaPmts in case audio and video are encrypted using different ECM pids

This commit is contained in:
Klaus Schmidinger 2009-08-15 22:19:42 +02:00
parent 23b5b1336d
commit 6d060a98f2
4 changed files with 70 additions and 53 deletions

View File

@ -6136,7 +6136,7 @@ Video Disk Recorder Revision History
file in a wrong way. file in a wrong way.
- Fixed variable types in cIndexFile (reported by Udo Richter). - Fixed variable types in cIndexFile (reported by Udo Richter).
2009-08-09: Version 1.7.9 2009-08-15: Version 1.7.9
- Fixed storing the current OSD size in case the device has - Fixed storing the current OSD size in case the device has
changed it in its setup menu (reported by Reinhard Nissl). changed it in its setup menu (reported by Reinhard Nissl).
@ -6148,3 +6148,5 @@ Video Disk Recorder Revision History
are assigned to doesn't have a VPS tag. are assigned to doesn't have a VPS tag.
- Fixed handling file name length on VFAT systems in case they - Fixed handling file name length on VFAT systems in case they
contain UTF-8 characters (thanks to Rolf Ahrenberg). contain UTF-8 characters (thanks to Rolf Ahrenberg).
- Fixed generating CaPmts in case audio and video are encrypted using different
ECM pids.

31
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 2.1 2008/04/13 13:28:52 kls Exp $ * $Id: ci.c 2.2 2009/08/15 11:16:27 kls Exp $
*/ */
#include "ci.h" #include "ci.h"
@ -551,6 +551,8 @@ bool cCiApplicationInformation::EnterMenu(void)
// --- cCiCaPmt -------------------------------------------------------------- // --- cCiCaPmt --------------------------------------------------------------
#define MAXCASYSTEMIDS 64
// Ca Pmt List Management: // Ca Pmt List Management:
#define CPLM_MORE 0x00 #define CPLM_MORE 0x00
@ -574,9 +576,10 @@ private:
int length; int length;
int esInfoLengthPos; int esInfoLengthPos;
uint8_t capmt[2048]; ///< XXX is there a specified maximum? uint8_t capmt[2048]; ///< XXX is there a specified maximum?
int caDescriptorsLength; int source;
uint8_t caDescriptors[2048]; int transponder;
bool streamFlag; int programNumber;
int caSystemIds[MAXCASYSTEMIDS + 1]; // list is zero terminated!
void AddCaDescriptors(int Length, const uint8_t *Data); void AddCaDescriptors(int Length, const uint8_t *Data);
public: public:
cCiCaPmt(uint8_t CmdId, int Source, int Transponder, int ProgramNumber, const int *CaSystemIds); cCiCaPmt(uint8_t CmdId, int Source, int Transponder, int ProgramNumber, const int *CaSystemIds);
@ -589,7 +592,17 @@ public:
cCiCaPmt::cCiCaPmt(uint8_t CmdId, int Source, int Transponder, int ProgramNumber, const int *CaSystemIds) cCiCaPmt::cCiCaPmt(uint8_t CmdId, int Source, int Transponder, int ProgramNumber, const int *CaSystemIds)
{ {
cmdId = CmdId; cmdId = CmdId;
caDescriptorsLength = GetCaDescriptors(Source, Transponder, ProgramNumber, CaSystemIds, sizeof(caDescriptors), caDescriptors, streamFlag); source = Source;
transponder = Transponder;
programNumber = ProgramNumber;
int i = 0;
if (CaSystemIds) {
for (; CaSystemIds[i]; i++)
caSystemIds[i] = CaSystemIds[i];
}
caSystemIds[i] = 0;
uint8_t caDescriptors[512];
int caDescriptorsLength = GetCaDescriptors(source, transponder, programNumber, caSystemIds, sizeof(caDescriptors), caDescriptors, 0);
length = 0; length = 0;
capmt[length++] = CPLM_ONLY; capmt[length++] = CPLM_ONLY;
capmt[length++] = (ProgramNumber >> 8) & 0xFF; capmt[length++] = (ProgramNumber >> 8) & 0xFF;
@ -598,7 +611,7 @@ cCiCaPmt::cCiCaPmt(uint8_t CmdId, int Source, int Transponder, int ProgramNumber
esInfoLengthPos = length; esInfoLengthPos = length;
capmt[length++] = 0x00; // program_info_length H (at program level) capmt[length++] = 0x00; // program_info_length H (at program level)
capmt[length++] = 0x00; // program_info_length L capmt[length++] = 0x00; // program_info_length L
if (!streamFlag) if (caDescriptorsLength > 0)
AddCaDescriptors(caDescriptorsLength, caDescriptors); AddCaDescriptors(caDescriptorsLength, caDescriptors);
} }
@ -610,6 +623,8 @@ void cCiCaPmt::SetListManagement(uint8_t ListManagement)
void cCiCaPmt::AddPid(int Pid, uint8_t StreamType) void cCiCaPmt::AddPid(int Pid, uint8_t StreamType)
{ {
if (Pid) { if (Pid) {
uint8_t caDescriptors[512];
int caDescriptorsLength = GetCaDescriptors(source, transponder, programNumber, caSystemIds, sizeof(caDescriptors), caDescriptors, Pid);
//XXX buffer overflow check??? //XXX buffer overflow check???
capmt[length++] = StreamType; capmt[length++] = StreamType;
capmt[length++] = (Pid >> 8) & 0xFF; capmt[length++] = (Pid >> 8) & 0xFF;
@ -617,7 +632,7 @@ void cCiCaPmt::AddPid(int Pid, uint8_t StreamType)
esInfoLengthPos = length; esInfoLengthPos = length;
capmt[length++] = 0x00; // ES_info_length H (at ES level) capmt[length++] = 0x00; // ES_info_length H (at ES level)
capmt[length++] = 0x00; // ES_info_length L capmt[length++] = 0x00; // ES_info_length L
if (streamFlag) if (caDescriptorsLength > 0)
AddCaDescriptors(caDescriptorsLength, caDescriptors); AddCaDescriptors(caDescriptorsLength, caDescriptors);
} }
} }
@ -643,8 +658,6 @@ void cCiCaPmt::AddCaDescriptors(int Length, const uint8_t *Data)
// --- cCiConditionalAccessSupport ------------------------------------------- // --- cCiConditionalAccessSupport -------------------------------------------
#define MAXCASYSTEMIDS 64
// CA Enable Ids: // CA Enable Ids:
#define CAEI_POSSIBLE 0x01 #define CAEI_POSSIBLE 0x01

84
pat.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: pat.c 2.2 2008/07/06 14:01:32 kls Exp $ * $Id: pat.c 2.3 2009/08/15 22:16:02 kls Exp $
*/ */
#include "pat.h" #include "pat.h"
@ -21,23 +21,23 @@
class cCaDescriptor : public cListObject { class cCaDescriptor : public cListObject {
private: private:
int caSystem; int caSystem;
bool stream; int esPid;
int length; int length;
uchar *data; uchar *data;
public: public:
cCaDescriptor(int CaSystem, int CaPid, bool Stream, int Length, const uchar *Data); cCaDescriptor(int CaSystem, int CaPid, int EsPid, int Length, const uchar *Data);
virtual ~cCaDescriptor(); virtual ~cCaDescriptor();
bool operator== (const cCaDescriptor &arg) const; bool operator== (const cCaDescriptor &arg) const;
int CaSystem(void) { return caSystem; } int CaSystem(void) { return caSystem; }
int Stream(void) { return stream; } int EsPid(void) { return esPid; }
int Length(void) const { return length; } int Length(void) const { return length; }
const uchar *Data(void) const { return data; } const uchar *Data(void) const { return data; }
}; };
cCaDescriptor::cCaDescriptor(int CaSystem, int CaPid, bool Stream, int Length, const uchar *Data) cCaDescriptor::cCaDescriptor(int CaSystem, int CaPid, int EsPid, int Length, const uchar *Data)
{ {
caSystem = CaSystem; caSystem = CaSystem;
stream = Stream; esPid = EsPid;
length = Length + 6; length = Length + 6;
data = MALLOC(uchar, length); data = MALLOC(uchar, length);
data[0] = SI::CaDescriptorTag; data[0] = SI::CaDescriptorTag;
@ -57,7 +57,7 @@ cCaDescriptor::~cCaDescriptor()
bool cCaDescriptor::operator== (const cCaDescriptor &arg) const bool cCaDescriptor::operator== (const cCaDescriptor &arg) const
{ {
return length == arg.length && memcmp(data, arg.data, length) == 0; return esPid == arg.esPid && length == arg.length && memcmp(data, arg.data, length) == 0;
} }
// --- cCaDescriptors -------------------------------------------------------- // --- cCaDescriptors --------------------------------------------------------
@ -77,8 +77,8 @@ public:
bool Is(int Source, int Transponder, int ServiceId); bool Is(int Source, int Transponder, int ServiceId);
bool Is(cCaDescriptors * CaDescriptors); bool Is(cCaDescriptors * CaDescriptors);
bool Empty(void) { return caDescriptors.Count() == 0; } bool Empty(void) { return caDescriptors.Count() == 0; }
void AddCaDescriptor(SI::CaDescriptor *d, bool Stream); void AddCaDescriptor(SI::CaDescriptor *d, int EsPid);
int GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag); int GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
const int *CaIds(void) { return caIds; } const int *CaIds(void) { return caIds; }
}; };
@ -126,9 +126,9 @@ void cCaDescriptors::AddCaId(int CaId)
} }
} }
void cCaDescriptors::AddCaDescriptor(SI::CaDescriptor *d, bool Stream) void cCaDescriptors::AddCaDescriptor(SI::CaDescriptor *d, int EsPid)
{ {
cCaDescriptor *nca = new cCaDescriptor(d->getCaType(), d->getCaPid(), Stream, d->privateData.getLength(), d->privateData.getData()); cCaDescriptor *nca = new cCaDescriptor(d->getCaType(), d->getCaPid(), EsPid, d->privateData.getLength(), d->privateData.getData());
for (cCaDescriptor *ca = caDescriptors.First(); ca; ca = caDescriptors.Next(ca)) { for (cCaDescriptor *ca = caDescriptors.First(); ca; ca = caDescriptors.Next(ca)) {
if (*ca == *nca) { if (*ca == *nca) {
delete nca; delete nca;
@ -141,37 +141,39 @@ void cCaDescriptors::AddCaDescriptor(SI::CaDescriptor *d, bool Stream)
#ifdef DEBUG_CA_DESCRIPTORS #ifdef DEBUG_CA_DESCRIPTORS
char buffer[1024]; char buffer[1024];
char *q = buffer; char *q = buffer;
q += sprintf(q, "CAM: %04X %5d %5d %04X %d -", source, transponder, serviceId, d->getCaType(), Stream); q += sprintf(q, "CAM: %04X %5d %5d %04X %04X -", source, transponder, serviceId, d->getCaType(), EsPid);
for (int i = 0; i < nca->Length(); i++) for (int i = 0; i < nca->Length(); i++)
q += sprintf(q, " %02X", nca->Data()[i]); q += sprintf(q, " %02X", nca->Data()[i]);
dsyslog(buffer); dsyslog(buffer);
#endif #endif
} }
int cCaDescriptors::GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag) // EsPid is to select the "type" of CaDescriptor to be returned
// >0 - CaDescriptor for the particular esPid
// =0 - common CaDescriptor
// <0 - all CaDescriptors regardless of type (old default)
int cCaDescriptors::GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
{ {
if (!CaSystemIds || !*CaSystemIds) if (!CaSystemIds || !*CaSystemIds)
return 0; return 0;
if (BufSize > 0 && Data) { if (BufSize > 0 && Data) {
int length = 0; int length = 0;
int IsStream = -1;
for (cCaDescriptor *d = caDescriptors.First(); d; d = caDescriptors.Next(d)) { for (cCaDescriptor *d = caDescriptors.First(); d; d = caDescriptors.Next(d)) {
const int *caids = CaSystemIds; if (EsPid < 0 || d->EsPid() == EsPid) {
do { const int *caids = CaSystemIds;
if (d->CaSystem() == *caids) { do {
if (length + d->Length() <= BufSize) { if (d->CaSystem() == *caids) {
if (IsStream >= 0 && IsStream != d->Stream()) if (length + d->Length() <= BufSize) {
dsyslog("CAM: different stream flag in CA descriptors"); memcpy(Data + length, d->Data(), d->Length());
IsStream = d->Stream(); length += d->Length();
memcpy(Data + length, d->Data(), d->Length()); }
length += d->Length(); else
return -1;
} }
else } while (*++caids);
return -1; }
}
} while (*++caids);
} }
StreamFlag = IsStream == 1;
return length; return length;
} }
return -1; return -1;
@ -187,7 +189,7 @@ public:
// Returns 0 if this is an already known descriptor, // Returns 0 if this is an already known descriptor,
// 1 if it is an all new descriptor with actual contents, // 1 if it is an all new descriptor with actual contents,
// and 2 if an existing descriptor was changed. // and 2 if an existing descriptor was changed.
int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag); int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
}; };
int cCaDescriptorHandler::AddCaDescriptors(cCaDescriptors *CaDescriptors) int cCaDescriptorHandler::AddCaDescriptors(cCaDescriptors *CaDescriptors)
@ -208,22 +210,21 @@ int cCaDescriptorHandler::AddCaDescriptors(cCaDescriptors *CaDescriptors)
return CaDescriptors->Empty() ? 0 : 1; return CaDescriptors->Empty() ? 0 : 1;
} }
int cCaDescriptorHandler::GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag) int cCaDescriptorHandler::GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
{ {
cMutexLock MutexLock(&mutex); cMutexLock MutexLock(&mutex);
StreamFlag = false;
for (cCaDescriptors *ca = First(); ca; ca = Next(ca)) { for (cCaDescriptors *ca = First(); ca; ca = Next(ca)) {
if (ca->Is(Source, Transponder, ServiceId)) if (ca->Is(Source, Transponder, ServiceId))
return ca->GetCaDescriptors(CaSystemIds, BufSize, Data, StreamFlag); return ca->GetCaDescriptors(CaSystemIds, BufSize, Data, EsPid);
} }
return 0; return 0;
} }
cCaDescriptorHandler CaDescriptorHandler; cCaDescriptorHandler CaDescriptorHandler;
int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag) int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
{ {
return CaDescriptorHandler.GetCaDescriptors(Source, Transponder, ServiceId, CaSystemIds, BufSize, Data, StreamFlag); return CaDescriptorHandler.GetCaDescriptors(Source, Transponder, ServiceId, CaSystemIds, BufSize, Data, EsPid);
} }
// --- cPatFilter ------------------------------------------------------------ // --- cPatFilter ------------------------------------------------------------
@ -322,7 +323,7 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
cCaDescriptors *CaDescriptors = new cCaDescriptors(Channel->Source(), Channel->Transponder(), Channel->Sid()); cCaDescriptors *CaDescriptors = new cCaDescriptors(Channel->Source(), Channel->Transponder(), Channel->Sid());
// Scan the common loop: // Scan the common loop:
for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)pmt.commonDescriptors.getNext(it, SI::CaDescriptorTag)); ) { for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)pmt.commonDescriptors.getNext(it, SI::CaDescriptorTag)); ) {
CaDescriptors->AddCaDescriptor(d, false); CaDescriptors->AddCaDescriptor(d, 0);
delete d; delete d;
} }
// Scan the stream-specific loop: // Scan the stream-specific loop:
@ -341,11 +342,12 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
int NumDpids = 0; int NumDpids = 0;
int NumSpids = 0; int NumSpids = 0;
for (SI::Loop::Iterator it; pmt.streamLoop.getNext(stream, it); ) { for (SI::Loop::Iterator it; pmt.streamLoop.getNext(stream, it); ) {
int esPid = stream.getPid();
switch (stream.getStreamType()) { switch (stream.getStreamType()) {
case 1: // STREAMTYPE_11172_VIDEO case 1: // STREAMTYPE_11172_VIDEO
case 2: // STREAMTYPE_13818_VIDEO case 2: // STREAMTYPE_13818_VIDEO
case 0x1B: // MPEG4 case 0x1B: // MPEG4
Vpid = stream.getPid(); Vpid = esPid;
Ppid = pmt.getPCRPid(); Ppid = pmt.getPCRPid();
Vtype = stream.getStreamType(); Vtype = stream.getStreamType();
break; break;
@ -353,7 +355,7 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
case 4: // STREAMTYPE_13818_AUDIO case 4: // STREAMTYPE_13818_AUDIO
{ {
if (NumApids < MAXAPIDS) { if (NumApids < MAXAPIDS) {
Apids[NumApids] = stream.getPid(); Apids[NumApids] = esPid;
SI::Descriptor *d; SI::Descriptor *d;
for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) { for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
switch (d->getDescriptorTag()) { switch (d->getDescriptorTag()) {
@ -392,11 +394,11 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) { for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
switch (d->getDescriptorTag()) { switch (d->getDescriptorTag()) {
case SI::AC3DescriptorTag: case SI::AC3DescriptorTag:
dpid = stream.getPid(); dpid = esPid;
break; break;
case SI::SubtitlingDescriptorTag: case SI::SubtitlingDescriptorTag:
if (NumSpids < MAXSPIDS) { if (NumSpids < MAXSPIDS) {
Spids[NumSpids] = stream.getPid(); Spids[NumSpids] = esPid;
SI::SubtitlingDescriptor *sd = (SI::SubtitlingDescriptor *)d; SI::SubtitlingDescriptor *sd = (SI::SubtitlingDescriptor *)d;
SI::SubtitlingDescriptor::Subtitling sub; SI::SubtitlingDescriptor::Subtitling sub;
char *s = SLangs[NumSpids]; char *s = SLangs[NumSpids];
@ -415,7 +417,7 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
} }
break; break;
case SI::TeletextDescriptorTag: case SI::TeletextDescriptorTag:
Tpid = stream.getPid(); Tpid = esPid;
break; break;
case SI::ISO639LanguageDescriptorTag: { case SI::ISO639LanguageDescriptorTag: {
SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d; SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d;
@ -438,7 +440,7 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
//default: printf("PID: %5d %5d %2d %3d %3d\n", pmt.getServiceId(), stream.getPid(), stream.getStreamType(), pmt.getVersionNumber(), Channel->Number());//XXX //default: printf("PID: %5d %5d %2d %3d %3d\n", pmt.getServiceId(), stream.getPid(), stream.getStreamType(), pmt.getVersionNumber(), Channel->Number());//XXX
} }
for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)stream.streamDescriptors.getNext(it, SI::CaDescriptorTag)); ) { for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)stream.streamDescriptors.getNext(it, SI::CaDescriptorTag)); ) {
CaDescriptors->AddCaDescriptor(d, true); CaDescriptors->AddCaDescriptor(d, esPid);
delete d; delete d;
} }
} }

4
pat.h
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: pat.h 1.7 2007/01/07 14:42:11 kls Exp $ * $Id: pat.h 2.1 2009/08/15 22:16:00 kls Exp $
*/ */
#ifndef __PAT_H #ifndef __PAT_H
@ -32,7 +32,7 @@ public:
void Trigger(void); void Trigger(void);
}; };
int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag); int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
///< Gets all CA descriptors for a given channel. ///< Gets all CA descriptors for a given channel.
///< Copies all available CA descriptors for the given Source, Transponder and ServiceId ///< Copies all available CA descriptors for the given Source, Transponder and ServiceId
///< into the provided buffer at Data (at most BufSize bytes). Only those CA descriptors ///< into the provided buffer at Data (at most BufSize bytes). Only those CA descriptors