MythTV  master
dtvchannel.cpp
Go to the documentation of this file.
1 
2 #include "dtvchannel.h"
3 
4 // MythTV headers
5 #include "libmythbase/mythdb.h"
7 
8 #include "cardutil.h"
9 #include "mpeg/mpegtables.h"
10 #include "tv_rec.h"
11 
12 #define LOC QString("DTVChan[%1](%2): ").arg(m_inputId).arg(GetDevice())
13 
14 QReadWriteLock DTVChannel::s_master_map_lock(QReadWriteLock::Recursive);
15 using MasterMap = QMap<QString,QList<DTVChannel*> >;
17 
19 {
20  if (m_genPAT)
21  {
22  delete m_genPAT;
23  m_genPAT = nullptr;
24  }
25 
26  if (m_genPMT)
27  {
28  delete m_genPMT;
29  m_genPMT = nullptr;
30  }
31 }
32 
33 void DTVChannel::SetDTVInfo(uint atsc_major, uint atsc_minor,
34  uint dvb_orig_netid,
35  uint mpeg_tsid, int mpeg_pnum)
36 {
37  QMutexLocker locker(&m_dtvinfoLock);
38  m_currentProgramNum = mpeg_pnum;
39  m_currentATSCMajorChannel = atsc_major;
40  m_currentATSCMinorChannel = atsc_minor;
41  m_currentTransportID = mpeg_tsid;
42  m_currentOriginalNetworkID = dvb_orig_netid;
43 }
44 
45 QString DTVChannel::GetSIStandard(void) const
46 {
47  QMutexLocker locker(&m_dtvinfoLock);
48  return m_sistandard;
49 }
50 
51 void DTVChannel::SetSIStandard(const QString &si_std)
52 {
53  QMutexLocker locker(&m_dtvinfoLock);
54  m_sistandard = si_std.toLower();
55 }
56 
57 QString DTVChannel::GetSuggestedTuningMode(bool is_live_tv) const
58 {
59  QString input = GetInputName();
60 
61  uint quickTuning = 0;
62  if (m_inputId && !input.isEmpty())
63  quickTuning = CardUtil::GetQuickTuning(m_inputId, input);
64 
65  bool useQuickTuning = ((quickTuning != 0U) && is_live_tv) || (quickTuning > 1);
66 
67  QMutexLocker locker(&m_dtvinfoLock);
68  if (!useQuickTuning && ((m_sistandard == "atsc") || (m_sistandard == "dvb")))
69  return m_sistandard;
70  return "mpeg";
71 }
72 
73 QString DTVChannel::GetTuningMode(void) const
74 {
75  QMutexLocker locker(&m_dtvinfoLock);
76  return m_tuningMode;
77 }
78 
79 std::vector<DTVTunerType> DTVChannel::GetTunerTypes(void) const
80 {
81  std::vector<DTVTunerType> tts;
83  tts.push_back(m_tunerType);
84  return tts;
85 }
86 
87 void DTVChannel::SetTuningMode(const QString &tuning_mode)
88 {
89  QMutexLocker locker(&m_dtvinfoLock);
90  m_tuningMode = tuning_mode.toLower();
91 }
92 
97 void DTVChannel::GetCachedPids(pid_cache_t &pid_cache) const
98 {
99  int chanid = GetChanID();
100  if (chanid > 0)
101  ChannelUtil::GetCachedPids(chanid, pid_cache);
102 }
103 
107 void DTVChannel::SaveCachedPids(const pid_cache_t &pid_cache) const
108 {
109  int chanid = GetChanID();
110  if (chanid > 0)
111  ChannelUtil::SaveCachedPids(chanid, pid_cache);
112 }
113 
114 void DTVChannel::RegisterForMaster(const QString &key)
115 {
116  s_master_map_lock.lockForWrite();
117  s_master_map[key].push_back(this);
118  s_master_map_lock.unlock();
119 }
120 
121 void DTVChannel::DeregisterForMaster(const QString &key)
122 {
123  s_master_map_lock.lockForWrite();
124  MasterMap::iterator mit = s_master_map.find(key);
125  if (mit == s_master_map.end())
126  mit = s_master_map.begin();
127  for (; mit != s_master_map.end(); ++mit)
128  {
129  (*mit).removeAll(this);
130  if (mit.key() == key)
131  break;
132  }
133  s_master_map_lock.unlock();
134 }
135 
137 {
138  s_master_map_lock.lockForRead();
139  MasterMap::iterator mit = s_master_map.find(key);
140  if (mit == s_master_map.end() || (*mit).empty())
141  {
142  s_master_map_lock.unlock();
143  return nullptr;
144  }
145  return (*mit).front();
146 }
147 
149 {
150  if (chan != nullptr)
151  {
152  chan = nullptr;
153  s_master_map_lock.unlock();
154  }
155 }
156 
157 bool DTVChannel::SetChannelByString(const QString &channum)
158 {
159  QString loc = LOC + QString("SetChannelByString(%1): ").arg(channum);
160  LOG(VB_CHANNEL, LOG_INFO, loc);
161 
162  ClearDTVInfo();
163 
164  if (!IsOpen() && !Open())
165  {
166  LOG(VB_GENERAL, LOG_ERR, loc + "Channel object "
167  "will not open, can not change channels.");
168 
169  return false;
170  }
171 
172  if (!m_inputId)
173  return false;
174 
175  uint mplexid_restriction = 0;
176  uint chanid_restriction = 0;
177  if (!IsInputAvailable(mplexid_restriction, chanid_restriction))
178  {
179  LOG(VB_GENERAL, LOG_INFO, loc +
180  QString("Requested channel '%1' is on input '%2' "
181  "which is in a busy input group")
182  .arg(channum).arg(m_inputId));
183 
184  return false;
185  }
186 
187  // Fetch tuning data from the database.
188  QString tvformat;
189  QString modulation;
190  QString freqtable;
191  QString freqid;
192  QString si_std;
193  int finetune = 0;
194  uint64_t frequency = 0;
195  int mpeg_prog_num = 0;
196  uint atsc_major = 0;
197  uint atsc_minor = 0;
198  uint mplexid = 0;
199  uint chanid = 0;
200  uint tsid = 0;
201  uint netid = 0;
202 
204  m_sourceId, chanid, channum,
205  tvformat, modulation, freqtable, freqid,
206  finetune, frequency,
207  si_std, mpeg_prog_num, atsc_major, atsc_minor, tsid, netid,
208  mplexid, m_commFree))
209  {
210  LOG(VB_GENERAL, LOG_ERR, loc + "Unable to find channel in database.");
211 
212  return false;
213  }
214 
215  if ((mplexid_restriction && (mplexid != mplexid_restriction)) ||
216  (!mplexid_restriction &&
217  chanid_restriction && (chanid != chanid_restriction)))
218  {
219  LOG(VB_GENERAL, LOG_ERR, loc +
220  QString("Requested channel '%1' is not available because "
221  "the tuner is currently in use on another transport.")
222  .arg(channum));
223 
224  return false;
225  }
226 
227  // If the frequency is zeroed out, don't use it directly.
228  if (frequency == 0)
229  {
230  frequency = (freqid.toULongLong() + finetune) * 1000;
231  mplexid = 0;
232  }
233  bool isFrequency = (frequency > 10000000);
234  bool hasTuneToChan =
235  !m_tuneToChannel.isEmpty() && m_tuneToChannel != "Undefined";
236 
237  // If we are tuning to a freqid, rather than an actual frequency,
238  // we may need to set the frequency table to use.
239  if (!isFrequency || hasTuneToChan)
240  SetFreqTable(freqtable);
241 
242  // Set NTSC, PAL, ATSC, etc.
243  SetFormat(tvformat);
244 
245  // If a tuneToChannel is set make sure we're still on it
246  if (hasTuneToChan)
247  Tune(m_tuneToChannel, 0);
248 
249  // Clear out any old PAT or PMT & save version info
250  uint version = 0;
251  if (m_genPAT)
252  {
253  version = (m_genPAT->Version()+1) & 0x1f;
254  delete m_genPAT; m_genPAT = nullptr;
255  delete m_genPMT; m_genPMT = nullptr;
256  }
257 
258  bool ok = true;
260  {
261  if (IsIPTV())
262  {
263  int chanid2 = ChannelUtil::GetChanID(m_sourceId, channum);
265  if (!Tune(tuning, false))
266  {
267  LOG(VB_GENERAL, LOG_ERR, loc + "Tuning to IPTV URL");
268  ClearDTVInfo();
269  ok = false;
270  }
271  }
272  else if (m_name.contains("composite", Qt::CaseInsensitive) ||
273  m_name.contains("component", Qt::CaseInsensitive) ||
274  m_name.contains("s-video", Qt::CaseInsensitive))
275  {
276  LOG(VB_GENERAL, LOG_WARNING, loc + "You have not set "
277  "an external channel changing"
278  "\n\t\t\tscript for a component|composite|s-video "
279  "input. Channel changing will do nothing.");
280  }
281  else if (isFrequency && Tune(frequency))
282  {
283  }
284  else if (isFrequency)
285  {
286  // Initialize basic the tuning parameters
287  DTVMultiplex tuning;
288  if (!mplexid || !tuning.FillFromDB(m_tunerType, mplexid))
289  {
290  LOG(VB_GENERAL, LOG_ERR, loc +
291  "Failed to initialize multiplex options");
292  ok = false;
293  }
294  else
295  {
296  LOG(VB_GENERAL, LOG_DEBUG, loc +
297  QString("Initialize multiplex options m_tunerType:%1 mplexid:%2")
298  .arg(m_tunerType).arg(mplexid));
299 
300  // Try to fix any problems with the multiplex
301  CheckOptions(tuning);
302 
303  // Tune to proper multiplex
304  if (!Tune(tuning))
305  {
306  LOG(VB_GENERAL, LOG_ERR, loc + "Tuning to frequency.");
307 
308  ClearDTVInfo();
309  ok = false;
310  }
311  }
312  }
313  else
314  {
315  // ExternalChannel justs wants the channum
316  ok = freqid.isEmpty() && finetune == 0 ?
317  Tune(channum) : Tune(freqid, finetune);
318  }
319  }
320 
321  LOG(VB_CHANNEL, LOG_INFO, loc + ((ok) ? "success" : "failure"));
322 
323  if (!ok)
324  return false;
325 
326  if (atsc_minor || (mpeg_prog_num>=0))
327  {
328  SetSIStandard(si_std);
329  SetDTVInfo(atsc_major, atsc_minor, netid, tsid, mpeg_prog_num);
330  }
331  else if (IsPIDTuningSupported())
332  {
333  // We need to pull the pid_cache since there are no tuning tables
334  pid_cache_t pid_cache;
335  int chanid3 = ChannelUtil::GetChanID(m_sourceId, channum);
336  ChannelUtil::GetCachedPids(chanid3, pid_cache);
337  if (pid_cache.empty())
338  {
339  LOG(VB_GENERAL, LOG_ERR, loc + "PID cache is empty");
340  return false;
341  }
342 
343  // Now we construct the PAT & PMT
344  std::vector<uint> pnum; pnum.push_back(1);
345  std::vector<uint> pid; pid.push_back(9999);
347 
348  int pcrpid = -1;
349  std::vector<uint> pids;
350  std::vector<uint> types;
351  for (auto & pit : pid_cache)
352  {
353  if (!pit.GetStreamID())
354  continue;
355  pids.push_back(pit.GetPID());
356  types.push_back(pit.GetStreamID());
357  if (pit.IsPCRPID())
358  pcrpid = pit.GetPID();
359  if ((pcrpid < 0) && StreamID::IsVideo(pit.GetStreamID()))
360  pcrpid = pit.GetPID();
361  }
362  if (pcrpid < 0)
363  pcrpid = pid_cache[0].GetPID();
364 
366  pnum.back(), pid.back(), pcrpid, version, pids, types);
367 
368  SetSIStandard("mpeg");
369  SetDTVInfo(0,0,0,0,-1);
370  }
371 
372  // Set the current channum to the new channel's channum
373  m_curChannelName = channum;
374 
375  // Setup filters & recording picture attributes for framegrabing recorders
376  // now that the new curchannelname has been established.
377  if (m_pParent)
380 
381  HandleScript(freqid);
382 
383  return ok;
384 }
385 
387 {
388  // MAYBE TODO? need to tell signal monitor to throw out any tables
389  // it saw on the last mux...
390 
391  // We do not want to call ChannelBase::HandleScript() as it
392  // will save the current channel to (*it)->startChanNum
393 }
394 
395 bool DTVChannel::TuneMultiplex(uint mplexid, const QString& /*inputname*/)
396 {
397  DTVMultiplex tuning;
398  if (!tuning.FillFromDB(m_tunerType, mplexid))
399  return false;
400 
401  CheckOptions(tuning);
402 
403  return Tune(tuning);
404 }
DTVChannel::GetTunerTypes
virtual std::vector< DTVTunerType > GetTunerTypes(void) const
Returns a vector of supported tuning types.
Definition: dtvchannel.cpp:79
MasterMap
QMap< QString, QList< DTVChannel * > > MasterMap
Definition: dtvchannel.cpp:15
DTVChannel::CheckOptions
virtual void CheckOptions(DTVMultiplex &) const
Checks tuning for problems, and tries to fix them.
Definition: dtvchannel.h:156
DTVMultiplex
Definition: dtvmultiplex.h:24
dtvchannel.h
DTVChannel::RegisterForMaster
void RegisterForMaster(const QString &key)
Definition: dtvchannel.cpp:114
DTVChannel::ReturnMasterLock
static void ReturnMasterLock(DTVChannelP &chan)
Definition: dtvchannel.cpp:148
DTVChannel::m_currentTransportID
uint m_currentTransportID
Definition: dtvchannel.h:170
mythdb.h
ChannelBase::m_name
QString m_name
Definition: channelbase.h:139
DTVChannel::s_master_map
static MasterMap s_master_map
Definition: dtvchannel.h:180
DTVChannel::ClearDTVInfo
void ClearDTVInfo(void)
Definition: dtvchannel.h:154
ChannelBase::Open
virtual bool Open(void)=0
Opens the channel changing hardware for use.
ChannelBase::GetInputName
virtual QString GetInputName(void) const
Definition: channelbase.h:69
DTVChannel::IsIPTV
virtual bool IsIPTV(void) const
Definition: dtvchannel.h:134
ChannelBase::IsOpen
virtual bool IsOpen(void) const =0
Reports whether channel is already open.
DTVChannel::IsPIDTuningSupported
virtual bool IsPIDTuningSupported(void) const
Definition: dtvchannel.h:132
ChannelBase::m_inputId
uint m_inputId
Definition: channelbase.h:137
types
static const struct wl_interface * types[]
Definition: idle_inhibit_unstable_v1.c:39
ChannelUtil::GetCachedPids
static bool GetCachedPids(uint chanid, pid_cache_t &pid_cache)
Returns cached MPEG PIDs when given a Channel ID.
Definition: channelutil.cpp:856
DTVChannel::SetChannelByString
bool SetChannelByString(const QString &chan) override
Definition: dtvchannel.cpp:157
DTVChannel::DeregisterForMaster
void DeregisterForMaster(const QString &key)
Definition: dtvchannel.cpp:121
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
DTVChannel::GetMasterLock
static DTVChannel * GetMasterLock(const QString &key)
Definition: dtvchannel.cpp:136
ChannelUtil::GetIPTVTuningData
static IPTVTuningData GetIPTVTuningData(uint chanid)
Definition: channelutil.cpp:1980
DTVChannel::Tune
virtual bool Tune(const DTVMultiplex &tuning)=0
This performs the actual frequency tuning and in some cases input switching.
ChannelBase::m_tuneToChannel
QString m_tuneToChannel
Definition: channelbase.h:142
DTVMultiplex::FillFromDB
virtual bool FillFromDB(DTVTunerType type, uint mplexid)
Definition: dtvmultiplex.cpp:525
DTVChannel::m_currentProgramNum
int m_currentProgramNum
Definition: dtvchannel.h:167
StreamID::IsVideo
static bool IsVideo(uint type)
Returns true iff video is an MPEG1/2/3, H264 or open cable video stream.
Definition: mpegtables.h:168
DTVChannel::GetTuningMode
QString GetTuningMode(void) const
Returns tuning mode last set by SetTuningMode().
Definition: dtvchannel.cpp:73
ChannelBase::IsInputAvailable
virtual bool IsInputAvailable(uint &mplexid_restriction, uint &chanid_restriction) const
Switches to another input on hardware, and sets the channel is setstarting is true.
Definition: channelbase.cpp:229
DTVChannel::m_currentOriginalNetworkID
uint m_currentOriginalNetworkID
Definition: dtvchannel.h:171
ChannelBase::HandleScript
void HandleScript(const QString &freqid)
Definition: channelbase.cpp:281
ChannelBase::InitPictureAttributes
virtual bool InitPictureAttributes(void)
Definition: channelbase.h:93
ChannelUtil::GetChanID
static int GetChanID(int db_mplexid, int service_transport_id, int major_channel, int minor_channel, int program_number)
Definition: channelutil.cpp:1310
mythlogging.h
DTVChannel::~DTVChannel
~DTVChannel() override
Definition: dtvchannel.cpp:18
DTVChannel::m_genPMT
ProgramMapTable * m_genPMT
This is a generated PMT for RAW pid tuning.
Definition: dtvchannel.h:176
DTVChannel::SaveCachedPids
void SaveCachedPids(const pid_cache_t &pid_cache) const
Saves MPEG PIDs to cache to database.
Definition: dtvchannel.cpp:107
ChannelBase::m_curChannelName
QString m_curChannelName
Definition: channelbase.h:135
DTVTunerType::kTunerTypeUnknown
static const int kTunerTypeUnknown
Definition: dtvconfparserhelpers.h:103
DTVChannel::SetSIStandard
void SetSIStandard(const QString &si_std)
Sets PSIP table standard: MPEG, DVB, ATSC, or OpenCable.
Definition: dtvchannel.cpp:51
pid_cache_t
std::vector< pid_cache_item_t > pid_cache_t
Definition: channelutil.h:43
ChannelBase::IsExternalChannelChangeInUse
virtual bool IsExternalChannelChangeInUse(void)
Definition: channelbase.cpp:840
IPTVTuningData
Definition: iptvtuningdata.h:21
mpegtables.h
DTVChannel::SetFormat
void SetFormat(const QString &format) override
Definition: dtvchannel.h:44
uint
unsigned int uint
Definition: compat.h:79
ProgramMapTable::Create
static ProgramMapTable * Create(uint programNumber, uint basepid, uint pcrpid, uint version, std::vector< uint > pids, std::vector< uint > types)
Definition: mpegtables.cpp:407
DTVChannel::m_sistandard
QString m_sistandard
PSIP table standard: MPEG, DVB, ATSC, OpenCable.
Definition: dtvchannel.h:164
DTVChannel::GetSIStandard
QString GetSIStandard(void) const
Returns PSIP table standard: MPEG, DVB, ATSC, or OpenCable.
Definition: dtvchannel.cpp:45
CardUtil::GetQuickTuning
static uint GetQuickTuning(uint inputid, const QString &input_name)
Definition: cardutil.cpp:2269
ChannelUtil::GetChannelData
static bool GetChannelData(uint sourceid, uint &chanid, const QString &channum, QString &tvformat, QString &modulation, QString &freqtable, QString &freqid, int &finetune, uint64_t &frequency, QString &dtv_si_std, int &mpeg_prog_num, uint &atsc_major, uint &atsc_minor, uint &dvb_transportid, uint &dvb_networkid, uint &mplexid, bool &commfree)
Definition: channelutil.cpp:1884
DTVChannel::HandleScriptEnd
void HandleScriptEnd(bool ok) override
Definition: dtvchannel.cpp:386
DTVChannel::m_tunerType
DTVTunerType m_tunerType
Definition: dtvchannel.h:162
DTVChannel::s_master_map_lock
static QReadWriteLock s_master_map_lock
Definition: dtvchannel.h:179
DTVChannel::TuneMultiplex
virtual bool TuneMultiplex(uint mplexid, const QString &inputname)
To be used by the channel scanner and possibly the EIT scanner.
Definition: dtvchannel.cpp:395
ChannelBase::SetFreqTable
virtual int SetFreqTable(const QString &)
Definition: channelbase.h:53
ChannelBase::m_sourceId
uint m_sourceId
Definition: channelbase.h:138
cardutil.h
DTVChannel::m_genPAT
ProgramAssociationTable * m_genPAT
This is a generated PAT for RAW pid tuning.
Definition: dtvchannel.h:174
DTVChannel::SetTuningMode
void SetTuningMode(const QString &tuning_mode)
Sets tuning mode: "mpeg", "dvb", "atsc", etc.
Definition: dtvchannel.cpp:87
DTVChannel::m_dtvinfoLock
QMutex m_dtvinfoLock
Definition: dtvchannel.h:160
tv_rec.h
ProgramAssociationTable::Create
static ProgramAssociationTable * Create(uint tsid, uint version, const std::vector< uint > &pnum, const std::vector< uint > &pid)
Definition: mpegtables.cpp:347
DTVChannel::SetDTVInfo
void SetDTVInfo(uint atsc_major, uint atsc_minor, uint dvb_orig_netid, uint mpeg_tsid, int mpeg_pnum)
Definition: dtvchannel.cpp:33
ChannelBase::GetSourceID
virtual uint GetSourceID(void) const
Definition: channelbase.h:71
LOC
#define LOC
Definition: dtvchannel.cpp:12
DTVChannel
Class providing a generic interface to digital tuning hardware.
Definition: dtvchannel.h:33
ChannelUtil::SaveCachedPids
static bool SaveCachedPids(uint chanid, const pid_cache_t &_pid_cache, bool delete_all=false)
Saves PIDs for PSIP tables to database.
Definition: channelutil.cpp:889
DTVChannel::GetCachedPids
void GetCachedPids(pid_cache_t &pid_cache) const
Returns cached MPEG PIDs for last tuned channel.
Definition: dtvchannel.cpp:97
TVRec::SetVideoFiltersForChannel
bool SetVideoFiltersForChannel(uint sourceid, const QString &channum)
Definition: tv_rec.cpp:2405
DTVChannel::GetSuggestedTuningMode
QString GetSuggestedTuningMode(bool is_live_tv) const
Returns suggested tuning mode: "mpeg", "dvb", or "atsc".
Definition: dtvchannel.cpp:57
DTVChannel::m_tuningMode
QString m_tuningMode
Definition: dtvchannel.h:165
DTVChannel::m_currentATSCMinorChannel
uint m_currentATSCMinorChannel
Definition: dtvchannel.h:169
DTVChannel::m_currentATSCMajorChannel
uint m_currentATSCMajorChannel
Definition: dtvchannel.h:168
nv_python_libs.bbciplayer.bbciplayer_api.version
string version
Definition: bbciplayer_api.py:77
ChannelBase::m_pParent
TVRec * m_pParent
Definition: channelbase.h:134
PSIPTable::Version
uint Version(void) const
Definition: mpegtables.h:539
ChannelBase::m_commFree
bool m_commFree
Definition: channelbase.h:136
ChannelBase::GetChanID
virtual int GetChanID(void) const
Definition: channelbase.cpp:496