diff --git a/mythtv/libs/libmythtv/NuppelVideoRecorder.cpp b/mythtv/libs/libmythtv/NuppelVideoRecorder.cpp
index debd75b..17481c2 100644
a
|
b
|
NuppelVideoRecorder::NuppelVideoRecorder(TVRec *rec, ChannelBase *channel) : |
87 | 87 | { |
88 | 88 | channelObj = channel; |
89 | 89 | |
90 | | encoding = false; |
91 | 90 | fd = -1; |
92 | 91 | channelfd = -1; |
93 | 92 | lf = tf = 0; |
… |
… |
NuppelVideoRecorder::NuppelVideoRecorder(TVRec *rec, ChannelBase *channel) : |
130 | 129 | text_buffer_count = 0; |
131 | 130 | text_buffer_size = 0; |
132 | 131 | |
133 | | childrenLive = false; |
134 | | errored = false; |
135 | | |
136 | | recording = false; |
137 | | |
138 | 132 | writepaused = false; |
139 | 133 | audiopaused = false; |
140 | 134 | mainpaused = false; |
… |
… |
bool NuppelVideoRecorder::IsRecording(void) |
491 | 485 | return recording; |
492 | 486 | } |
493 | 487 | |
494 | | bool NuppelVideoRecorder::IsErrored(void) |
495 | | { |
496 | | return errored; |
497 | | } |
498 | | |
499 | 488 | long long NuppelVideoRecorder::GetFramesWritten(void) |
500 | 489 | { |
501 | 490 | return framesWritten; |
… |
… |
void NuppelVideoRecorder::Initialize(void) |
748 | 737 | livetv = false; |
749 | 738 | if (!ringBuffer->IsOpen()) |
750 | 739 | { |
751 | | LOG(VB_GENERAL, LOG_ERR, LOC + "Could not open RingBuffer"); |
752 | | errored = true; |
| 740 | _error = "Could not open RingBuffer"; |
| 741 | LOG(VB_GENERAL, LOG_ERR, LOC + _error); |
753 | 742 | return; |
754 | 743 | } |
755 | 744 | } |
… |
… |
void NuppelVideoRecorder::ResizeVideoBuffers(void) |
992 | 981 | } |
993 | 982 | } |
994 | 983 | |
995 | | void NuppelVideoRecorder::StopRecording(void) |
996 | | { |
997 | | encoding = false; |
998 | | V4LRecorder::StopRecording(); |
999 | | } |
1000 | | |
1001 | 984 | void NuppelVideoRecorder::StreamAllocate(void) |
1002 | 985 | { |
1003 | 986 | strm = new signed char[width * height * 2 + 10]; |
… |
… |
bool NuppelVideoRecorder::Open(void) |
1017 | 1000 | fd = open(vdevice.constData(), O_RDWR); |
1018 | 1001 | if (retries++ > 5) |
1019 | 1002 | { |
1020 | | LOG(VB_GENERAL, LOG_ERR, LOC + |
1021 | | QString("Can't open video device: %1").arg(videodevice)); |
1022 | | LOG(VB_GENERAL, LOG_ERR, LOC + "open video: " + ENO); |
| 1003 | _error = QString("Can't open video device: %1").arg(videodevice); |
| 1004 | LOG(VB_GENERAL, LOG_ERR, LOC + _error + ENO); |
1023 | 1005 | KillChildren(); |
1024 | | errored = true; |
1025 | 1006 | return false; |
1026 | 1007 | } |
1027 | 1008 | } |
… |
… |
void NuppelVideoRecorder::run(void) |
1072 | 1053 | if (lzo_init() != LZO_E_OK) |
1073 | 1054 | { |
1074 | 1055 | LOG(VB_GENERAL, LOG_ERR, LOC + "lzo_init() failed, exiting"); |
1075 | | errored = true; |
| 1056 | _error = "lzo_init() failed, exiting"; |
| 1057 | LOG(VB_GENERAL, LOG_ERR, LOC + _error); |
1076 | 1058 | return; |
1077 | 1059 | } |
1078 | 1060 | |
1079 | 1061 | if (!Open()) |
1080 | 1062 | { |
1081 | | errored = true; |
| 1063 | _error = "Failed to open device"; |
| 1064 | LOG(VB_GENERAL, LOG_ERR, LOC + _error); |
1082 | 1065 | return; |
1083 | 1066 | } |
1084 | 1067 | |
… |
… |
void NuppelVideoRecorder::run(void) |
1086 | 1069 | |
1087 | 1070 | if (usingv4l2 && !SetFormatV4L2()) |
1088 | 1071 | { |
1089 | | errored = true; |
| 1072 | _error = "Failed to set V4L2 format"; |
| 1073 | LOG(VB_GENERAL, LOG_ERR, LOC + _error); |
1090 | 1074 | return; |
1091 | 1075 | } |
1092 | 1076 | |
… |
… |
void NuppelVideoRecorder::run(void) |
1112 | 1096 | |
1113 | 1097 | if (CreateNuppelFile() != 0) |
1114 | 1098 | { |
1115 | | LOG(VB_GENERAL, LOG_ERR, LOC + QString("Cannot open '%1' for writing") |
1116 | | .arg(ringBuffer->GetFilename())); |
1117 | | errored = true; |
| 1099 | _error = QString("Cannot open '%1' for writing") |
| 1100 | .arg(ringBuffer->GetFilename()); |
| 1101 | LOG(VB_GENERAL, LOG_ERR, LOC + _error); |
1118 | 1102 | return; |
1119 | 1103 | } |
1120 | 1104 | |
1121 | | if (childrenLive) |
| 1105 | if (IsHelperRequested()) |
1122 | 1106 | { |
1123 | 1107 | LOG(VB_GENERAL, LOG_ERR, LOC + "Children are already alive"); |
1124 | | errored = true; |
| 1108 | _error = "Children are already alive"; |
1125 | 1109 | return; |
1126 | 1110 | } |
1127 | 1111 | |
1128 | | if (!SpawnChildren()) |
1129 | 1112 | { |
1130 | | LOG(VB_GENERAL, LOG_ERR, LOC + "Couldn't spawn children"); |
1131 | | errored = true; |
1132 | | return; |
| 1113 | QMutexLocker locker(&pauseLock); |
| 1114 | request_recording = true; |
| 1115 | request_helper = true; |
| 1116 | recording = true; |
| 1117 | recordingWait.wakeAll(); |
1133 | 1118 | } |
1134 | 1119 | |
| 1120 | write_thread = new NVRWriteThread(this); |
| 1121 | write_thread->start(); |
| 1122 | |
| 1123 | audio_thread = new NVRAudioThread(this); |
| 1124 | audio_thread->start(); |
| 1125 | |
| 1126 | if ((vbimode != VBIMode::None) && (OpenVBIDevice() >= 0)) |
| 1127 | vbi_thread = new VBIThread(this); |
| 1128 | |
1135 | 1129 | // save the start time |
1136 | 1130 | gettimeofday(&stm, &tzone); |
1137 | 1131 | |
… |
… |
void NuppelVideoRecorder::run(void) |
1143 | 1137 | inpixfmt = FMT_NONE; |
1144 | 1138 | InitFilters(); |
1145 | 1139 | DoV4L2(); |
1146 | | return; |
1147 | 1140 | } |
1148 | 1141 | else |
1149 | 1142 | DoV4L1(); |
| 1143 | |
| 1144 | { |
| 1145 | QMutexLocker locker(&pauseLock); |
| 1146 | request_recording = false; |
| 1147 | request_helper = false; |
| 1148 | recording = false; |
| 1149 | recordingWait.wakeAll(); |
| 1150 | } |
1150 | 1151 | } |
1151 | 1152 | |
1152 | 1153 | #ifdef USING_V4L1 |
… |
… |
void NuppelVideoRecorder::DoV4L1(void) |
1168 | 1169 | |
1169 | 1170 | if (ioctl(fd, VIDIOCGCAP, &vc) < 0) |
1170 | 1171 | { |
1171 | | LOG(VB_GENERAL, LOG_ERR, LOC + "VIDIOCGCAP: " + ENO); |
| 1172 | QString tmp = "VIDIOCGCAP: " + ENO; |
1172 | 1173 | KillChildren(); |
1173 | | errored = true; |
| 1174 | LOG(VB_GENERAL, LOG_ERR, tmp); |
| 1175 | _error = tmp; |
1174 | 1176 | return; |
1175 | 1177 | } |
1176 | 1178 | |
… |
… |
void NuppelVideoRecorder::DoV4L1(void) |
1210 | 1212 | if ((vc.type & VID_TYPE_MJPEG_ENCODER) && hardware_encode) |
1211 | 1213 | { |
1212 | 1214 | DoMJPEG(); |
1213 | | errored = true; |
| 1215 | _error = "MJPEG requested but not available."; |
| 1216 | LOG(VB_GENERAL, LOG_ERR, LOC + _error); |
1214 | 1217 | return; |
1215 | 1218 | } |
1216 | 1219 | |
… |
… |
void NuppelVideoRecorder::DoV4L1(void) |
1219 | 1222 | |
1220 | 1223 | if (ioctl(fd, VIDIOCGMBUF, &vm) < 0) |
1221 | 1224 | { |
1222 | | LOG(VB_GENERAL, LOG_ERR, LOC + "VIDIOCGMBUF: " +ENO); |
| 1225 | QString tmp = "VIDIOCGMBUF: " + ENO; |
1223 | 1226 | KillChildren(); |
1224 | | errored = true; |
| 1227 | LOG(VB_GENERAL, LOG_ERR, LOC + tmp); |
| 1228 | _error = tmp; |
1225 | 1229 | return; |
1226 | 1230 | } |
1227 | 1231 | |
1228 | 1232 | if (vm.frames < 2) |
1229 | 1233 | { |
1230 | | LOG(VB_GENERAL, LOG_ERR, LOC + "need a minimum of 2 capture buffers"); |
| 1234 | QString tmp = "need a minimum of 2 capture buffers"; |
1231 | 1235 | KillChildren(); |
1232 | | errored = true; |
| 1236 | LOG(VB_GENERAL, LOG_ERR, LOC + tmp); |
| 1237 | _error = tmp; |
1233 | 1238 | return; |
1234 | 1239 | } |
1235 | 1240 | |
… |
… |
void NuppelVideoRecorder::DoV4L1(void) |
1241 | 1246 | fd, 0); |
1242 | 1247 | if (buf <= 0) |
1243 | 1248 | { |
1244 | | LOG(VB_GENERAL, LOG_ERR, LOC + "mmap: " + ENO); |
| 1249 | QString tmp = "mmap: " + ENO; |
1245 | 1250 | KillChildren(); |
1246 | | errored = true; |
| 1251 | LOG(VB_GENERAL, LOG_ERR, LOC + tmp); |
| 1252 | _error = tmp; |
1247 | 1253 | return; |
1248 | 1254 | } |
1249 | 1255 | |
… |
… |
void NuppelVideoRecorder::DoV4L1(void) |
1261 | 1267 | if (ioctl(fd, VIDIOCMCAPTURE, &mm)<0) |
1262 | 1268 | LOG(VB_GENERAL, LOG_ERR, LOC + "VIDIOCMCAPTUREi1: " + ENO); |
1263 | 1269 | |
1264 | | encoding = true; |
1265 | | recording = true; |
1266 | | |
1267 | 1270 | int syncerrors = 0; |
1268 | 1271 | |
1269 | | while (encoding) |
| 1272 | while (IsRecordingRequested() && !IsErrored()) |
1270 | 1273 | { |
1271 | 1274 | { |
1272 | 1275 | QMutexLocker locker(&pauseLock); |
… |
… |
void NuppelVideoRecorder::DoV4L1(void) |
1338 | 1341 | |
1339 | 1342 | FinishRecording(); |
1340 | 1343 | |
1341 | | recording = false; |
1342 | 1344 | close(fd); |
1343 | 1345 | } |
1344 | 1346 | #else // if !USING_V4L1 |
… |
… |
void NuppelVideoRecorder::DoV4L2(void) |
1487 | 1489 | comp.flags |= GO7007_COMP_CLOSED_GOP; |
1488 | 1490 | if (ioctl(fd, GO7007IOC_S_COMP_PARAMS, &comp) < 0) |
1489 | 1491 | { |
1490 | | LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to set compression params"); |
1491 | | errored = true; |
| 1492 | _error = "Unable to set compression params"; |
| 1493 | LOG(VB_GENERAL, LOG_ERR, LOC + _error); |
1492 | 1494 | return; |
1493 | 1495 | } |
1494 | 1496 | |
… |
… |
void NuppelVideoRecorder::DoV4L2(void) |
1501 | 1503 | |
1502 | 1504 | if (ioctl(fd, GO7007IOC_S_MPEG_PARAMS, &mpeg) < 0) |
1503 | 1505 | { |
1504 | | LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to set MPEG params"); |
1505 | | errored = true; |
| 1506 | _error = "Unable to set MPEG params"; |
| 1507 | LOG(VB_GENERAL, LOG_ERR, LOC + _error); |
1506 | 1508 | return; |
1507 | 1509 | } |
1508 | 1510 | |
… |
… |
void NuppelVideoRecorder::DoV4L2(void) |
1515 | 1517 | |
1516 | 1518 | if (ioctl(fd, GO7007IOC_S_BITRATE, &usebitrate) < 0) |
1517 | 1519 | { |
1518 | | LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to set bitrate"); |
1519 | | errored = true; |
| 1520 | _error = "Unable to set bitrate"; |
| 1521 | LOG(VB_GENERAL, LOG_ERR, LOC + _error); |
1520 | 1522 | return; |
1521 | 1523 | } |
1522 | 1524 | |
… |
… |
void NuppelVideoRecorder::DoV4L2(void) |
1531 | 1533 | |
1532 | 1534 | if (ioctl(fd, VIDIOC_REQBUFS, &vrbuf) < 0) |
1533 | 1535 | { |
1534 | | LOG(VB_GENERAL, LOG_ERR, LOC + |
1535 | | "Not able to get any capture buffers, exiting"); |
1536 | | errored = true; |
| 1536 | _error = "Not able to get any capture buffers, exiting"; |
| 1537 | LOG(VB_GENERAL, LOG_ERR, LOC + _error); |
1537 | 1538 | return; |
1538 | 1539 | } |
1539 | 1540 | |
… |
… |
void NuppelVideoRecorder::DoV4L2(void) |
1558 | 1559 | { |
1559 | 1560 | LOG(VB_GENERAL, LOG_ERR, LOC + |
1560 | 1561 | QString("unable to query capture buffer %1").arg(i)); |
1561 | | errored = true; |
| 1562 | _error = "Unable to query capture buffer"; |
1562 | 1563 | return; |
1563 | 1564 | } |
1564 | 1565 | |
… |
… |
void NuppelVideoRecorder::DoV4L2(void) |
1569 | 1570 | if (buffers[i] == MAP_FAILED) |
1570 | 1571 | { |
1571 | 1572 | LOG(VB_GENERAL, LOG_ERR, LOC + "mmap: " + ENO); |
1572 | | LOG(VB_GENERAL, LOG_ERR, LOC + QString("Memory map failed")); |
1573 | | errored = true; |
| 1573 | LOG(VB_GENERAL, LOG_ERR, LOC + "Memory map failed"); |
| 1574 | _error = "Memory map failed"; |
1574 | 1575 | return; |
1575 | 1576 | } |
1576 | 1577 | bufferlen[i] = vbuf.length; |
… |
… |
void NuppelVideoRecorder::DoV4L2(void) |
1592 | 1593 | int frame = 0; |
1593 | 1594 | bool forcekey = false; |
1594 | 1595 | |
1595 | | encoding = true; |
1596 | | recording = true; |
1597 | 1596 | resetcapture = false; |
1598 | 1597 | |
1599 | 1598 | // setup pixel format conversions for YUYV and UYVY |
… |
… |
void NuppelVideoRecorder::DoV4L2(void) |
1610 | 1609 | output_buffer = (uint8_t*)av_malloc(height * width * 3 / 2); |
1611 | 1610 | if (!output_buffer) |
1612 | 1611 | { |
1613 | | LOG(VB_GENERAL, LOG_ERR, LOC + |
1614 | | "Cannot initialize image conversionbuffer"); |
1615 | | errored = true; |
| 1612 | _error = "Cannot initialize image conversion buffer"; |
| 1613 | LOG(VB_GENERAL, LOG_ERR, LOC + _error); |
1616 | 1614 | return; |
1617 | 1615 | } |
1618 | 1616 | |
… |
… |
void NuppelVideoRecorder::DoV4L2(void) |
1621 | 1619 | SWS_FAST_BILINEAR, NULL, NULL, NULL); |
1622 | 1620 | if (!convert_ctx) |
1623 | 1621 | { |
1624 | | LOG(VB_GENERAL, LOG_ERR, LOC + |
1625 | | "Cannot initialize image conversion context"); |
1626 | | errored = true; |
| 1622 | _error = "Cannot initialize image conversion context"; |
| 1623 | LOG(VB_GENERAL, LOG_ERR, LOC + _error); |
1627 | 1624 | return; |
1628 | 1625 | } |
1629 | 1626 | |
1630 | 1627 | avpicture_fill(&img_out, output_buffer, PIX_FMT_YUV420P, width, height); |
1631 | 1628 | } |
1632 | 1629 | |
1633 | | while (encoding) { |
| 1630 | while (IsRecordingRequested() && !IsErrored()) |
| 1631 | { |
1634 | 1632 | again: |
1635 | 1633 | { |
1636 | 1634 | QMutexLocker locker(&pauseLock); |
… |
… |
again: |
1765 | 1763 | av_free(output_buffer); |
1766 | 1764 | sws_freeContext(convert_ctx); |
1767 | 1765 | |
1768 | | recording = false; |
1769 | 1766 | close(fd); |
1770 | 1767 | close(channelfd); |
1771 | 1768 | } |
… |
… |
void NuppelVideoRecorder::DoMJPEG(void) |
1867 | 1864 | LOG(VB_GENERAL, LOG_ERR, LOC + "MJPIOC_QBUF_CAPT: " + ENO); |
1868 | 1865 | } |
1869 | 1866 | |
1870 | | encoding = true; |
1871 | | recording = true; |
1872 | | |
1873 | | while (encoding) |
| 1867 | while (IsRecordingRequested() && !IsErrored()) |
1874 | 1868 | { |
1875 | 1869 | { |
1876 | 1870 | QMutexLocker locker(&pauseLock); |
… |
… |
void NuppelVideoRecorder::DoMJPEG(void) |
1897 | 1891 | } |
1898 | 1892 | |
1899 | 1893 | if (ioctl(fd, MJPIOC_SYNC, &bsync) < 0) |
1900 | | encoding = false; |
| 1894 | { |
| 1895 | _error = "MJPEG sync error"; |
| 1896 | LOG(VB_GENERAL, LOG_ERR, LOC + _error + ENO); |
| 1897 | break; |
| 1898 | } |
1901 | 1899 | |
1902 | 1900 | BufferIt((unsigned char *)(MJPG_buff + bsync.frame * breq.size), |
1903 | 1901 | bsync.length); |
1904 | 1902 | |
1905 | 1903 | if (ioctl(fd, MJPIOC_QBUF_CAPT, &(bsync.frame)) < 0) |
1906 | | encoding = false; |
| 1904 | { |
| 1905 | _error = "MJPEG Capture error"; |
| 1906 | LOG(VB_GENERAL, LOG_ERR, LOC + _error + ENO); |
| 1907 | } |
1907 | 1908 | } |
1908 | 1909 | |
1909 | 1910 | munmap(MJPG_buff, breq.count * breq.size); |
… |
… |
void NuppelVideoRecorder::DoMJPEG(void) |
1911 | 1912 | |
1912 | 1913 | FinishRecording(); |
1913 | 1914 | |
1914 | | recording = false; |
1915 | 1915 | close(fd); |
1916 | 1916 | } |
1917 | 1917 | #else // if !USING_V4L1 |
1918 | 1918 | void NuppelVideoRecorder::DoMJPEG(void) {} |
1919 | 1919 | #endif // !USING_V4L1 |
1920 | 1920 | |
1921 | | bool NuppelVideoRecorder::SpawnChildren(void) |
1922 | | { |
1923 | | childrenLive = true; |
1924 | | |
1925 | | write_thread = new NVRWriteThread(this); |
1926 | | write_thread->start(); |
1927 | | |
1928 | | audio_thread = new NVRAudioThread(this); |
1929 | | audio_thread->start(); |
1930 | | |
1931 | | if ((vbimode != VBIMode::None) && (OpenVBIDevice() >= 0)) |
1932 | | vbi_thread = new VBIThread(this); |
1933 | | |
1934 | | return true; |
1935 | | } |
1936 | | |
1937 | 1921 | void NuppelVideoRecorder::KillChildren(void) |
1938 | 1922 | { |
1939 | | childrenLive = false; |
1940 | 1923 | { |
1941 | 1924 | QMutexLocker locker(&pauseLock); |
| 1925 | request_helper = false; |
1942 | 1926 | unpauseWait.wakeAll(); |
1943 | 1927 | } |
1944 | 1928 | |
… |
… |
void NuppelVideoRecorder::doAudioThread(void) |
2409 | 2393 | int act = 0, lastread = 0; |
2410 | 2394 | audio_bytes_per_sample = audio_channels * audio_bits / 8; |
2411 | 2395 | |
2412 | | while (childrenLive) |
| 2396 | while (IsHelperRequested() && !IsErrored()) |
2413 | 2397 | { |
2414 | 2398 | { |
2415 | 2399 | QMutexLocker locker(&pauseLock); |
… |
… |
void NuppelVideoRecorder::doAudioThread(void) |
2433 | 2417 | } |
2434 | 2418 | } |
2435 | 2419 | |
| 2420 | if (!IsHelperRequested() || IsErrored()) |
| 2421 | break; |
| 2422 | |
2436 | 2423 | lastread = audio_device->GetSamples(buffer, audio_buffer_size); |
2437 | 2424 | if (audio_buffer_size != lastread) |
2438 | 2425 | { |
… |
… |
void NuppelVideoRecorder::AddTextData(unsigned char *buf, int len, |
2696 | 2683 | |
2697 | 2684 | void NuppelVideoRecorder::doWriteThread(void) |
2698 | 2685 | { |
2699 | | while (childrenLive && !IsErrored()) |
| 2686 | while (IsHelperRequested() && !IsErrored()) |
2700 | 2687 | { |
2701 | 2688 | { |
2702 | 2689 | QMutexLocker locker(&pauseLock); |
… |
… |
void NuppelVideoRecorder::doWriteThread(void) |
2720 | 2707 | } |
2721 | 2708 | } |
2722 | 2709 | |
| 2710 | if (!IsHelperRequested() || IsErrored()) |
| 2711 | break; |
| 2712 | |
2723 | 2713 | CheckForRingBufferSwitch(); |
2724 | 2714 | |
2725 | 2715 | enum |
… |
… |
void NuppelVideoRecorder::WriteAudio(unsigned char *buf, int fnum, int timecode) |
3182 | 3172 | { |
3183 | 3173 | LOG(VB_GENERAL, LOG_ERR, LOC + |
3184 | 3174 | QString("lame error '%1'").arg(lameret)); |
3185 | | errored = true; |
| 3175 | _error = QString("Audio Encoding Error '%1'") |
| 3176 | .arg(lameret); |
3186 | 3177 | return; |
3187 | 3178 | } |
3188 | 3179 | compressedsize = lameret; |
… |
… |
void NuppelVideoRecorder::WriteAudio(unsigned char *buf, int fnum, int timecode) |
3193 | 3184 | { |
3194 | 3185 | LOG(VB_GENERAL, LOG_ERR, LOC + |
3195 | 3186 | QString("lame error '%1'").arg(lameret)); |
3196 | | errored = true; |
| 3187 | _error = QString("Audio Encoding Error '%1'") |
| 3188 | .arg(lameret); |
3197 | 3189 | return; |
3198 | 3190 | } |
3199 | 3191 | gaplesssize = lameret; |
diff --git a/mythtv/libs/libmythtv/NuppelVideoRecorder.h b/mythtv/libs/libmythtv/NuppelVideoRecorder.h
index 860571d..67b7d67 100644
a
|
b
|
class MTV_PUBLIC NuppelVideoRecorder : public V4LRecorder, public CC608Input |
86 | 86 | |
87 | 87 | void Initialize(void); |
88 | 88 | void run(void); |
89 | | void StopRecording(void); |
90 | 89 | |
91 | 90 | virtual void Pause(bool clear = true); |
92 | 91 | virtual bool IsPaused(bool holding_lock = false) const; |
93 | 92 | |
94 | 93 | bool IsRecording(void); |
95 | | bool IsErrored(void); |
96 | 94 | |
97 | 95 | long long GetFramesWritten(void); |
98 | 96 | |
… |
… |
class MTV_PUBLIC NuppelVideoRecorder : public V4LRecorder, public CC608Input |
142 | 140 | |
143 | 141 | bool MJPEGInit(void); |
144 | 142 | |
145 | | bool SpawnChildren(void); |
146 | 143 | void KillChildren(void); |
147 | 144 | |
148 | 145 | void BufferIt(unsigned char *buf, int len = -1, bool forcekey = false); |
… |
… |
class MTV_PUBLIC NuppelVideoRecorder : public V4LRecorder, public CC608Input |
161 | 158 | |
162 | 159 | void UpdateResolutions(void); |
163 | 160 | |
164 | | bool encoding; |
165 | | |
166 | 161 | int fd; // v4l input file handle |
167 | 162 | signed char *strm; |
168 | 163 | unsigned int lf, tf; |
… |
… |
class MTV_PUBLIC NuppelVideoRecorder : public V4LRecorder, public CC608Input |
224 | 219 | struct timeval stm; |
225 | 220 | struct timezone tzone; |
226 | 221 | |
227 | | volatile bool childrenLive; |
228 | | |
229 | 222 | NVRWriteThread *write_thread; |
230 | 223 | NVRAudioThread *audio_thread; |
231 | 224 | |
232 | 225 | bool recording; |
233 | | bool errored; |
234 | 226 | |
235 | 227 | int keyframedist; |
236 | 228 | vector<struct seektable_entry> *seektable; |
diff --git a/mythtv/libs/libmythtv/mpegrecorder.cpp b/mythtv/libs/libmythtv/mpegrecorder.cpp
index 36e33c7..ced08fb 100644
a
|
b
|
void MpegRecorder::run(void) |
933 | 933 | { |
934 | 934 | QMutexLocker locker(&pauseLock); |
935 | 935 | request_recording = true; |
| 936 | request_helper = true; |
936 | 937 | recording = true; |
937 | 938 | recordingWait.wakeAll(); |
938 | 939 | } |
… |
… |
void MpegRecorder::run(void) |
1145 | 1146 | |
1146 | 1147 | StopEncoding(readfd); |
1147 | 1148 | |
| 1149 | { |
| 1150 | QMutexLocker locker(&pauseLock); |
| 1151 | request_helper = false; |
| 1152 | } |
| 1153 | |
| 1154 | if (vbi_thread) |
| 1155 | { |
| 1156 | vbi_thread->wait(); |
| 1157 | delete vbi_thread; |
| 1158 | vbi_thread = NULL; |
| 1159 | CloseVBIDevice(); |
| 1160 | } |
| 1161 | |
1148 | 1162 | FinishRecording(); |
1149 | 1163 | |
1150 | 1164 | delete[] buffer; |
… |
… |
void MpegRecorder::run(void) |
1157 | 1171 | } |
1158 | 1172 | |
1159 | 1173 | QMutexLocker locker(&pauseLock); |
| 1174 | request_recording = false; |
1160 | 1175 | recording = false; |
1161 | 1176 | recordingWait.wakeAll(); |
1162 | 1177 | } |
diff --git a/mythtv/libs/libmythtv/v4lrecorder.cpp b/mythtv/libs/libmythtv/v4lrecorder.cpp
index 40042b1..7a665da 100644
a
|
b
|
V4LRecorder::V4LRecorder(TVRec *tv) : |
33 | 33 | ntsc_vbi_width(0), ntsc_vbi_start_line(0), |
34 | 34 | ntsc_vbi_line_count(0), |
35 | 35 | vbi608(NULL), |
36 | | vbi_thread(NULL), vbi_fd(-1) |
| 36 | vbi_thread(NULL), vbi_fd(-1), |
| 37 | request_helper(false) |
37 | 38 | { |
38 | 39 | } |
39 | 40 | |
40 | 41 | V4LRecorder::~V4LRecorder() |
41 | 42 | { |
| 43 | { |
| 44 | QMutexLocker locker(&pauseLock); |
| 45 | request_helper = false; |
| 46 | unpauseWait.wakeAll(); |
| 47 | } |
| 48 | |
42 | 49 | if (vbi_thread) |
43 | 50 | { |
| 51 | vbi_thread->wait(); |
44 | 52 | delete vbi_thread; |
45 | 53 | vbi_thread = NULL; |
| 54 | CloseVBIDevice(); |
46 | 55 | } |
47 | 56 | } |
48 | 57 | |
… |
… |
void V4LRecorder::StopRecording(void) |
53 | 62 | vbi_thread->wait(); |
54 | 63 | } |
55 | 64 | |
| 65 | bool V4LRecorder::IsHelperRequested(void) const |
| 66 | { |
| 67 | QMutexLocker locker(&pauseLock); |
| 68 | return request_helper && request_recording; |
| 69 | } |
| 70 | |
56 | 71 | void V4LRecorder::SetOption(const QString &name, const QString &value) |
57 | 72 | { |
58 | 73 | if (name == "audiodevice") |
… |
… |
void V4LRecorder::RunVBIDevice(void) |
252 | 267 | ptr_end = buf + sz; |
253 | 268 | } |
254 | 269 | |
255 | | while (IsRecordingRequested() && !IsErrored()) |
| 270 | while (IsHelperRequested() && !IsErrored()) |
256 | 271 | { |
257 | 272 | if (PauseAndWait()) |
258 | 273 | continue; |
259 | 274 | |
260 | | if (!IsRecordingRequested()) |
| 275 | if (!IsHelperRequested() || IsErrored()) |
261 | 276 | break; |
262 | 277 | |
263 | 278 | struct timeval tv; |
diff --git a/mythtv/libs/libmythtv/v4lrecorder.h b/mythtv/libs/libmythtv/v4lrecorder.h
index 64de6fe..7835d3b 100644
a
|
b
|
class MTV_PUBLIC V4LRecorder : public DTVRecorder |
38 | 38 | void CloseVBIDevice(void); |
39 | 39 | void RunVBIDevice(void); |
40 | 40 | |
| 41 | virtual bool IsHelperRequested(void) const; |
41 | 42 | virtual void FormatTT(struct VBIData *vbidata) {} |
42 | 43 | virtual void FormatCC(uint code1, uint code2) {} |
43 | 44 | |
… |
… |
class MTV_PUBLIC V4LRecorder : public DTVRecorder |
54 | 55 | VBIThread *vbi_thread; |
55 | 56 | QList<struct txtbuffertype*> textbuffer; |
56 | 57 | int vbi_fd; |
| 58 | volatile bool request_helper; |
57 | 59 | }; |
58 | 60 | |
59 | 61 | class VBIThread : public MThread |