From 6d060a98f20852ce8e4988dee65d65dc65091786 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sat, 15 Aug 2009 22:19:42 +0200 Subject: [PATCH] Fixed generating CaPmts in case audio and video are encrypted using different ECM pids --- HISTORY | 4 ++- ci.c | 31 ++++++++++++++------- pat.c | 84 +++++++++++++++++++++++++++++---------------------------- pat.h | 4 +-- 4 files changed, 70 insertions(+), 53 deletions(-) diff --git a/HISTORY b/HISTORY index b70ab127..f5f77674 100644 --- a/HISTORY +++ b/HISTORY @@ -6136,7 +6136,7 @@ Video Disk Recorder Revision History file in a wrong way. - 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 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. - Fixed handling file name length on VFAT systems in case they contain UTF-8 characters (thanks to Rolf Ahrenberg). +- Fixed generating CaPmts in case audio and video are encrypted using different + ECM pids. diff --git a/ci.c b/ci.c index 4d3df3e0..2b2994f4 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 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" @@ -551,6 +551,8 @@ bool cCiApplicationInformation::EnterMenu(void) // --- cCiCaPmt -------------------------------------------------------------- +#define MAXCASYSTEMIDS 64 + // Ca Pmt List Management: #define CPLM_MORE 0x00 @@ -574,9 +576,10 @@ private: int length; int esInfoLengthPos; uint8_t capmt[2048]; ///< XXX is there a specified maximum? - int caDescriptorsLength; - uint8_t caDescriptors[2048]; - bool streamFlag; + int source; + int transponder; + int programNumber; + int caSystemIds[MAXCASYSTEMIDS + 1]; // list is zero terminated! void AddCaDescriptors(int Length, const uint8_t *Data); public: 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) { 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; capmt[length++] = CPLM_ONLY; capmt[length++] = (ProgramNumber >> 8) & 0xFF; @@ -598,7 +611,7 @@ cCiCaPmt::cCiCaPmt(uint8_t CmdId, int Source, int Transponder, int ProgramNumber esInfoLengthPos = length; capmt[length++] = 0x00; // program_info_length H (at program level) capmt[length++] = 0x00; // program_info_length L - if (!streamFlag) + if (caDescriptorsLength > 0) AddCaDescriptors(caDescriptorsLength, caDescriptors); } @@ -610,6 +623,8 @@ void cCiCaPmt::SetListManagement(uint8_t ListManagement) void cCiCaPmt::AddPid(int Pid, uint8_t StreamType) { if (Pid) { + uint8_t caDescriptors[512]; + int caDescriptorsLength = GetCaDescriptors(source, transponder, programNumber, caSystemIds, sizeof(caDescriptors), caDescriptors, Pid); //XXX buffer overflow check??? capmt[length++] = StreamType; capmt[length++] = (Pid >> 8) & 0xFF; @@ -617,7 +632,7 @@ void cCiCaPmt::AddPid(int Pid, uint8_t StreamType) esInfoLengthPos = length; capmt[length++] = 0x00; // ES_info_length H (at ES level) capmt[length++] = 0x00; // ES_info_length L - if (streamFlag) + if (caDescriptorsLength > 0) AddCaDescriptors(caDescriptorsLength, caDescriptors); } } @@ -643,8 +658,6 @@ void cCiCaPmt::AddCaDescriptors(int Length, const uint8_t *Data) // --- cCiConditionalAccessSupport ------------------------------------------- -#define MAXCASYSTEMIDS 64 - // CA Enable Ids: #define CAEI_POSSIBLE 0x01 diff --git a/pat.c b/pat.c index 52857842..8136ef07 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 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" @@ -21,23 +21,23 @@ class cCaDescriptor : public cListObject { private: int caSystem; - bool stream; + int esPid; int length; uchar *data; 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(); bool operator== (const cCaDescriptor &arg) const; int CaSystem(void) { return caSystem; } - int Stream(void) { return stream; } + int EsPid(void) { return esPid; } int Length(void) const { return length; } 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; - stream = Stream; + esPid = EsPid; length = Length + 6; data = MALLOC(uchar, length); data[0] = SI::CaDescriptorTag; @@ -57,7 +57,7 @@ cCaDescriptor::~cCaDescriptor() 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 -------------------------------------------------------- @@ -77,8 +77,8 @@ public: bool Is(int Source, int Transponder, int ServiceId); bool Is(cCaDescriptors * CaDescriptors); bool Empty(void) { return caDescriptors.Count() == 0; } - void AddCaDescriptor(SI::CaDescriptor *d, bool Stream); - int GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag); + void AddCaDescriptor(SI::CaDescriptor *d, int EsPid); + int GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, int EsPid); 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)) { if (*ca == *nca) { delete nca; @@ -141,37 +141,39 @@ void cCaDescriptors::AddCaDescriptor(SI::CaDescriptor *d, bool Stream) #ifdef DEBUG_CA_DESCRIPTORS char buffer[1024]; 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++) q += sprintf(q, " %02X", nca->Data()[i]); dsyslog(buffer); #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) return 0; if (BufSize > 0 && Data) { int length = 0; - int IsStream = -1; for (cCaDescriptor *d = caDescriptors.First(); d; d = caDescriptors.Next(d)) { - const int *caids = CaSystemIds; - do { - if (d->CaSystem() == *caids) { - if (length + d->Length() <= BufSize) { - if (IsStream >= 0 && IsStream != d->Stream()) - dsyslog("CAM: different stream flag in CA descriptors"); - IsStream = d->Stream(); - memcpy(Data + length, d->Data(), d->Length()); - length += d->Length(); + if (EsPid < 0 || d->EsPid() == EsPid) { + const int *caids = CaSystemIds; + do { + if (d->CaSystem() == *caids) { + if (length + d->Length() <= BufSize) { + memcpy(Data + length, d->Data(), d->Length()); + length += d->Length(); + } + else + return -1; } - else - return -1; - } - } while (*++caids); + } while (*++caids); + } } - StreamFlag = IsStream == 1; return length; } return -1; @@ -187,7 +189,7 @@ public: // Returns 0 if this is an already known descriptor, // 1 if it is an all new descriptor with actual contents, // 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) @@ -208,22 +210,21 @@ int cCaDescriptorHandler::AddCaDescriptors(cCaDescriptors *CaDescriptors) 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); - StreamFlag = false; for (cCaDescriptors *ca = First(); ca; ca = Next(ca)) { if (ca->Is(Source, Transponder, ServiceId)) - return ca->GetCaDescriptors(CaSystemIds, BufSize, Data, StreamFlag); + return ca->GetCaDescriptors(CaSystemIds, BufSize, Data, EsPid); } return 0; } 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 ------------------------------------------------------------ @@ -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()); // Scan the common loop: for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)pmt.commonDescriptors.getNext(it, SI::CaDescriptorTag)); ) { - CaDescriptors->AddCaDescriptor(d, false); + CaDescriptors->AddCaDescriptor(d, 0); delete d; } // 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 NumSpids = 0; for (SI::Loop::Iterator it; pmt.streamLoop.getNext(stream, it); ) { + int esPid = stream.getPid(); switch (stream.getStreamType()) { case 1: // STREAMTYPE_11172_VIDEO case 2: // STREAMTYPE_13818_VIDEO case 0x1B: // MPEG4 - Vpid = stream.getPid(); + Vpid = esPid; Ppid = pmt.getPCRPid(); Vtype = stream.getStreamType(); 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 { if (NumApids < MAXAPIDS) { - Apids[NumApids] = stream.getPid(); + Apids[NumApids] = esPid; SI::Descriptor *d; for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) { 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)); ) { switch (d->getDescriptorTag()) { case SI::AC3DescriptorTag: - dpid = stream.getPid(); + dpid = esPid; break; case SI::SubtitlingDescriptorTag: if (NumSpids < MAXSPIDS) { - Spids[NumSpids] = stream.getPid(); + Spids[NumSpids] = esPid; SI::SubtitlingDescriptor *sd = (SI::SubtitlingDescriptor *)d; SI::SubtitlingDescriptor::Subtitling sub; char *s = SLangs[NumSpids]; @@ -415,7 +417,7 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length } break; case SI::TeletextDescriptorTag: - Tpid = stream.getPid(); + Tpid = esPid; break; case SI::ISO639LanguageDescriptorTag: { 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 } for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)stream.streamDescriptors.getNext(it, SI::CaDescriptorTag)); ) { - CaDescriptors->AddCaDescriptor(d, true); + CaDescriptors->AddCaDescriptor(d, esPid); delete d; } } diff --git a/pat.h b/pat.h index fe337367..b516b903 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 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 @@ -32,7 +32,7 @@ public: 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. ///< 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