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 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)
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
395bool 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}
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:2322
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 &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:386
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:395
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:351
static ProgramMapTable * Create(uint programNumber, uint basepid, uint pcrpid, uint version, std::vector< uint > pids, std::vector< uint > types)
Definition: mpegtables.cpp:411
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:2506
QMap< QString, QList< DTVChannel * > > MasterMap
Definition: dtvchannel.cpp:15
#define LOC
Definition: dtvchannel.cpp:12
unsigned int uint
Definition: freesurround.h:24
static const struct wl_interface * types[]
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
string version
Definition: giantbomb.py:185