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