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 typedef QMap<QString,QList<DTVChannel*> > MasterMap;
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 && 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;
175  uint chanid_restriction;
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, modulation, freqtable, freqid, si_std;
188  int finetune;
189  uint64_t frequency;
190  int mpeg_prog_num;
191  uint atsc_major, atsc_minor, mplexid, chanid, tsid, netid;
192 
194  m_sourceid, chanid, channum,
195  tvformat, modulation, freqtable, freqid,
196  finetune, frequency,
197  si_std, mpeg_prog_num, atsc_major, atsc_minor, tsid, netid,
198  mplexid, m_commfree))
199  {
200  LOG(VB_GENERAL, LOG_ERR, loc + "Unable to find channel in database.");
201 
202  return false;
203  }
204 
205  if ((mplexid_restriction && (mplexid != mplexid_restriction)) ||
206  (!mplexid_restriction &&
207  chanid_restriction && (chanid != chanid_restriction)))
208  {
209  LOG(VB_GENERAL, LOG_ERR, loc +
210  QString("Requested channel '%1' is not available because "
211  "the tuner is currently in use on another transport.")
212  .arg(channum));
213 
214  return false;
215  }
216 
217  // If the frequency is zeroed out, don't use it directly.
218  if (frequency == 0)
219  {
220  frequency = (freqid.toULongLong() + finetune) * 1000;
221  mplexid = 0;
222  }
223  bool isFrequency = (frequency > 10000000);
224  bool hasTuneToChan =
225  !m_tuneToChannel.isEmpty() && m_tuneToChannel != "Undefined";
226 
227  // If we are tuning to a freqid, rather than an actual frequency,
228  // we may need to set the frequency table to use.
229  if (!isFrequency || hasTuneToChan)
230  SetFreqTable(freqtable);
231 
232  // Set NTSC, PAL, ATSC, etc.
233  SetFormat(tvformat);
234 
235  // If a tuneToChannel is set make sure we're still on it
236  if (hasTuneToChan)
237  Tune(m_tuneToChannel, 0);
238 
239  // Clear out any old PAT or PMT & save version info
240  uint version = 0;
241  if (m_genPAT)
242  {
243  version = (m_genPAT->Version()+1) & 0x1f;
244  delete m_genPAT; m_genPAT = nullptr;
245  delete m_genPMT; m_genPMT = nullptr;
246  }
247 
248  bool ok = true;
250  {
251  if (IsIPTV())
252  {
253  int chanid2 = ChannelUtil::GetChanID(m_sourceid, channum);
255  if (!Tune(tuning, false))
256  {
257  LOG(VB_GENERAL, LOG_ERR, loc + "Tuning to IPTV URL");
258  ClearDTVInfo();
259  ok = false;
260  }
261  }
262  else if (m_name.contains("composite", Qt::CaseInsensitive) ||
263  m_name.contains("component", Qt::CaseInsensitive) ||
264  m_name.contains("s-video", Qt::CaseInsensitive))
265  {
266  LOG(VB_GENERAL, LOG_WARNING, loc + "You have not set "
267  "an external channel changing"
268  "\n\t\t\tscript for a component|composite|s-video "
269  "input. Channel changing will do nothing.");
270  }
271  else if (isFrequency && Tune(frequency))
272  {
273  }
274  else if (isFrequency)
275  {
276  // Initialize basic the tuning parameters
277  DTVMultiplex tuning;
278  if (!mplexid || !tuning.FillFromDB(m_tunerType, mplexid))
279  {
280  LOG(VB_GENERAL, LOG_ERR, loc +
281  "Failed to initialize multiplex options");
282  ok = false;
283  }
284  else
285  {
286  LOG(VB_GENERAL, LOG_DEBUG, loc +
287  QString("Initialize multiplex options m_tunerType:%1 mplexid:%2")
288  .arg(m_tunerType).arg(mplexid));
289 
290  // Try to fix any problems with the multiplex
291  CheckOptions(tuning);
292 
293  // Tune to proper multiplex
294  if (!Tune(tuning))
295  {
296  LOG(VB_GENERAL, LOG_ERR, loc + "Tuning to frequency.");
297 
298  ClearDTVInfo();
299  ok = false;
300  }
301  }
302  }
303  else
304  {
305  // ExternalChannel justs wants the channum
306  ok = freqid.isEmpty() && finetune == 0 ?
307  Tune(channum) : Tune(freqid, finetune);
308  }
309  }
310 
311  LOG(VB_CHANNEL, LOG_INFO, loc + ((ok) ? "success" : "failure"));
312 
313  if (!ok)
314  return false;
315 
316  if (atsc_minor || (mpeg_prog_num>=0))
317  {
318  SetSIStandard(si_std);
319  SetDTVInfo(atsc_major, atsc_minor, netid, tsid, mpeg_prog_num);
320  }
321  else if (IsPIDTuningSupported())
322  {
323  // We need to pull the pid_cache since there are no tuning tables
324  pid_cache_t pid_cache;
325  int chanid3 = ChannelUtil::GetChanID(m_sourceid, channum);
326  ChannelUtil::GetCachedPids(chanid3, pid_cache);
327  if (pid_cache.empty())
328  {
329  LOG(VB_GENERAL, LOG_ERR, loc + "PID cache is empty");
330  return false;
331  }
332 
333  // Now we construct the PAT & PMT
334  vector<uint> pnum; pnum.push_back(1);
335  vector<uint> pid; pid.push_back(9999);
337 
338  int pcrpid = -1;
339  vector<uint> pids;
340  vector<uint> types;
341  pid_cache_t::iterator pit = pid_cache.begin();
342  for (; pit != pid_cache.end(); ++pit)
343  {
344  if (!pit->GetStreamID())
345  continue;
346  pids.push_back(pit->GetPID());
347  types.push_back(pit->GetStreamID());
348  if (pit->IsPCRPID())
349  pcrpid = pit->GetPID();
350  if ((pcrpid < 0) && StreamID::IsVideo(pit->GetStreamID()))
351  pcrpid = pit->GetPID();
352  }
353  if (pcrpid < 0)
354  pcrpid = pid_cache[0].GetPID();
355 
357  pnum.back(), pid.back(), pcrpid, version, pids, types);
358 
359  SetSIStandard("mpeg");
360  SetDTVInfo(0,0,0,0,-1);
361  }
362 
363  // Set the current channum to the new channel's channum
364  m_curchannelname = channum;
365 
366  // Setup filters & recording picture attributes for framegrabing recorders
367  // now that the new curchannelname has been established.
368  if (m_pParent)
371 
372  HandleScript(freqid);
373 
374  return ok;
375 }
376 
378 {
379  // MAYBE TODO? need to tell signal monitor to throw out any tables
380  // it saw on the last mux...
381 
382  // We do not want to call ChannelBase::HandleScript() as it
383  // will save the current channel to (*it)->startChanNum
384 }
385 
386 bool DTVChannel::TuneMultiplex(uint mplexid, const QString& /*inputname*/)
387 {
388  DTVMultiplex tuning;
389  if (!tuning.FillFromDB(m_tunerType, mplexid))
390  return false;
391 
392  CheckOptions(tuning);
393 
394  return Tune(tuning);
395 }
#define LOC
Definition: dtvchannel.cpp:11
uint Version(void) const
Definition: mpegtables.h:503
virtual int GetChanID(void) const
static QReadWriteLock s_master_map_lock
Definition: dtvchannel.h:180
ProgramMapTable * m_genPMT
This is a generated PMT for RAW pid tuning.
Definition: dtvchannel.h:177
virtual bool IsOpen(void) const =0
Reports whether channel is already open.
void SetTuningMode(const QString &tuning_mode)
Sets tuning mode: "mpeg", "dvb", "atsc", etc.
Definition: dtvchannel.cpp:86
TVRec * m_pParent
Definition: channelbase.h:134
bool m_commfree
Definition: channelbase.h:136
static const int kTunerTypeUnknown
static bool GetCachedPids(uint chanid, pid_cache_t &pid_cache)
Returns cached MPEG PIDs when given a Channel ID.
vector< pid_cache_item_t > pid_cache_t
Definition: channelutil.h:43
QString GetSuggestedTuningMode(bool is_live_tv) const
Returns suggested tuning mode: "mpeg", "dvb", or "atsc".
Definition: dtvchannel.cpp:56
QString m_name
Definition: channelbase.h:139
unsigned int uint
Definition: compat.h:140
QString m_tuningMode
Definition: dtvchannel.h:166
virtual bool Open(void)=0
Opens the channel changing hardware for use.
uint m_inputid
Definition: channelbase.h:137
QMutex m_dtvinfo_lock
Definition: dtvchannel.h:161
void HandleScriptEnd(bool ok) override
Definition: dtvchannel.cpp:377
static IPTVTuningData GetIPTVTuningData(uint chanid)
void HandleScript(const QString &freqid)
DTVTunerType m_tunerType
Definition: dtvchannel.h:163
virtual bool TuneMultiplex(uint mplexid, const QString &inputname)
To be used by the channel scanner and possibly the EIT scanner.
Definition: dtvchannel.cpp:386
virtual bool IsExternalChannelChangeInUse(void)
static MasterMap s_master_map
Definition: dtvchannel.h:181
uint m_sourceid
Definition: channelbase.h:138
static bool IsVideo(uint type)
Returns true iff video is an MPEG1/2/3, H264 or open cable video stream.
Definition: mpegtables.h:165
void RegisterForMaster(const QString &key)
Definition: dtvchannel.cpp:113
virtual bool IsInputAvailable(uint &mplexid_restriction, uint &chanid_restriction) const
Switches to another input on hardware, and sets the channel is setstarting is true.
static ProgramAssociationTable * Create(uint tsid, uint version, const vector< uint > &pnum, const vector< uint > &pid)
Definition: mpegtables.cpp:346
QString m_curchannelname
Definition: channelbase.h:135
static ProgramMapTable * Create(uint programNumber, uint basepid, uint pcrpid, uint version, vector< uint > pids, vector< uint > types)
Definition: mpegtables.cpp:406
Class providing a generic interface to digital tuning hardware.
Definition: dtvchannel.h:34
QString m_tuneToChannel
Definition: channelbase.h:142
static int GetChanID(int db_mplexid, int service_transport_id, int major_channel, int minor_channel, int program_number)
static uint GetQuickTuning(uint inputid, const QString &input_name)
Definition: cardutil.cpp:2132
ProgramAssociationTable * m_genPAT
This is a generated PAT for RAW pid tuning.
Definition: dtvchannel.h:175
static DTVChannel * GetMasterLock(const QString &key)
Definition: dtvchannel.cpp:135
virtual bool IsIPTV(void) const
Definition: dtvchannel.h:135
void GetCachedPids(pid_cache_t &pid_cache) const
Returns cached MPEG PIDs for last tuned channel.
Definition: dtvchannel.cpp:96
virtual bool InitPictureAttributes(void)
Definition: channelbase.h:93
virtual bool IsPIDTuningSupported(void) const
Definition: dtvchannel.h:133
uint m_currentATSCMinorChannel
Definition: dtvchannel.h:170
void SetDTVInfo(uint atsc_major, uint atsc_minor, uint dvb_orig_netid, uint mpeg_tsid, int mpeg_pnum)
Definition: dtvchannel.cpp:32
uint m_currentATSCMajorChannel
Definition: dtvchannel.h:169
QString GetTuningMode(void) const
Returns tuning mode last set by SetTuningMode().
Definition: dtvchannel.cpp:72
virtual bool Tune(const DTVMultiplex &tuning)=0
This performs the actual frequency tuning and in some cases input switching.
virtual void CheckOptions(DTVMultiplex &) const
Checks tuning for problems, and tries to fix them.
Definition: dtvchannel.h:157
virtual int SetFreqTable(const QString &)
Definition: channelbase.h:53
void SaveCachedPids(const pid_cache_t &pid_cache) const
Saves MPEG PIDs to cache to database.
Definition: dtvchannel.cpp:106
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
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)
static bool SaveCachedPids(uint chanid, const pid_cache_t &_pid_cache, bool delete_all=false)
Saves PIDs for PSIP tables to database.
bool SetVideoFiltersForChannel(uint sourceid, const QString &channum)
Definition: tv_rec.cpp:2450
void SetSIStandard(const QString &)
Sets PSIP table standard: MPEG, DVB, ATSC, or OpenCable.
Definition: dtvchannel.cpp:50
uint m_currentTransportID
Definition: dtvchannel.h:171
void ClearDTVInfo(void)
Definition: dtvchannel.h:155
QMap< QString, QList< DTVChannel * > > MasterMap
Definition: dtvchannel.cpp:14
void SetFormat(const QString &format) override
Definition: dtvchannel.h:45
static void ReturnMasterLock(DTVChannelP &)
Definition: dtvchannel.cpp:147
bool SetChannelByString(const QString &chan) override
Definition: dtvchannel.cpp:156
virtual ~DTVChannel()
Definition: dtvchannel.cpp:17
void DeregisterForMaster(const QString &key)
Definition: dtvchannel.cpp:120
QString GetSIStandard(void) const
Returns PSIP table standard: MPEG, DVB, ATSC, or OpenCable.
Definition: dtvchannel.cpp:44
virtual uint GetSourceID(void) const
Definition: channelbase.h:71
virtual vector< DTVTunerType > GetTunerTypes(void) const
Returns a vector of supported tuning types.
Definition: dtvchannel.cpp:78
int m_currentProgramNum
Definition: dtvchannel.h:168
virtual QString GetInputName(void) const
Definition: channelbase.h:69
virtual bool FillFromDB(DTVTunerType type, uint mplexid)
uint m_currentOriginalNetworkID
Definition: dtvchannel.h:172
QString m_sistandard
PSIP table standard: MPEG, DVB, ATSC, OpenCable.
Definition: dtvchannel.h:165