mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Added receiving Ca pids to cCamSlot
This commit is contained in:
parent
b95b85fee4
commit
566c6fa464
7
HISTORY
7
HISTORY
@ -8032,7 +8032,7 @@ Video Disk Recorder Revision History
|
||||
the last replayed recording (if any) by pressing Ok repeatedly in the Recordings
|
||||
menu.
|
||||
|
||||
2013-12-29: Version 2.1.3
|
||||
2014-01-01: Version 2.1.3
|
||||
|
||||
- Changed the return value of cPositioner::HorizonLongitude() to 0 in case the
|
||||
latitude of the antenna location is beyond +/-81 degrees.
|
||||
@ -8091,7 +8091,10 @@ Video Disk Recorder Revision History
|
||||
Skyttä).
|
||||
- The new function cCamSlot::Decrypt() can be used by derived classes to implement a
|
||||
CAM slot that can be freely assigned to any device, without being directly inserted
|
||||
into the full TS data stream in hardware.
|
||||
into the full TS data stream in hardware. A derived class that implements Decrypt()
|
||||
will also need to set the new parameter ReceiveCaPids in the call to the cCamSlot
|
||||
base class constructor to true, in order to receive the CA pid TS packets that
|
||||
contain data necessary for decrypting.
|
||||
- Many member functions of cCamSlot have been made virtual to allow for easier
|
||||
implementation of derived classes.
|
||||
- cTSBuffer now provides the number of available bytes in its Get() function.
|
||||
|
36
ci.c
36
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 3.2 2013/12/29 15:51:08 kls Exp $
|
||||
* $Id: ci.c 3.3 2014/01/01 12:33:27 kls Exp $
|
||||
*/
|
||||
|
||||
#include "ci.h"
|
||||
@ -19,6 +19,7 @@
|
||||
#include <unistd.h>
|
||||
#include "device.h"
|
||||
#include "pat.h"
|
||||
#include "receiver.h"
|
||||
#include "tools.h"
|
||||
|
||||
// Set these to 'true' for debug output:
|
||||
@ -102,6 +103,16 @@ static char *GetString(int &Length, const uint8_t **Data)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// --- cCaPidReceiver --------------------------------------------------------
|
||||
|
||||
// A dummy receiver, just used to make the device receive the CA pids.
|
||||
|
||||
class cCaPidReceiver : public cReceiver {
|
||||
public:
|
||||
virtual ~cCaPidReceiver() { Detach(); }
|
||||
virtual void Receive(uchar *Data, int Length) {}
|
||||
};
|
||||
|
||||
// --- cTPDU -----------------------------------------------------------------
|
||||
|
||||
#define MAX_TPDU_SIZE 2048
|
||||
@ -570,7 +581,7 @@ bool cCiApplicationInformation::EnterMenu(void)
|
||||
#define CPCI_QUERY 0x03
|
||||
#define CPCI_NOT_SELECTED 0x04
|
||||
|
||||
class cCiCaPmt : public cListObject {
|
||||
class cCiCaPmt {
|
||||
friend class cCiConditionalAccessSupport;
|
||||
private:
|
||||
uint8_t cmdId;
|
||||
@ -1553,9 +1564,10 @@ cCamSlots CamSlots;
|
||||
#define MODULE_CHECK_INTERVAL 500 // ms
|
||||
#define MODULE_RESET_TIMEOUT 2 // s
|
||||
|
||||
cCamSlot::cCamSlot(cCiAdapter *CiAdapter)
|
||||
cCamSlot::cCamSlot(cCiAdapter *CiAdapter, bool ReceiveCaPids)
|
||||
{
|
||||
ciAdapter = CiAdapter;
|
||||
caPidReceiver = ReceiveCaPids ? new cCaPidReceiver : NULL;
|
||||
slotIndex = -1;
|
||||
lastModuleStatus = msReset; // avoids initial reset log message
|
||||
resetTime = 0;
|
||||
@ -1572,6 +1584,7 @@ cCamSlot::cCamSlot(cCiAdapter *CiAdapter)
|
||||
|
||||
cCamSlot::~cCamSlot()
|
||||
{
|
||||
delete caPidReceiver;
|
||||
CamSlots.Del(this, false);
|
||||
DeleteAllConnections();
|
||||
}
|
||||
@ -1802,6 +1815,10 @@ void cCamSlot::SendCaPmt(uint8_t CmdId)
|
||||
const int *CaSystemIds = cas->GetCaSystemIds();
|
||||
if (CaSystemIds && *CaSystemIds) {
|
||||
if (caProgramList.Count()) {
|
||||
if (caPidReceiver && caPidReceiver->NumPids()) {
|
||||
if (cDevice *d = Device())
|
||||
d->Detach(caPidReceiver);
|
||||
}
|
||||
for (int Loop = 1; Loop <= 2; Loop++) {
|
||||
for (cCiCaProgramData *p = caProgramList.First(); p; p = caProgramList.Next(p)) {
|
||||
if (p->modified || resendPmt) {
|
||||
@ -1814,6 +1831,15 @@ void cCamSlot::SendCaPmt(uint8_t CmdId)
|
||||
}
|
||||
}
|
||||
if ((Loop == 1) != Active) { // first remove, then add
|
||||
if (caPidReceiver) {
|
||||
int CaPids[MAXRECEIVEPIDS + 1];
|
||||
if (GetCaPids(source, transponder, p->programNumber, CaSystemIds, MAXRECEIVEPIDS + 1, CaPids) > 0) {
|
||||
if (Loop == 1)
|
||||
caPidReceiver->DelPids(CaPids);
|
||||
else
|
||||
caPidReceiver->AddPids(CaPids);
|
||||
}
|
||||
}
|
||||
if (cas->RepliesToQuery())
|
||||
CaPmt.SetListManagement(Active ? CPLM_ADD : CPLM_UPDATE);
|
||||
if (Active || cas->RepliesToQuery())
|
||||
@ -1823,6 +1849,10 @@ void cCamSlot::SendCaPmt(uint8_t CmdId)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (caPidReceiver && caPidReceiver->NumPids()) {
|
||||
if (cDevice *d = Device())
|
||||
d->AttachReceiver(caPidReceiver);
|
||||
}
|
||||
resendPmt = false;
|
||||
}
|
||||
else {
|
||||
|
12
ci.h
12
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 3.1 2013/12/28 13:20:08 kls Exp $
|
||||
* $Id: ci.h 3.2 2014/01/01 12:13:04 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CI_H
|
||||
@ -121,6 +121,7 @@ class cTPDU;
|
||||
class cCiTransportConnection;
|
||||
class cCiSession;
|
||||
class cCiCaProgramData;
|
||||
class cReceiver;
|
||||
|
||||
class cCamSlot : public cListObject {
|
||||
friend class cCiAdapter;
|
||||
@ -129,6 +130,7 @@ private:
|
||||
cMutex mutex;
|
||||
cCondVar processed;
|
||||
cCiAdapter *ciAdapter;
|
||||
cReceiver *caPidReceiver;
|
||||
int slotIndex;
|
||||
int slotNumber;
|
||||
cCiTransportConnection *tc[MAX_CONNECTIONS_PER_CAM_SLOT + 1]; // connection numbering starts with 1
|
||||
@ -147,10 +149,13 @@ private:
|
||||
void Write(cTPDU *TPDU);
|
||||
cCiSession *GetSessionByResourceId(uint32_t ResourceId);
|
||||
public:
|
||||
cCamSlot(cCiAdapter *CiAdapter);
|
||||
cCamSlot(cCiAdapter *CiAdapter, bool ReceiveCaPids = false);
|
||||
///< Creates a new CAM slot for the given CiAdapter.
|
||||
///< The CiAdapter will take care of deleting the CAM slot,
|
||||
///< so the caller must not delete it!
|
||||
///< If ReceiveCaPids is true, the CAM slot will take care that the CA pids
|
||||
///< of the selected programmes will be included in the TS data stream that
|
||||
///< is presented to the Decrypt() function.
|
||||
virtual ~cCamSlot();
|
||||
bool Assign(cDevice *Device, bool Query = false);
|
||||
///< Assigns this CAM slot to the given Device, if this is possible.
|
||||
@ -243,6 +248,9 @@ public:
|
||||
///< Data pointing to the TS packet immediately following the previous
|
||||
///< one. However, it can not be assumed that a call to Decrypt() with
|
||||
///< a Data pointer of P will be followed by a call with P + TS_SIZE.
|
||||
///< A derived class that implements this function will also need
|
||||
///< to set the ReceiveCaPids parameter in the call to the base class
|
||||
///< constructor to true in order to receive the CA pid data.
|
||||
};
|
||||
|
||||
class cCamSlots : public cList<cCamSlot> {};
|
||||
|
6
device.c
6
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 3.5 2013/12/28 12:56:24 kls Exp $
|
||||
* $Id: device.c 3.6 2014/01/01 11:51:17 kls Exp $
|
||||
*/
|
||||
|
||||
#include "device.h"
|
||||
@ -1666,7 +1666,7 @@ bool cDevice::AttachReceiver(cReceiver *Receiver)
|
||||
Receiver->device = this;
|
||||
receiver[i] = Receiver;
|
||||
Unlock();
|
||||
if (camSlot) {
|
||||
if (camSlot && Receiver->priority > MINPRIORITY) { // priority check to avoid an infinite loop with the CAM slot's caPidReceiver
|
||||
camSlot->StartDecrypting();
|
||||
startScrambleDetection = time(NULL);
|
||||
}
|
||||
@ -1697,7 +1697,7 @@ void cDevice::Detach(cReceiver *Receiver)
|
||||
else if (receiver[i])
|
||||
receiversLeft = true;
|
||||
}
|
||||
if (camSlot)
|
||||
if (camSlot && Receiver->priority > MINPRIORITY) // priority check to avoid an infinite loop with the CAM slot's caPidReceiver
|
||||
camSlot->StartDecrypting();
|
||||
if (!receiversLeft)
|
||||
Cancel(-1);
|
||||
|
46
pat.c
46
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.19 2012/11/25 14:12:21 kls Exp $
|
||||
* $Id: pat.c 3.1 2014/01/01 12:02:39 kls Exp $
|
||||
*/
|
||||
|
||||
#include "pat.h"
|
||||
@ -21,6 +21,7 @@
|
||||
class cCaDescriptor : public cListObject {
|
||||
private:
|
||||
int caSystem;
|
||||
int caPid;
|
||||
int esPid;
|
||||
int length;
|
||||
uchar *data;
|
||||
@ -29,6 +30,7 @@ public:
|
||||
virtual ~cCaDescriptor();
|
||||
bool operator== (const cCaDescriptor &arg) const;
|
||||
int CaSystem(void) { return caSystem; }
|
||||
int CaPid(void) { return caPid; }
|
||||
int EsPid(void) { return esPid; }
|
||||
int Length(void) const { return length; }
|
||||
const uchar *Data(void) const { return data; }
|
||||
@ -37,6 +39,7 @@ public:
|
||||
cCaDescriptor::cCaDescriptor(int CaSystem, int CaPid, int EsPid, int Length, const uchar *Data)
|
||||
{
|
||||
caSystem = CaSystem;
|
||||
caPid = CaPid;
|
||||
esPid = EsPid;
|
||||
length = Length + 6;
|
||||
data = MALLOC(uchar, length);
|
||||
@ -79,6 +82,7 @@ public:
|
||||
bool Empty(void) { return caDescriptors.Count() == 0; }
|
||||
void AddCaDescriptor(SI::CaDescriptor *d, int EsPid);
|
||||
int GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
|
||||
int GetCaPids(const int *CaSystemIds, int BufSize, int *Pids);
|
||||
const int *CaIds(void) { return caIds; }
|
||||
};
|
||||
|
||||
@ -179,6 +183,30 @@ int cCaDescriptors::GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cCaDescriptors::GetCaPids(const int *CaSystemIds, int BufSize, int *Pids)
|
||||
{
|
||||
if (!CaSystemIds || !*CaSystemIds)
|
||||
return 0;
|
||||
if (BufSize > 0 && Pids) {
|
||||
int numPids = 0;
|
||||
for (cCaDescriptor *d = caDescriptors.First(); d; d = caDescriptors.Next(d)) {
|
||||
const int *caids = CaSystemIds;
|
||||
do {
|
||||
if (d->CaSystem() == *caids) {
|
||||
if (numPids + 1 < BufSize) {
|
||||
Pids[numPids++] = d->CaPid();
|
||||
Pids[numPids] = 0;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
} while (*++caids);
|
||||
}
|
||||
return numPids;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// --- cCaDescriptorHandler --------------------------------------------------
|
||||
|
||||
class cCaDescriptorHandler : public cList<cCaDescriptors> {
|
||||
@ -190,6 +218,7 @@ public:
|
||||
// 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, int EsPid);
|
||||
int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids);
|
||||
};
|
||||
|
||||
int cCaDescriptorHandler::AddCaDescriptors(cCaDescriptors *CaDescriptors)
|
||||
@ -220,6 +249,16 @@ int cCaDescriptorHandler::GetCaDescriptors(int Source, int Transponder, int Serv
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cCaDescriptorHandler::GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids)
|
||||
{
|
||||
cMutexLock MutexLock(&mutex);
|
||||
for (cCaDescriptors *ca = First(); ca; ca = Next(ca)) {
|
||||
if (ca->Is(Source, Transponder, ServiceId))
|
||||
return ca->GetCaPids(CaSystemIds, BufSize, Pids);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
cCaDescriptorHandler CaDescriptorHandler;
|
||||
|
||||
int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
|
||||
@ -227,6 +266,11 @@ int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSy
|
||||
return CaDescriptorHandler.GetCaDescriptors(Source, Transponder, ServiceId, CaSystemIds, BufSize, Data, EsPid);
|
||||
}
|
||||
|
||||
int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids)
|
||||
{
|
||||
return CaDescriptorHandler.GetCaPids(Source, Transponder, ServiceId, CaSystemIds, BufSize, Pids);
|
||||
}
|
||||
|
||||
// --- cPatFilter ------------------------------------------------------------
|
||||
|
||||
cPatFilter::cPatFilter(void)
|
||||
|
12
pat.h
12
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 2.3 2013/02/16 15:20:24 kls Exp $
|
||||
* $Id: pat.h 3.1 2013/12/30 11:32:40 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __PAT_H
|
||||
@ -39,7 +39,13 @@ int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSy
|
||||
///< are copied that match one of the given CA system IDs.
|
||||
///< Returns the number of bytes copied into Data (0 if no CA descriptors are
|
||||
///< available), or -1 if BufSize was too small to hold all CA descriptors.
|
||||
///< The return value tells whether these CA descriptors are to be used
|
||||
///< for the individual streams.
|
||||
|
||||
int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids);
|
||||
///< Gets all CA pids for a given channel.
|
||||
///< Copies all available CA pids from the CA descriptors for the given Source, Transponder and ServiceId
|
||||
///< into the provided buffer at Pids (at most BufSize - 1 entries, the list will be zero-terminated).
|
||||
///< Only the CA pids of those CA descriptors are copied that match one of the given CA system IDs.
|
||||
///< Returns the number of pids copied into Pids (0 if no CA descriptors are
|
||||
///< available), or -1 if BufSize was too small to hold all CA pids.
|
||||
|
||||
#endif //__PAT_H
|
||||
|
24
receiver.c
24
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 2.7 2012/06/02 13:20:38 kls Exp $
|
||||
* $Id: receiver.c 3.1 2014/01/01 12:03:00 kls Exp $
|
||||
*/
|
||||
|
||||
#include "receiver.h"
|
||||
@ -72,6 +72,28 @@ bool cReceiver::SetPids(const cChannel *Channel)
|
||||
return true;
|
||||
}
|
||||
|
||||
void cReceiver::DelPid(int Pid)
|
||||
{
|
||||
if (Pid) {
|
||||
for (int i = 0; i < numPids; i++) {
|
||||
if (pids[i] == Pid) {
|
||||
for ( ; i < numPids; i++) // we also copy the terminating 0!
|
||||
pids[i] = pids[i + 1];
|
||||
numPids--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cReceiver::DelPids(const int *Pids)
|
||||
{
|
||||
if (Pids) {
|
||||
while (*Pids)
|
||||
DelPid(*Pids++);
|
||||
}
|
||||
}
|
||||
|
||||
bool cReceiver::WantsPid(int Pid)
|
||||
{
|
||||
if (Pid) {
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: receiver.h 2.9 2012/09/02 09:27:20 kls Exp $
|
||||
* $Id: receiver.h 3.1 2014/01/01 11:45:09 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __RECEIVER_H
|
||||
@ -64,7 +64,13 @@ public:
|
||||
///< through ChannelID(). The ChannelID is necessary to allow the device
|
||||
///< that will be used for this receiver to detect and store whether the
|
||||
///< channel can be decrypted in case this is an encrypted channel.
|
||||
void DelPid(int Pid);
|
||||
///< Deletes the given Pid from the list of PIDs of this receiver.
|
||||
void DelPids(const int *Pids);
|
||||
///< Deletes the given zero terminated list of Pids from the list of PIDs of this
|
||||
///< receiver.
|
||||
tChannelID ChannelID(void) { return channelID; }
|
||||
int NumPids(void) const { return numPids; }
|
||||
bool IsAttached(void) { return device != NULL; }
|
||||
///< Returns true if this receiver is (still) attached to a device.
|
||||
///< A receiver may be automatically detached from its device in
|
||||
|
Loading…
Reference in New Issue
Block a user