diff --git a/mythtv/libs/libmythbase/mythdb.cpp b/mythtv/libs/libmythbase/mythdb.cpp
index 2ab7962..ea30783 100644
a
|
b
|
bool MythDB::GetSettings(QMap<QString,QString> &_key_value_pairs)
|
452 | 452 | } |
453 | 453 | } |
454 | 454 | } |
455 | | else |
| 455 | for (; kvit != _key_value_pairs.end(); ++dit, ++kvit) |
456 | 456 | { |
457 | | for (; kvit != _key_value_pairs.end(); ++dit, ++kvit) |
| 457 | SettingsMap::const_iterator it = |
| 458 | d->overriddenSettings.find(dit.key()); |
| 459 | if (it != d->overriddenSettings.end()) |
458 | 460 | { |
459 | | SettingsMap::const_iterator it = |
460 | | d->overriddenSettings.find(dit.key()); |
461 | | if (it != d->overriddenSettings.end()) |
462 | | { |
463 | | *kvit = *it; |
464 | | *dit = true; |
465 | | done_cnt++; |
466 | | } |
| 461 | *kvit = *it; |
| 462 | *dit = true; |
| 463 | done_cnt++; |
467 | 464 | } |
468 | 465 | } |
469 | 466 | d->settingsCacheLock.unlock(); |
… |
… |
QString MythDB::GetSettingOnHost(const QString &_key, const QString &_host,
|
605 | 602 | return value; |
606 | 603 | } |
607 | 604 | } |
608 | | else |
| 605 | SettingsMap::const_iterator it = d->overriddenSettings.find(myKey); |
| 606 | if (it != d->overriddenSettings.end()) |
609 | 607 | { |
610 | | SettingsMap::const_iterator it = d->overriddenSettings.find(myKey); |
611 | | if (it != d->overriddenSettings.end()) |
612 | | { |
613 | | value = *it; |
614 | | d->settingsCacheLock.unlock(); |
615 | | return value; |
616 | | } |
| 608 | value = *it; |
| 609 | d->settingsCacheLock.unlock(); |
| 610 | return value; |
617 | 611 | } |
618 | 612 | d->settingsCacheLock.unlock(); |
619 | 613 | |
diff --git a/mythtv/libs/libmythtv/mpegrecorder.cpp b/mythtv/libs/libmythtv/mpegrecorder.cpp
index 8728faa..18e1766 100644
a
|
b
|
bool MpegRecorder::OpenV4L2DeviceAsInput(void)
|
423 | 423 | SetRecordingVolume(chanfd); // we don't care if this fails... |
424 | 424 | |
425 | 425 | if (!SetV4L2DeviceOptions(chanfd)) |
| 426 | { |
| 427 | close(chanfd); |
| 428 | chanfd = -1; |
426 | 429 | return false; |
| 430 | } |
427 | 431 | |
428 | 432 | SetVBIOptions(chanfd); // we don't care if this fails... |
429 | 433 | |
… |
… |
bool MpegRecorder::OpenV4L2DeviceAsInput(void)
|
451 | 455 | if (!_device_read_buffer) |
452 | 456 | { |
453 | 457 | LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to allocate DRB buffer"); |
454 | | _error = true; |
| 458 | _error = "Failed to allocate DRB buffer"; |
455 | 459 | close(chanfd); |
456 | 460 | chanfd = -1; |
457 | 461 | close(readfd); |
… |
… |
bool MpegRecorder::OpenV4L2DeviceAsInput(void)
|
461 | 465 | |
462 | 466 | if (!_device_read_buffer->Setup(vdevice.constData(), readfd)) |
463 | 467 | { |
464 | | LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to allocate DRB buffer"); |
465 | | _error = true; |
| 468 | LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to setup DRB buffer"); |
| 469 | _error = "Failed to setup DRB buffer"; |
466 | 470 | close(chanfd); |
467 | 471 | chanfd = -1; |
468 | 472 | close(readfd); |
… |
… |
void MpegRecorder::run(void)
|
902 | 906 | { |
903 | 907 | if (!Open()) |
904 | 908 | { |
905 | | _error = "Failed to open V4L device"; |
| 909 | if (_error.isEmpty()) |
| 910 | _error = "Failed to open V4L device"; |
906 | 911 | return; |
907 | 912 | } |
908 | 913 | |
… |
… |
void MpegRecorder::run(void)
|
963 | 968 | else if (_device_read_buffer) |
964 | 969 | { |
965 | 970 | LOG(VB_RECORD, LOG_INFO, LOC + "Initial startup of recorder"); |
966 | | |
967 | | if (!StartEncoding(readfd)) |
968 | | { |
969 | | LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to start recording"); |
970 | | _error = true; |
971 | | } |
972 | | else |
973 | | _device_read_buffer->Start(); |
| 971 | StartEncoding(); |
974 | 972 | } |
975 | 973 | |
976 | 974 | QByteArray vdevice = videodevice.toAscii(); |
… |
… |
void MpegRecorder::run(void)
|
1000 | 998 | } |
1001 | 999 | } |
1002 | 1000 | } |
1003 | | else |
1004 | | { |
1005 | | if (readfd < 0) |
1006 | | { |
1007 | | if (!Open()) |
1008 | | { |
1009 | | _error = true; |
1010 | | break; |
1011 | | } |
1012 | | |
1013 | | if (readfd < 0) |
1014 | | { |
1015 | | LOG(VB_GENERAL, LOG_ERR, LOC + |
1016 | | QString("Failed to open device '%1'") |
1017 | | .arg(videodevice)); |
1018 | | continue; |
1019 | | } |
1020 | | } |
1021 | | } |
1022 | 1001 | |
1023 | 1002 | if (_device_read_buffer) |
1024 | 1003 | { |
… |
… |
void MpegRecorder::run(void)
|
1036 | 1015 | IsRecordingRequested()) |
1037 | 1016 | { |
1038 | 1017 | LOG(VB_GENERAL, LOG_ERR, LOC + "Device EOF detected"); |
1039 | | _error = true; |
| 1018 | _error = "Device EOF detected"; |
1040 | 1019 | } |
1041 | 1020 | } |
1042 | 1021 | else |
… |
… |
void MpegRecorder::run(void)
|
1133 | 1112 | |
1134 | 1113 | LOG(VB_RECORD, LOG_INFO, LOC + "run finishing up"); |
1135 | 1114 | |
1136 | | pauseLock.lock(); |
1137 | | if (_device_read_buffer) |
1138 | | { |
1139 | | if (_device_read_buffer->IsRunning()) |
1140 | | _device_read_buffer->Stop(); |
1141 | | |
1142 | | delete _device_read_buffer; |
1143 | | _device_read_buffer = NULL; |
1144 | | } |
1145 | | pauseLock.unlock(); |
1146 | | |
1147 | | StopEncoding(readfd); |
| 1115 | StopEncoding(); |
1148 | 1116 | |
1149 | 1117 | { |
1150 | 1118 | QMutexLocker locker(&pauseLock); |
… |
… |
bool MpegRecorder::PauseAndWait(int timeout)
|
1241 | 1209 | { |
1242 | 1210 | LOG(VB_RECORD, LOG_INFO, LOC + "PauseAndWait pause"); |
1243 | 1211 | |
1244 | | if (_device_read_buffer) |
1245 | | { |
1246 | | _device_read_buffer->SetRequestPause(true); |
1247 | | _device_read_buffer->WaitForPaused(4000); |
1248 | | } |
1249 | | |
1250 | | StopEncoding(readfd); |
| 1212 | StopEncoding(); |
1251 | 1213 | |
1252 | 1214 | paused = true; |
1253 | 1215 | pauseWait.wakeAll(); |
… |
… |
bool MpegRecorder::PauseAndWait(int timeout)
|
1272 | 1234 | SetV4L2DeviceOptions(chanfd); |
1273 | 1235 | } |
1274 | 1236 | |
1275 | | StartEncoding(readfd); |
1276 | | |
1277 | | if (_device_read_buffer) |
1278 | | _device_read_buffer->SetRequestPause(false); |
| 1237 | StartEncoding(); |
1279 | 1238 | |
1280 | 1239 | if (_stream_data) |
1281 | 1240 | _stream_data->Reset(_stream_data->DesiredProgram()); |
… |
… |
void MpegRecorder::RestartEncoding(void)
|
1290 | 1249 | { |
1291 | 1250 | LOG(VB_RECORD, LOG_INFO, LOC + "RestartEncoding"); |
1292 | 1251 | |
1293 | | _device_read_buffer->Stop(); |
1294 | | |
1295 | 1252 | QMutexLocker locker(&start_stop_encoding_lock); |
1296 | 1253 | |
1297 | | StopEncoding(readfd); |
| 1254 | StopEncoding(); |
1298 | 1255 | |
1299 | 1256 | // Make sure the next things in the file are a PAT & PMT |
1300 | 1257 | if (_stream_data && |
… |
… |
void MpegRecorder::RestartEncoding(void)
|
1308 | 1265 | |
1309 | 1266 | if (driver == "hdpvr") // HD-PVR will sometimes reset to defaults |
1310 | 1267 | SetV4L2DeviceOptions(chanfd); |
1311 | | if (!StartEncoding(readfd)) |
1312 | | { |
1313 | | if (0 != close(readfd)) |
1314 | | LOG(VB_GENERAL, LOG_ERR, LOC + "Close error" + ENO); |
1315 | 1268 | |
1316 | | readfd = -1; |
1317 | | return; |
1318 | | } |
1319 | | |
1320 | | _device_read_buffer->Start(); |
| 1269 | StartEncoding(); |
1321 | 1270 | } |
1322 | 1271 | |
1323 | | bool MpegRecorder::StartEncoding(int fd) |
| 1272 | bool MpegRecorder::StartEncoding(void) |
1324 | 1273 | { |
1325 | 1274 | QMutexLocker locker(&start_stop_encoding_lock); |
1326 | 1275 | |
… |
… |
bool MpegRecorder::StartEncoding(int fd)
|
1333 | 1282 | |
1334 | 1283 | LOG(VB_RECORD, LOG_INFO, LOC + "StartEncoding"); |
1335 | 1284 | |
1336 | | if (ioctl(fd, VIDIOC_ENCODER_CMD, &command) == 0) |
| 1285 | if (readfd < 0) |
| 1286 | { |
| 1287 | readfd = open(videodevice.toAscii().constData(), O_RDWR | O_NONBLOCK); |
| 1288 | if (readfd < 0) |
| 1289 | { |
| 1290 | LOG(VB_GENERAL, LOG_ERR, LOC + |
| 1291 | "StartEncoding: Can't open video device." + ENO); |
| 1292 | _error = "Failed to start recording"; |
| 1293 | return false; |
| 1294 | } |
| 1295 | } |
| 1296 | |
| 1297 | bool started = 0 == ioctl(readfd, VIDIOC_ENCODER_CMD, &command); |
| 1298 | if (started) |
1337 | 1299 | { |
1338 | 1300 | if (driver == "hdpvr") |
1339 | 1301 | { |
… |
… |
bool MpegRecorder::StartEncoding(int fd)
|
1341 | 1303 | _wait_for_keyframe_option = true; |
1342 | 1304 | _seen_sps = false; |
1343 | 1305 | } |
1344 | | |
1345 | 1306 | LOG(VB_RECORD, LOG_INFO, LOC + "Encoding started"); |
1346 | | return true; |
| 1307 | } |
| 1308 | else if ((ENOTTY == errno) || (EINVAL == errno)) |
| 1309 | { |
| 1310 | // Some drivers do not support this ioctl at all. It is marked as |
| 1311 | // "experimental" in the V4L2 API spec. These drivers return EINVAL |
| 1312 | // in older kernels and ENOTTY in 3.1+ |
| 1313 | started = true; |
| 1314 | } |
| 1315 | else |
| 1316 | { |
| 1317 | LOG(VB_GENERAL, LOG_WARNING, LOC + "StartEncoding failed" + ENO); |
1347 | 1318 | } |
1348 | 1319 | |
1349 | | // Some drivers do not support this ioctl at all. It is marked as |
1350 | | // "experimental" in the V4L2 API spec. If we fail with EINVAL (which |
1351 | | // happens if the ioctl isn't supported), treat it as a success, but |
1352 | | // put a warning in the logs. This should keep any driver without this |
1353 | | // support (such as saa7164) recording without affecting those that do |
1354 | | // use it. |
1355 | | if (errno == EINVAL) |
1356 | | return true; |
| 1320 | if (_device_read_buffer) |
| 1321 | { |
| 1322 | _device_read_buffer->Reset(videodevice.toAscii().constData(), readfd); |
| 1323 | _device_read_buffer->Start(); |
| 1324 | } |
1357 | 1325 | |
1358 | | LOG(VB_GENERAL, LOG_WARNING, LOC + "StartEncoding failed" + ENO); |
1359 | | return false; |
| 1326 | return true; |
1360 | 1327 | } |
1361 | 1328 | |
1362 | | bool MpegRecorder::StopEncoding(int fd) |
| 1329 | bool MpegRecorder::StopEncoding(void) |
1363 | 1330 | { |
1364 | 1331 | QMutexLocker locker(&start_stop_encoding_lock); |
1365 | 1332 | |
| 1333 | if (readfd < 0) |
| 1334 | return true; |
| 1335 | |
1366 | 1336 | struct v4l2_encoder_cmd command; |
1367 | 1337 | memset(&command, 0, sizeof(struct v4l2_encoder_cmd)); |
1368 | 1338 | command.cmd = V4L2_ENC_CMD_STOP; |
… |
… |
bool MpegRecorder::StopEncoding(int fd)
|
1370 | 1340 | |
1371 | 1341 | LOG(VB_RECORD, LOG_INFO, LOC + "StopEncoding"); |
1372 | 1342 | |
1373 | | if (ioctl(fd, VIDIOC_ENCODER_CMD, &command) == 0) |
| 1343 | bool stopped = 0 == ioctl(readfd, VIDIOC_ENCODER_CMD, &command); |
| 1344 | if (stopped) |
1374 | 1345 | { |
1375 | 1346 | LOG(VB_RECORD, LOG_INFO, LOC + "Encoding stopped"); |
1376 | | return true; |
| 1347 | } |
| 1348 | else if ((ENOTTY == errno) || (EINVAL == errno)) |
| 1349 | { |
| 1350 | // Some drivers do not support this ioctl at all. It is marked as |
| 1351 | // "experimental" in the V4L2 API spec. These drivers return EINVAL |
| 1352 | // in older kernels and ENOTTY in 3.1+ |
| 1353 | stopped = true; |
| 1354 | } |
| 1355 | else |
| 1356 | { |
| 1357 | LOG(VB_GENERAL, LOG_WARNING, LOC + "StopEncoding failed" + ENO); |
1377 | 1358 | } |
1378 | 1359 | |
1379 | | // Some drivers do not support this ioctl at all. It is marked as |
1380 | | // "experimental" in the V4L2 API spec. If we fail with EINVAL (which |
1381 | | // happens if the ioctl isn't supported), treat it as a success, but |
1382 | | // put a warning in the logs. This should keep any driver without this |
1383 | | // support (such as saa7164) recording without affecting those that do |
1384 | | // use it. |
1385 | | if (errno == EINVAL) |
1386 | | return true; |
| 1360 | if (_device_read_buffer && _device_read_buffer->IsRunning()) |
| 1361 | { |
| 1362 | usleep(20 * 1000); // allow last bits of data through.. |
| 1363 | _device_read_buffer->Stop(); |
| 1364 | } |
| 1365 | |
| 1366 | // close the fd so streamoff/streamon work in V4LChannel |
| 1367 | close(readfd); |
| 1368 | readfd = -1; |
1387 | 1369 | |
1388 | | LOG(VB_GENERAL, LOG_WARNING, LOC + "StopEncoding failed" + ENO); |
1389 | | return false; |
| 1370 | return stopped; |
1390 | 1371 | } |
1391 | 1372 | |
1392 | 1373 | void MpegRecorder::SetStreamData(void) |
diff --git a/mythtv/libs/libmythtv/mpegrecorder.h b/mythtv/libs/libmythtv/mpegrecorder.h
index da1b7fc..d27a62d 100644
a
|
b
|
class MpegRecorder : public V4LRecorder,
|
68 | 68 | uint GetFilteredAudioBitRate(uint audio_layer) const; |
69 | 69 | |
70 | 70 | void RestartEncoding(void); |
71 | | bool StartEncoding(int fd); |
72 | | bool StopEncoding(int fd); |
| 71 | bool StartEncoding(void); |
| 72 | bool StopEncoding(void); |
73 | 73 | |
74 | 74 | void SetBitrate(int bitrate, int maxbitrate, const QString & reason); |
75 | 75 | void HandleResolutionChanges(void); |
diff --git a/mythtv/libs/libmythtv/v4lchannel.cpp b/mythtv/libs/libmythtv/v4lchannel.cpp
index e8ab9d9..a128523 100644
a
|
b
|
bool V4LChannel::Open(void)
|
99 | 99 | has_tuner = !!(capabilities & V4L2_CAP_TUNER); |
100 | 100 | has_sliced_vbi = !!(capabilities & V4L2_CAP_SLICED_VBI_CAPTURE); |
101 | 101 | |
102 | | if (driver_name == "bttv" || driver_name == "cx8800") |
103 | | has_stream_io = false; // driver workaround, see #9825 & #10519 |
104 | | |
105 | 102 | LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Device name '%1' driver '%2'.") |
106 | 103 | .arg(device_name).arg(driver_name)); |
107 | 104 | |