MythTV  master
dvbcam.cpp
Go to the documentation of this file.
1 /*
2  * Class DVBCam
3  *
4  * Original Project
5  * MythTV http://www.mythtv.org
6  *
7  * Author(s):
8  * Jesper Sorensen
9  * - Changed to work with Taylor Jacob's DVB rewrite
10  * Kenneth Aafloy
11  * - General Implementation
12  *
13  * Description:
14  * This Class has been developed from bits n' pieces of other
15  * projects.
16  *
17  *
18  *
19  * This program is free software; you can redistribute it and/or
20  * modify it under the terms of the GNU General Public License
21  * as published by the Free Software Foundation; either version 2
22  * of the License, or (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program; if not, write to the Free Software
31  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
32  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
33  *
34  */
35 
36 // C++
37 #include <cstdio>
38 #include <cstdlib>
39 
40 // C
41 #include <fcntl.h>
42 #include <sys/ioctl.h>
43 #include <sys/poll.h>
44 #include <linux/dvb/ca.h>
45 
46 // Qt
47 #include <QString>
48 #include <QList>
49 #include <QMap>
50 
51 // MythTV
52 #include "dvbci.h"
53 #include "recorderbase.h"
54 #include "cardutil.h"
55 #include "dvbcam.h"
56 #include "mthread.h"
57 #include "dvbchannel.h"
58 #include "dvbrecorder.h"
59 #include "mythlogging.h"
60 
61 #define LOC QString("DVBCam(%1): ").arg(m_device)
62 
63 DVBCam::DVBCam(QString device)
64  : m_device(std::move(device))
65 {
66  QString dvbdev = CardUtil::GetDeviceName(DVB_DEV_CA, m_device);
67  QByteArray dev = dvbdev.toLatin1();
68  int cafd = open(dev.constData(), O_RDWR);
69  if (cafd >= 0)
70  {
71  ca_caps_t caps;
72  // slot_num will be uninitialised if ioctl fails
73  if (ioctl(cafd, CA_GET_CAP, &caps) >= 0)
74  m_numslots = caps.slot_num;
75  else
76  LOG(VB_GENERAL, LOG_ERR, LOC + "ioctl CA_GET_CAP failed: " + ENO);
77 
78  close(cafd);
79  }
80 }
81 
83 {
84  Stop();
85 }
86 
87 bool DVBCam::Start(void)
88 {
89  if (m_numslots == 0)
90  return false;
91 
92  m_havePmt = false;
93  m_pmtSent = false;
94  m_pmtUpdated = false;
95  m_pmtAdded = false;
96 
97  QString dvbdev = CardUtil::GetDeviceName(DVB_DEV_CA, m_device);
98  QByteArray dev = dvbdev.toLatin1();
99  m_ciHandler = cCiHandler::CreateCiHandler(dev.constData());
100  if (!m_ciHandler)
101  {
102  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to initialize CI handler");
103  return false;
104  }
105 
106  QMutexLocker locker(&m_ciHandlerLock);
107  m_ciHandlerDoRun = true;
108  m_ciHandlerThread = new MThread("DVBCam", this);
111  m_ciHandlerWait.wait(locker.mutex(), 1000);
112 
113  if (m_ciHandlerRunning)
114  LOG(VB_DVBCAM, LOG_INFO, LOC + "CI handler successfully initialized!");
115 
116  return m_ciHandlerRunning;
117 }
118 
119 bool DVBCam::Stop(void)
120 {
121  {
122  QMutexLocker locker(&m_ciHandlerLock);
123  if (m_ciHandlerRunning)
124  {
125  m_ciHandlerDoRun = false;
126  locker.unlock();
128  locker.relock();
129  delete m_ciHandlerThread;
130  m_ciHandlerThread = nullptr;
131  }
132 
133  if (m_ciHandler)
134  {
135  delete m_ciHandler;
136  m_ciHandler = nullptr;
137  }
138  }
139 
140  QMutexLocker locker(&m_pmtLock);
141  pmt_list_t::iterator it;
142 
143  for (it = m_pmtList.begin(); it != m_pmtList.end(); ++it)
144  delete *it;
145  m_pmtList.clear();
146 
147  for (it = m_pmtAddList.begin(); it != m_pmtAddList.end(); ++it)
148  delete *it;
149  m_pmtAddList.clear();
150 
151  return true;
152 }
153 
155 {
157  if (enq != nullptr)
158  {
159  if (enq->Text() != nullptr)
160  LOG(VB_DVBCAM, LOG_INFO, LOC + QString("CAM: Received message: %1")
161  .arg(enq->Text()));
162  delete enq;
163  }
164 
166  if (menu != nullptr)
167  {
168  if (menu->TitleText() != nullptr)
169  LOG(VB_DVBCAM, LOG_INFO, LOC + QString("CAM: Menu Title: %1")
170  .arg(menu->TitleText()));
171  if (menu->SubTitleText() != nullptr)
172  LOG(VB_DVBCAM, LOG_INFO, LOC + QString("CAM: Menu SubTitle: %1")
173  .arg(menu->SubTitleText()));
174  if (menu->BottomText() != nullptr)
175  LOG(VB_DVBCAM, LOG_INFO, LOC + QString("CAM: Menu BottomText: %1")
176  .arg(menu->BottomText()));
177 
178  for (int i=0; i<menu->NumEntries(); i++)
179  {
180  if (menu->Entry(i) != nullptr)
181  LOG(VB_DVBCAM, LOG_INFO, LOC + QString("CAM: Menu Entry: %1")
182  .arg(menu->Entry(i)));
183  }
184 
185  if (menu->Selectable())
186  {
187  LOG(VB_CHANNEL, LOG_INFO, LOC + "CAM: Menu is selectable");
188  }
189 
190  if (menu->NumEntries() > 0)
191  {
192  LOG(VB_DVBCAM, LOG_INFO, LOC + "CAM: Selecting first entry");
193  menu->Select(0);
194  }
195  else
196  {
197  LOG(VB_DVBCAM, LOG_INFO, LOC + "CAM: Cancelling menu");
198  }
199 
200  delete menu;
201  }
202 }
203 
204 // Remove duplicate service IDs because the CAM needs to be setup only
205 // once for each service even if the service is recorded twice.
206 // This can happen with overlapping recordings on the same channel.
208 {
209  QList<uint> unique_sids;
210  pmt_list_t::iterator it;
211 
212  // Remove duplicates in m_pmtList
213  for (it = m_pmtList.begin(); it != m_pmtList.end(); )
214  {
215  const ChannelBase *chan = it.key();
216  uint inputId = chan->GetInputID();
217  const ProgramMapTable *pmt = (*it);
218  uint serviceId = pmt->ProgramNumber();
219  if (unique_sids.contains(serviceId))
220  {
221  it = m_pmtList.erase(it);
222  LOG(VB_DVBCAM, LOG_DEBUG, LOC + QString("Service [%1]%2 duplicate, removed from pmtList")
223  .arg(inputId).arg(serviceId));
224  }
225  else
226  {
227  unique_sids.append(serviceId);
228  ++it;
229  LOG(VB_DVBCAM, LOG_DEBUG, LOC + QString("Service [%1]%2 stays in pmtList")
230  .arg(inputId).arg(serviceId));
231  }
232  }
233 
234  // Remove duplicates in m_pmtAddList
235  for (it = m_pmtAddList.begin(); it != m_pmtAddList.end(); )
236  {
237  const ChannelBase *chan = it.key();
238  uint inputId = chan->GetInputID();
239  const ProgramMapTable *pmt = (*it);
240  uint serviceId = pmt->ProgramNumber();
241  if (unique_sids.contains(serviceId))
242  {
243  it = m_pmtAddList.erase(it);
244  LOG(VB_DVBCAM, LOG_DEBUG, LOC + QString("Service [%1]%2 duplicate, removed from pmtAddList")
245  .arg(inputId).arg(serviceId));
246  }
247  else
248  {
249  unique_sids.append(serviceId);
250  ++it;
251  LOG(VB_DVBCAM, LOG_DEBUG, LOC + QString("Service [%1]%2 stays in pmtAddList")
252  .arg(inputId).arg(serviceId));
253  }
254  }
255 }
256 
257 
259 {
260  LOG(VB_DVBCAM, LOG_INFO, LOC + "CiHandler needs CA_PMT");
261  QMutexLocker locker(&m_pmtLock);
262 
264 
265  if (m_pmtSent && m_pmtAdded && !m_pmtUpdated)
266  {
267  // Send added PMT
268  while (!m_pmtAddList.empty())
269  {
270  pmt_list_t::iterator it = m_pmtAddList.begin();
271  const ChannelBase *chan = it.key();
272  ProgramMapTable *pmt = (*it);
273  m_pmtList[chan] = pmt;
274  m_pmtAddList.erase(it);
275  SendPMT(*pmt, CPLM_ADD);
276  }
277 
278  m_pmtUpdated = false;
279  m_pmtAdded = false;
280  return;
281  }
282 
283  // Grab any added PMT
284  while (!m_pmtAddList.empty())
285  {
286  pmt_list_t::iterator it = m_pmtAddList.begin();
287  const ChannelBase *chan = it.key();
288  ProgramMapTable *pmt = (*it);
289  m_pmtList[chan] = pmt;
290  m_pmtAddList.erase(it);
291  }
292 
293  uint length = m_pmtList.size();
294  uint count = 0;
295 
296  for (auto *pmt : qAsConst(m_pmtList))
297  {
298  uint cplm = (count == 0) ? CPLM_FIRST : CPLM_MORE;
299  cplm = (count + 1 == length) ? CPLM_LAST : cplm;
300  cplm = (length == 1) ? CPLM_ONLY : cplm;
301 
302  SendPMT(*pmt, cplm);
303 
304  count++;
305  }
306 
307  m_pmtSent = true;
308  m_pmtUpdated = false;
309  m_pmtAdded = false;
310 }
311 
312 void DVBCam::run(void)
313 {
314  LOG(VB_DVBCAM, LOG_INFO, LOC + "CI handler thread running");
315 
316  QMutexLocker locker(&m_ciHandlerLock);
317  m_ciHandlerRunning = true;
318 
319  while (m_ciHandlerDoRun)
320  {
321  locker.unlock();
322  if (m_ciHandler->Process())
323  {
324  if (m_ciHandler->HasUserIO())
325  HandleUserIO();
326 
327  bool handle_pmt = m_pmtSent && (m_pmtUpdated || m_pmtAdded);
328  handle_pmt |= m_havePmt && m_ciHandler->NeedCaPmt();
329 
330  if (handle_pmt)
331  HandlePMT();
332  }
333  locker.relock();
334  m_ciHandlerWait.wait(locker.mutex(), 10);
335  }
336 
337  m_ciHandlerRunning = false;
338  LOG(VB_DVBCAM, LOG_INFO, LOC + "CiHandler thread stopped");
339 }
340 
341 void DVBCam::SetPMT(const ChannelBase *chan, const ProgramMapTable *pmt)
342 {
343  QMutexLocker locker(&m_pmtLock);
344 
345  pmt_list_t::iterator it = m_pmtList.find(chan);
346  pmt_list_t::iterator it2 = m_pmtAddList.find(chan);
347  if (!pmt && (it != m_pmtList.end()))
348  {
349  delete *it;
350  m_pmtList.erase(it);
351  m_pmtUpdated = true;
352  }
353  else if (!pmt && (it2 != m_pmtAddList.end()))
354  {
355  delete *it2;
356  m_pmtAddList.erase(it2);
357  m_pmtAdded = !m_pmtAddList.empty();
358  }
359  else if (pmt && (m_pmtList.empty() || (it != m_pmtList.end())))
360  {
361  if (it != m_pmtList.end())
362  delete *it;
363  m_pmtList[chan] = new ProgramMapTable(*pmt);
364  m_havePmt = true;
365  m_pmtUpdated = true;
366  }
367  else if (pmt && (it == m_pmtList.end()))
368  {
369  m_pmtAddList[chan] = new ProgramMapTable(*pmt);
370  m_pmtAdded = true;
371  }
372 }
373 
374 void DVBCam::SetTimeOffset(double offset_in_seconds)
375 {
376  QMutexLocker locker(&m_ciHandlerLock);
377  if (m_ciHandler)
378  m_ciHandler->SetTimeOffset(offset_in_seconds);
379 }
380 
381 static std::array<const std::string,6> cplm_info
382 {
383  "CPLM_MORE",
384  "CPLM_FIRST",
385  "CPLM_LAST",
386  "CPLM_ONLY",
387  "CPLM_ADD",
388  "CPLM_UPDATE"
389 };
390 
391 cCiCaPmt CreateCAPMT(const ProgramMapTable& /*pmt*/, const dvbca_vector &/*casids*/, uint /*cplm*/);
392 
393 /*
394  * Send a CA_PMT object to the CAM (see EN50221, section 8.4.3.4)
395  */
396 void DVBCam::SendPMT(const ProgramMapTable &pmt, uint cplm)
397 {
398  bool success = false;
399 
400  for (uint s = 0; s < (uint)m_ciHandler->NumSlots(); s++)
401  {
403 
404  if (casids.empty())
405  {
406  LOG(success ? VB_DVBCAM : VB_GENERAL, LOG_ERR,
407  LOC + "CAM supports no CA systems! " +
408  QString("(Slot #%1)").arg(s));
409  continue;
410  }
411 
412  LOG(VB_DVBCAM, LOG_INFO, LOC +
413  QString("Creating CA_PMT, ServiceID = %1")
414  .arg(pmt.ProgramNumber()));
415 
416  cCiCaPmt capmt = CreateCAPMT(pmt, casids, cplm);
417 
418  LOG(VB_DVBCAM, LOG_INFO, LOC +
419  QString("Sending CA_PMT with %1 to CI slot #%2")
420  .arg(QString::fromStdString(cplm_info[cplm])).arg(s));
421 
422  if (!m_ciHandler->SetCaPmt(capmt, s))
423  {
424  LOG(success ? VB_DVBCAM : VB_GENERAL, LOG_ERR,
425  LOC + "CA_PMT send failed!");
426  }
427  else
428  {
429  success = true;
430  }
431  }
432 }
433 
434 static void process_desc(cCiCaPmt &capmt,
435  const dvbca_vector &casids,
436  const desc_list_t &desc)
437 {
438  desc_list_t::const_iterator it;
439  for (it = desc.begin(); it != desc.end(); ++it)
440  {
442  for (auto id : casids)
443  {
444  if (!cad.IsValid() || cad.SystemID() != id)
445  continue;
446 
447  LOG(VB_DVBCAM, LOG_INFO, QString("DVBCam: Adding CA descriptor: "
448  "CASID(0x%2), ECM PID(0x%3)")
449  .arg(cad.SystemID(),0,16).arg(cad.PID(),0,16));
450 
451  capmt.AddCaDescriptor(cad.SystemID(), cad.PID(),
452  cad.DataSize(), cad.Data());
453  }
454  }
455 
456 }
457 
459  const dvbca_vector &casids,
460  uint cplm)
461 {
462  cCiCaPmt capmt(pmt.ProgramNumber(), cplm);
463 
464  // Add CA descriptors for the service
466  pmt.ProgramInfo(), pmt.ProgramInfoLength(),
468 
469  process_desc(capmt, casids, gdesc);
470 
471  // Add elementary streams + CA descriptors
472  for (uint i = 0; i < pmt.StreamCount(); i++)
473  {
474  LOG(VB_DVBCAM, LOG_INFO,
475  QString("DVBCam: Adding elementary stream: %1, pid(0x%2)")
476  .arg(pmt.StreamDescription(i, "dvb"))
477  .arg(pmt.StreamPID(i),0,16));
478 
479  capmt.AddElementaryStream(pmt.StreamType(i), pmt.StreamPID(i));
480 
482  pmt.StreamInfo(i), pmt.StreamInfoLength(i),
484 
485  process_desc(capmt, casids, desc);
486  }
487  return capmt;
488 }
ProgramMapTable::ProgramInfo
const unsigned char * ProgramInfo(void) const
Definition: mpegtables.h:735
dvbci.h
DVBCam::m_numslots
int m_numslots
Definition: dvbcam.h:47
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:286
ENO
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:72
cCiCaPmt::AddCaDescriptor
void AddCaDescriptor(int ca_system_id, int ca_pid, int data_len, const uint8_t *data)
Definition: dvbci.cpp:1522
dvbcam.h
ProgramMapTable::StreamCount
uint StreamCount(void) const
Definition: mpegtables.h:750
recorderbase.h
cCiHandler::SetCaPmt
virtual bool SetCaPmt(cCiCaPmt &CaPmt, int Slot)=0
dvbca_vector
std::vector< uint16_t > dvbca_vector
Definition: dvbci.h:47
MThread::wait
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:303
ProgramMapTable::StreamInfo
const unsigned char * StreamInfo(uint i) const
Definition: mpegtables.h:747
ProgramMapTable
A PMT table maps a program described in the ProgramAssociationTable to various PID's which describe t...
Definition: mpegtables.h:692
cCiHandler::GetEnquiry
virtual cCiEnquiry * GetEnquiry(void)=0
cCiEnquiry::Text
const char * Text(void)
Definition: dvbci.h:110
DVBCam::Stop
bool Stop(void)
Definition: dvbcam.cpp:119
arg
arg(title).arg(filename).arg(doDelete))
DVBCam::m_pmtList
pmt_list_t m_pmtList
Definition: dvbcam.h:57
DVBCam::HandleUserIO
void HandleUserIO(void)
Definition: dvbcam.cpp:154
cCiCaPmt
Definition: dvbci.h:126
ProgramMapTable::ProgramNumber
uint ProgramNumber(void) const
Definition: mpegtables.h:729
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
DVBCam::m_pmtUpdated
bool m_pmtUpdated
Definition: dvbcam.h:61
DVB_DEV_CA
@ DVB_DEV_CA
Definition: cardutil.h:32
cplm_info
static std::array< const std::string, 6 > cplm_info
Definition: dvbcam.cpp:382
cCiHandler::Process
virtual bool Process(void)=0
ConditionalAccessDescriptor::DataSize
uint DataSize(void) const
Definition: mpegdescriptors.h:483
menu
static MythThemedMenu * menu
Definition: mythtv/programs/mythtv-setup/main.cpp:53
dvbchannel.h
close
#define close
Definition: compat.h:17
CPLM_FIRST
#define CPLM_FIRST
Definition: dvbci.h:120
DVBCam::SetTimeOffset
void SetTimeOffset(double offset_in_seconds)
Definition: dvbcam.cpp:374
process_desc
static void process_desc(cCiCaPmt &capmt, const dvbca_vector &casids, const desc_list_t &desc)
Definition: dvbcam.cpp:434
dvbrecorder.h
MPEGDescriptor::IsValid
bool IsValid(void) const
Definition: mpegdescriptors.h:342
cCiHandler::SetTimeOffset
virtual void SetTimeOffset(double)
Definition: dvbci.h:159
DVBCam::~DVBCam
~DVBCam() override
Definition: dvbcam.cpp:82
ProgramMapTable::StreamDescription
QString StreamDescription(uint i, const QString &sistandard) const
Returns a better (and more expensive) string representation of type at stream index i than StreamType...
Definition: mpegtables.cpp:1160
ConditionalAccessDescriptor::Data
const unsigned char * Data(void) const
Definition: mpegdescriptors.h:484
DVBCam::m_pmtAddList
pmt_list_t m_pmtAddList
Definition: dvbcam.h:58
mythlogging.h
ChannelBase
Abstract class providing a generic interface to tuning hardware.
Definition: channelbase.h:31
CPLM_MORE
#define CPLM_MORE
Definition: dvbci.h:119
cCiHandler::NumSlots
virtual int NumSlots(void)=0
ConditionalAccessDescriptor::SystemID
uint SystemID(void) const
Definition: mpegdescriptors.h:481
cCiHandler::NeedCaPmt
virtual bool NeedCaPmt(void)=0
ProgramMapTable::StreamType
uint StreamType(uint i) const
Definition: mpegtables.h:738
DVBCam::run
void run(void) override
Definition: dvbcam.cpp:312
DVBCam::Start
bool Start(void)
Definition: dvbcam.cpp:87
DVBCam::m_havePmt
bool m_havePmt
Definition: dvbcam.h:59
ConditionalAccessDescriptor
Definition: mpegdescriptors.h:475
desc_list_t
std::vector< const unsigned char * > desc_list_t
Definition: mpegdescriptors.h:18
DVBCam::m_ciHandlerLock
QMutex m_ciHandlerLock
Definition: dvbcam.h:49
MPEGDescriptor::ParseOnlyInclude
static desc_list_t ParseOnlyInclude(const unsigned char *data, uint len, int excluded_descid)
Definition: mpegdescriptors.cpp:57
DVBCam::m_ciHandlerWait
QWaitCondition m_ciHandlerWait
Definition: dvbcam.h:50
cCiHandler::HasUserIO
virtual bool HasUserIO(void)=0
LOC
#define LOC
Definition: dvbcam.cpp:61
DVBCam::m_pmtSent
bool m_pmtSent
Definition: dvbcam.h:60
uint
unsigned int uint
Definition: compat.h:140
CreateCAPMT
cCiCaPmt CreateCAPMT(const ProgramMapTable &, const dvbca_vector &, uint)
Definition: dvbcam.cpp:458
DVBCam::m_device
QString m_device
Definition: dvbcam.h:46
CardUtil::GetDeviceName
static QString GetDeviceName(dvb_dev_type_t type, const QString &device)
Definition: cardutil.cpp:2770
ProgramMapTable::ProgramInfoLength
uint ProgramInfoLength(void) const
Definition: mpegtables.h:732
DVBCam::RemoveDuplicateServices
void RemoveDuplicateServices(void)
Definition: dvbcam.cpp:207
DVBCam::m_ciHandlerDoRun
bool m_ciHandlerDoRun
Definition: dvbcam.h:51
DVBCam::SendPMT
void SendPMT(const ProgramMapTable &pmt, uint cplm)
Definition: dvbcam.cpp:396
cardutil.h
std
Definition: mythchrono.h:23
DVBCam::m_ciHandlerThread
MThread * m_ciHandlerThread
Definition: dvbcam.h:54
MThread
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:49
DVBCam::SetPMT
void SetPMT(const ChannelBase *chan, const ProgramMapTable *pmt)
Definition: dvbcam.cpp:341
CPLM_ADD
#define CPLM_ADD
Definition: dvbci.h:123
mthread.h
ChannelBase::GetInputID
virtual int GetInputID(void) const
Definition: channelbase.h:67
DescriptorID::conditional_access
@ conditional_access
Definition: mpegdescriptors.h:33
cCiHandler::CreateCiHandler
static cCiHandler * CreateCiHandler(const char *FileName)
Definition: dvbci.cpp:1579
CPLM_ONLY
#define CPLM_ONLY
Definition: dvbci.h:122
cCiMenu
Definition: dvbci.h:75
cCiHandler::GetMenu
virtual cCiMenu * GetMenu(void)=0
cCiEnquiry
Definition: dvbci.h:100
DVBCam::HandlePMT
void HandlePMT(void)
Definition: dvbcam.cpp:258
DVBCam::DVBCam
DVBCam(QString device)
Definition: dvbcam.cpp:63
cCiHandler::GetCaSystemIds
virtual dvbca_vector GetCaSystemIds(int Slot)=0
DVBCam::m_pmtAdded
bool m_pmtAdded
Definition: dvbcam.h:62
ProgramMapTable::StreamInfoLength
uint StreamInfoLength(uint i) const
Definition: mpegtables.h:744
ProgramMapTable::StreamPID
uint StreamPID(uint i) const
Definition: mpegtables.h:741
CPLM_LAST
#define CPLM_LAST
Definition: dvbci.h:121
DVBCam::m_ciHandlerRunning
bool m_ciHandlerRunning
Definition: dvbcam.h:52
ConditionalAccessDescriptor::PID
uint PID(void) const
Definition: mpegdescriptors.h:482
DVBCam::m_pmtLock
QMutex m_pmtLock
Definition: dvbcam.h:56
cCiCaPmt::AddElementaryStream
void AddElementaryStream(int type, int pid)
Definition: dvbci.cpp:1487
DVBCam::m_ciHandler
cCiHandler * m_ciHandler
Definition: dvbcam.h:53