7 #include <sys/select.h>
23 #define LOC QString("HDHRSH[%1](%2): ").arg(m_inputId).arg(m_device)
30 int inputid,
int majorid)
34 QMap<int,HDHRStreamHandler*>::iterator it =
s_handlers.find(majorid);
43 LOG(VB_RECORD, LOG_INFO,
44 QString(
"HDHRSH[%1]: Creating new stream handler %2 for %3")
45 .arg(inputid).arg(majorid).arg(devname));
51 LOG(VB_RECORD, LOG_INFO,
52 QString(
"HDHRSH[%1]: Using existing stream handler %2 for %3")
53 .arg(inputid).arg(majorid)
54 .arg(devname) + QString(
" (%1 in use)").arg(rcount));
70 QMap<int,HDHRStreamHandler*>::iterator it =
s_handlers.find(majorid);
80 LOG(VB_RECORD, LOG_INFO, QString(
"HDHRSH[%1]: Closing handler for %2")
81 .arg(inputid).arg(majorid));
88 LOG(VB_GENERAL, LOG_ERR,
89 QString(
"HDHRSH[%1] Error: Couldn't find handler for %2")
90 .arg(inputid).arg(majorid));
118 LOG(VB_GENERAL, LOG_ERR,
LOC +
119 "Starting recording (set target failed). Aborting.");
129 LOG(VB_RECORD, LOG_INFO,
LOC +
"RunTS(): begin");
132 QElapsedTimer last_update;
135 auto elapsed = !last_update.isValid()
136 ? -1ms : std::chrono::milliseconds(last_update.elapsed());
137 elapsed = (elapsed < 0ms) ? 1s : elapsed;
143 last_update.restart();
146 size_t read_size = VIDEO_DATA_BUFFER_SIZE_1S / 8;
147 read_size /= VIDEO_DATA_PACKET_SIZE;
148 read_size *= VIDEO_DATA_PACKET_SIZE;
150 size_t data_length = 0;
151 unsigned char *data_buffer = hdhomerun_device_stream_recv(
156 std::this_thread::sleep_for(20ms);
171 remainder = sit.key()->ProcessData(data_buffer, data_length);
173 WriteMPTS(data_buffer, data_length - remainder);
178 LOG(VB_RECORD, LOG_INFO,
LOC +
179 QString(
"RunTS(): data_length = %1 remainder = %2")
180 .arg(data_length).arg(remainder));
183 LOG(VB_RECORD, LOG_INFO,
LOC +
"RunTS(): " +
"shutdown");
194 struct hdhomerun_video_sock_t* vs =
nullptr;
195 struct hdhomerun_video_stats_t stats {};
199 hdhomerun_video_get_stats(vs, &stats);
200 LOG(VB_RECORD, LOG_INFO,
LOC +
201 QString(
"stream stats: packet_count=%1 "
203 "transport_errors=%3 "
204 "sequence_errors=%4 "
205 "overflow_errors=%5")
206 .arg(stats.packet_count)
207 .arg(stats.network_error_count)
208 .arg(stats.transport_error_count)
209 .arg(stats.sequence_error_count)
210 .arg(stats.overflow_error_count));
214 LOG(VB_RECORD, LOG_INFO,
LOC +
"RunTS(): " +
"end");
223 uint pid0 = (pid / (16*16*16)) % 16;
224 uint pid1 = (pid / (16*16)) % 16;
225 uint pid2 = (pid / (16)) % 16;
226 uint pid3 = pid % 16;
227 return QString(
"0x%1%2%3%4")
228 .arg(pid0,0,16).arg(pid1,0,16)
229 .arg(pid2,0,16).arg(pid3,0,16);
239 LOG(VB_GENERAL, LOG_ERR,
LOC +
240 "UpdateFilters called in wrong tune mode");
244 #ifdef DEBUG_PID_FILTERS
245 LOG(VB_RECORD, LOG_DEBUG,
LOC +
"UpdateFilters()");
246 #endif // DEBUG_PID_FILTERS
256 std::vector<uint> range_min;
257 std::vector<uint> range_max;
261 range_min.push_back(it.key());
262 PIDInfoMap::const_iterator eit = it;
264 (eit !=
m_pidInfo.cend()) && (it.key() + 1 == eit.key());
266 range_max.push_back(it.key());
268 if (range_min.size() > 16)
270 range_min.resize(16);
271 uint pid_max = range_max.back();
272 range_max.resize(15);
273 range_max.push_back(pid_max);
276 for (
size_t i = 0; i < range_min.size(); i++)
279 if (range_min[i] != range_max[i])
280 filter += QString(
"-%1").arg(
filt_str(range_max[i]));
284 filter = filter.trimmed();
286 QString new_filter =
TunerSet(
"filter", filter);
288 #ifdef DEBUG_PID_FILTERS
289 QString msg = QString(
"Filter: '%1'").arg(filter);
290 if (filter != new_filter)
291 msg += QString(
"\n\t\t\t\t'%2'").arg(new_filter);
293 LOG(VB_RECORD, LOG_DEBUG,
LOC + msg);
294 #endif // DEBUG_PID_FILTERS
298 return filter == new_filter;
307 if (QString(model).contains(
"cablecard", Qt::CaseInsensitive))
309 QString status_channel =
"none";
310 hdhomerun_tuner_status_t t_status {};
312 if (hdhomerun_device_get_oob_status(
315 LOG(VB_GENERAL, LOG_ERR,
LOC +
316 "Failed to query Cable card OOB channel");
320 status_channel = QString(t_status.channel);
321 LOG(VB_RECORD, LOG_INFO,
LOC +
322 QString(
"Cable card OOB channel is '%1'")
323 .arg(status_channel));
326 if (status_channel ==
"none")
328 LOG(VB_RECORD, LOG_INFO,
LOC +
"Cable card is not present");
333 LOG(VB_RECORD, LOG_INFO,
LOC +
"Cable card is present");
337 else if (QString(model).endsWith(
"dvbt", Qt::CaseInsensitive))
341 else if (QString(model).endsWith(
"dvbc", Qt::CaseInsensitive))
345 else if (QString(model).endsWith(
"dvbtc", Qt::CaseInsensitive))
380 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Unable to create device selector");
384 QStringList devices =
m_device.split(
",");
385 for (
const QString& device : qAsConst(devices))
387 QByteArray ba = device.toUtf8();
388 int n = hdhomerun_device_selector_load_from_str(
390 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Added %1 devices from %3")
391 .arg(n).arg(device));
398 LOG(VB_GENERAL, LOG_ERR,
LOC +
399 QString(
"Unable to find a free device"));
407 LOG(VB_GENERAL, LOG_INFO,
LOC +
408 QString(
"Connected to device(%1)")
420 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Get request failed (not connected)");
424 QString valname = QString(
"/tuner%1/%2").arg(
m_tuner).arg(name);
425 char *value =
nullptr;
426 char *
error =
nullptr;
427 if (hdhomerun_device_get_var(
431 LOG(VB_GENERAL, LOG_ERR,
LOC +
432 QString(
"Get %1 request failed").arg(valname) +
ENO);
438 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"DeviceGet(%1): %2")
452 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Set request failed (not connected)");
456 QString valname = QString(
"/tuner%1/%2").arg(
m_tuner).arg(name);
457 char *value =
nullptr;
458 char *
error =
nullptr;
461 LOG(VB_CHANSCAN, LOG_DEBUG,
LOC + valname +
" " + val);
466 if (name.contains(
"filter") && val.contains(
"0x2000"))
468 val2 =
"0x0000-0x1FFF";
469 LOG(VB_RECORD, LOG_INFO,
LOC + valname +
" fixup: \"" + val +
"\" to \"" +val2 +
"\"");
472 if (hdhomerun_device_set_var(
474 val2.toLocal8Bit().constData(), &value, &
error) < 0)
476 LOG(VB_GENERAL, LOG_ERR,
LOC +
477 QString(
"Set %1 to '%2' request failed").arg(valname, val2) +
485 if (strstr(
error,
"ERROR: lock no longer held"))
488 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"DeviceSet(%1 %2): %3")
489 .arg(name, val2,
error));
515 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Not Re-Tuning channel %1")
520 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Tuning channel %1 (was %2)")
522 return !
TunerSet(
"channel", chanid).isEmpty();
532 LOG(VB_GENERAL, LOG_ERR,
LOC +
"TuneProgram called in wrong tune mode");
536 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Tuning program %1")
537 .arg(mpeg_prog_num));
539 "program", QString::number(mpeg_prog_num)).isEmpty();
549 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Not Re-Tuning channel %1")
553 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"TuneVChannel(%1) from (%2)")
556 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Tuning vchannel %1").arg(vchn));
557 return !
TunerSet(
"vchannel", vchn).isEmpty();