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