15 #include <sys/types.h> 17 #include <sys/ioctl.h> 21 #include <linux/videodev2.h> 27 #include "ringbuffer.h" 40 #define IVTV_KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) 42 #define LOC QString("MPEGRec[%1](%2): ") \ 43 .arg(tvrec ? tvrec->GetInputId() : -1).arg(videodevice) 47 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0
52 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0
57 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0
62 "MPEG-2 PS",
"MPEG-2 TS",
"MPEG-1 VCD",
"PES AV",
63 "",
"PES V",
"",
"PES A",
65 "SVCD",
"DVD-Special 1",
"DVD-Special 2",
nullptr 70 "Square",
"4:3",
"16:9",
"2.21:1",
nullptr 76 deviceIsMpegFile(
false), bufferSize(0),
79 supports_sliced_vbi(
false),
81 start_stop_encoding_lock(QMutex::Recursive),
83 cleartimeonpause(
false),
85 width(720), height(480),
86 bitrate(4500), maxbitrate(6000),
87 streamtype(0), aspectratio(2),
88 audtype(2), audsamplerate(48000),
89 audbitratel1(14), audbitratel2(14),
91 audvolume(80), language(0),
92 low_mpeg4avgbitrate(4500), low_mpeg4peakbitrate(6000),
93 medium_mpeg4avgbitrate(9000), medium_mpeg4peakbitrate(13500),
94 high_mpeg4avgbitrate(13500), high_mpeg4peakbitrate(20200),
96 chanfd(-1), readfd(-1),
97 _device_read_buffer(nullptr)
134 for (
uint i = 0; audio_rate[i] != 0; i++)
136 if (audio_rate[i] == value)
147 else if (opt ==
"height")
149 else if (opt ==
"mpeg2bitrate")
151 else if (opt ==
"mpeg2maxbitrate")
153 else if (opt ==
"samplerate")
155 else if (opt ==
"mpeg2audbitratel1")
162 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Audiorate(L1): " +
163 QString(
"%1 is invalid").arg(value));
166 else if (opt ==
"mpeg2audbitratel2")
173 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Audiorate(L2): " +
174 QString(
"%1 is invalid").arg(value));
177 else if (opt ==
"mpeg2audbitratel3")
184 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Audiorate(L2): " +
185 QString(
"%1 is invalid").arg(value));
188 else if (opt ==
"mpeg2audvolume")
190 else if (opt.endsWith(
"_mpeg4avgbitrate"))
192 if (opt.startsWith(
"low"))
194 else if (opt.startsWith(
"medium"))
196 else if (opt.startsWith(
"high"))
201 else if (opt.endsWith(
"_mpeg4peakbitrate"))
203 if (opt.startsWith(
"low"))
205 else if (opt.startsWith(
"medium"))
207 else if (opt.startsWith(
"high"))
218 if (opt ==
"mpeg2streamtype")
221 for (
unsigned int i = 0; i <
sizeof(
streamType) /
sizeof(
char*); i++)
229 else if (QString(
streamType[i]) ==
"MPEG-2 PS")
247 LOG(VB_GENERAL, LOG_ERR,
LOC +
"MPEG2 stream type: " +
248 QString(
"%1 is invalid").arg(value));
251 else if (opt ==
"mpeg2language")
257 LOG(VB_GENERAL, LOG_ERR,
LOC +
"MPEG2 language (stereo) flag " +
258 QString(
"'%1' is invalid").arg(value));
261 else if (opt ==
"mpeg2aspectratio")
276 LOG(VB_GENERAL, LOG_ERR,
LOC +
"MPEG2 Aspect-ratio: " +
277 QString(
"%1 is invalid").arg(value));
280 else if (opt ==
"mpeg2audtype")
282 if (value ==
"Layer I")
283 audtype = V4L2_MPEG_AUDIO_ENCODING_LAYER_1 + 1;
284 else if (value ==
"Layer II")
285 audtype = V4L2_MPEG_AUDIO_ENCODING_LAYER_2 + 1;
286 else if (value ==
"Layer III")
287 audtype = V4L2_MPEG_AUDIO_ENCODING_LAYER_3 + 1;
290 LOG(VB_GENERAL, LOG_ERR,
LOC +
"MPEG2 audio layer: " +
291 QString(
"%1 is invalid").arg(value));
294 else if (opt ==
"audiocodec")
296 if (value ==
"AAC Hardware Encoder")
297 audtype = V4L2_MPEG_AUDIO_ENCODING_AAC + 1;
298 else if (value ==
"AC3 Hardware Encoder")
299 audtype = V4L2_MPEG_AUDIO_ENCODING_AC3 + 1;
308 const QString &videodev,
309 const QString &audiodev,
310 const QString &vbidev)
315 if (videodev.toLower().startsWith(
"file:"))
319 QString newVideoDev = videodev;
320 if (newVideoDev.startsWith(
"file:", Qt::CaseInsensitive))
321 newVideoDev = newVideoDev.remove(0,5);
383 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Can't open MPEG File '%1'")
385 _error =
LOC + QString(
"Can't open MPEG File '%1'")
398 chanfd = open(vdevice.constData(), O_RDWR);
401 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Can't open video device. " +
ENO);
408 bool supports_tuner =
false, supports_audio =
false;
409 uint32_t capabilities = 0;
413 supports_tuner = !!(capabilities & V4L2_CAP_TUNER);
414 supports_audio = !!(capabilities & V4L2_CAP_AUDIO);
423 if (!(capabilities & V4L2_CAP_VIDEO_CAPTURE))
425 LOG(VB_GENERAL, LOG_ERR,
LOC +
"V4L version 1, unsupported");
426 _error =
LOC +
"V4L version 1, unsupported";
458 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Can't open video device." +
ENO);
478 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to allocate DRB buffer");
479 _error =
"Failed to allocate DRB buffer";
489 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to setup DRB buffer");
490 _error =
"Failed to setup DRB buffer";
498 LOG(VB_RECORD, LOG_INFO,
LOC +
"DRB ready");
512 struct v4l2_format vfmt;
513 memset(&vfmt, 0,
sizeof(vfmt));
515 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
517 if (ioctl(
chanfd, VIDIOC_G_FMT, &vfmt) < 0)
519 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Error getting format" +
ENO);
524 vfmt.fmt.pix.width =
width;
525 vfmt.fmt.pix.height =
height;
527 if (ioctl(
chanfd, VIDIOC_S_FMT, &vfmt) < 0)
529 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Error setting format" +
ENO);
540 struct v4l2_tuner vt;
541 memset(&vt, 0,
sizeof(
struct v4l2_tuner));
542 if (ioctl(
chanfd, VIDIOC_G_TUNER, &vt) < 0)
544 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Unable to get audio mode" +
ENO);
551 vt.audmode = V4L2_TUNER_MODE_LANG1;
554 vt.audmode = V4L2_TUNER_MODE_LANG2;
557 vt.audmode = V4L2_TUNER_MODE_LANG1_LANG2;
560 vt.audmode = V4L2_TUNER_MODE_LANG1;
565 if ((2 ==
language) && (1 == audio_layer))
567 LOG(VB_GENERAL, LOG_WARNING,
568 "Dual audio mode incompatible with Layer I audio." 569 "\n\t\t\tFalling back to Main Language");
570 vt.audmode = V4L2_TUNER_MODE_LANG1;
574 if (ioctl(
chanfd, VIDIOC_S_TUNER, &vt) < 0)
576 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Unable to set audio mode" +
ENO);
586 struct v4l2_queryctrl qctrl;
587 memset(&qctrl, 0 ,
sizeof(
struct v4l2_queryctrl));
588 qctrl.id = V4L2_CID_AUDIO_VOLUME;
589 if ((ioctl(
chanfd, VIDIOC_QUERYCTRL, &qctrl) < 0) ||
590 (qctrl.flags & V4L2_CTRL_FLAG_DISABLED))
592 LOG(VB_CHANNEL, LOG_WARNING,
593 LOC +
"Audio volume control not supported.");
598 int range = qctrl.maximum - qctrl.minimum;
599 int value = (int) ((range *
audvolume * 0.01f) + qctrl.minimum);
600 int ctrl_volume = min(qctrl.maximum, max(qctrl.minimum, value));
603 struct v4l2_control ctrl;
604 ctrl.id = V4L2_CID_AUDIO_VOLUME;
605 ctrl.value = ctrl_volume;
607 if (ioctl(
chanfd, VIDIOC_S_CTRL, &ctrl) < 0)
609 LOG(VB_GENERAL, LOG_WARNING,
LOC +
610 "Unable to set recording volume" +
ENO +
"\n\t\t\t" +
611 "If you are using an AverMedia M179 card this is normal.");
626 case 2: st = 2;
break;
629 case 14: st = 10;
break;
630 case 11: st = 11;
break;
631 case 12: st = 12;
break;
632 default: st = 0;
break;
638 LOG(VB_GENERAL, LOG_WARNING,
LOC +
639 QString(
"Stream type '%1'\n\t\t\t" 640 "is not supported by %2 driver, using '%3' instead.")
651 sr = (
driver ==
"ivtv") ? 48000 : sr;
655 LOG(VB_GENERAL, LOG_WARNING,
LOC +
656 QString(
"Audio sample rate %1 Hz\n\t\t\t" 657 "is not supported by %2 driver, using %3 Hz instead.")
663 case 32000:
return V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000;
664 case 44100:
return V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100;
665 case 48000:
return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
666 default:
return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
674 layer = max(min(layer, 3U), 1U);
676 layer = (
driver ==
"ivtv") ? 2 : layer;
680 LOG(VB_GENERAL, LOG_WARNING,
LOC +
681 QString(
"MPEG layer %1 does not work properly\n\t\t\t" 682 "with %2 driver. Using MPEG layer %3 audio instead.")
699 case 0:
return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
700 case 1:
return V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
701 case 2:
return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD;
702 case 3:
return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
703 case 5:
return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
704 case 7:
return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
705 case 10:
return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
706 case 11:
return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD;
707 case 12:
return V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD;
708 case 13:
return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
709 case 14:
return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
710 default:
return V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
715 uint32_t
id, int32_t value)
717 struct v4l2_ext_control tmp_ctrl;
718 memset(&tmp_ctrl, 0,
sizeof(
struct v4l2_ext_control));
720 tmp_ctrl.value = value;
721 ctrl_list.push_back(tmp_ctrl);
724 static void set_ctrls(
int fd, vector<struct v4l2_ext_control> &ext_ctrls)
726 static QMutex control_description_lock;
727 static QMap<uint32_t,QString> control_description;
729 control_description_lock.lock();
730 if (control_description.isEmpty())
732 control_description[V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ] =
733 "Audio Sampling Frequency";
734 control_description[V4L2_CID_MPEG_VIDEO_ASPECT] =
735 "Video Aspect ratio";
736 control_description[V4L2_CID_MPEG_AUDIO_ENCODING] =
738 control_description[V4L2_CID_MPEG_AUDIO_L2_BITRATE] =
740 control_description[V4L2_CID_MPEG_VIDEO_BITRATE_PEAK] =
741 "Video Peak Bitrate";
742 control_description[V4L2_CID_MPEG_VIDEO_BITRATE] =
743 "Video Average Bitrate";
744 control_description[V4L2_CID_MPEG_STREAM_TYPE] =
746 control_description[V4L2_CID_MPEG_VIDEO_BITRATE_MODE] =
749 control_description_lock.unlock();
751 for (
uint i = 0; i < ext_ctrls.size(); i++)
753 struct v4l2_ext_controls ctrls;
754 memset(&ctrls, 0,
sizeof(
struct v4l2_ext_controls));
756 int value = ext_ctrls[i].value;
758 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
760 ctrls.controls = &ext_ctrls[i];
762 if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
764 QMutexLocker locker(&control_description_lock);
765 LOG(VB_GENERAL, LOG_ERR, QString(
"mpegrecorder.cpp:set_ctrls(): ") +
766 QString(
"Could not set %1 to %2")
767 .arg(control_description[ext_ctrls[i].
id]).arg(value) +
775 vector<struct v4l2_ext_control> ext_ctrls;
780 if (!
driver.startsWith(
"saa7164"))
782 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
810 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
812 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR :
813 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
819 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
828 struct v4l2_audio ain;
829 memset(&ain, 0,
sizeof(ain));
830 ain.index = audioinput;
831 if (ioctl(
chanfd, VIDIOC_ENUMAUDIO, &ain) < 0)
833 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Unable to get audio input.");
837 ain.index = audioinput;
838 if (ioctl(
chanfd, VIDIOC_S_AUDIO, &ain) < 0)
840 LOG(VB_GENERAL, LOG_WARNING,
841 LOC +
"Unable to set audio input.");
847 if (
driver ==
"hdpvr" && audioinput != 2)
849 struct v4l2_queryctrl qctrl;
850 qctrl.id = V4L2_CID_MPEG_AUDIO_ENCODING;
852 if (!ioctl(
chanfd, VIDIOC_QUERYCTRL, &qctrl))
854 uint audio_enc = max(min(
audtype-1, qctrl.maximum), qctrl.minimum);
855 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_ENCODING, audio_enc);
859 LOG(VB_GENERAL, LOG_WARNING,
LOC +
860 "Unable to get supported audio codecs." +
ENO);
875 #ifdef V4L2_CAP_SLICED_VBI_CAPTURE 885 struct v4l2_format vbifmt;
886 memset(&vbifmt, 0,
sizeof(
struct v4l2_format));
887 vbifmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
889 V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
891 if (ioctl(fd, VIDIOC_S_FMT, &vbifmt) < 0)
896 if (ioctl(fd, VIDIOC_S_FMT, &vbifmt) < 0)
898 LOG(VB_GENERAL, LOG_WARNING,
LOC +
899 "Unable to enable VBI embedding (/dev/vbiX)" +
ENO);
905 LOG(VB_GENERAL, LOG_WARNING,
LOC +
906 "Unable to enable VBI embedding (/dev/videoX)" +
ENO);
911 if (ioctl(fd, VIDIOC_G_FMT, &vbifmt) >= 0)
913 LOG(VB_RECORD, LOG_INFO,
914 LOC + QString(
"VBI service: %1, io size: %2")
915 .arg(vbifmt.fmt.sliced.service_set)
916 .arg(vbifmt.fmt.sliced.io_size));
918 struct v4l2_ext_control vbi_ctrl;
919 vbi_ctrl.id = V4L2_CID_MPEG_STREAM_VBI_FMT;
920 vbi_ctrl.value = V4L2_MPEG_STREAM_VBI_FMT_IVTV;
922 struct v4l2_ext_controls ctrls;
923 memset(&ctrls, 0,
sizeof(
struct v4l2_ext_controls));
924 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
926 ctrls.controls = &vbi_ctrl;
928 if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
930 LOG(VB_GENERAL, LOG_WARNING,
LOC +
931 "Unable to set VBI embedding format" +
ENO);
939 #endif // V4L2_CAP_SLICED_VBI_CAPTURE 955 _error =
"Failed to open V4L device";
959 bool has_select =
true;
961 #if defined(__FreeBSD__) 992 unsigned char *buffer =
new unsigned char[
bufferSize + 1];
996 bool good_data =
false;
1002 long long bytesRead = 0;
1005 if (getenv(
"DUMMYBPS"))
1007 dummyBPS = atoi(getenv(
"DUMMYBPS")) / 8;
1008 LOG(VB_GENERAL, LOG_INFO,
1009 LOC + QString(
"Throttling dummy recorder to %1 bits per second")
1010 .arg(dummyBPS * 8));
1017 elapsedTimer.
start();
1020 LOG(VB_RECORD, LOG_INFO,
LOC +
"Initial startup of recorder");
1032 if (dummyBPS && bytesRead)
1034 elapsed = (elapsedTimer.
elapsed() / 1000.0) + 1;
1035 while ((bytesRead / elapsed) > dummyBPS)
1037 std::this_thread::sleep_for(std::chrono::milliseconds(50));
1038 elapsed = (elapsedTimer.
elapsed() / 1000.0) + 1;
1043 elapsed = (elapsedTimer.
elapsed() / 1000.0) + 1;
1046 std::this_thread::sleep_for(std::chrono::milliseconds(50));
1047 elapsed = (elapsedTimer.
elapsed() / 1000.0) + 1;
1055 (&(buffer[remainder]),
bufferSize - remainder);
1060 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Device error detected");
1080 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Device EOF detected");
1081 _error =
"Device EOF detected";
1094 (gap_start, gap_end));
1095 LOG(VB_RECORD, LOG_DEBUG,
1096 LOC + QString(
"Inserted gap %1 dur %2")
1098 .arg(gap_start.secsTo(gap_end)));
1119 switch (select(
readfd + 1, &rdset,
nullptr,
nullptr, &tv))
1125 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Select error" +
ENO);
1129 LOG(VB_GENERAL, LOG_ERR,
LOC +
"select timeout - " 1130 "driver has stopped responding");
1134 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Close error" +
ENO);
1148 if (len < 0 && !has_select)
1159 readfd = open(vdevice.constData(), O_RDONLY);
1164 &(buffer[remainder]),
bufferSize - remainder);
1169 _error =
"Failed to read from video file";
1173 else if (len < 0 && errno != EAGAIN)
1175 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"error reading from: %1")
1189 int start_remain = len - remainder;
1190 if (remainder && (start_remain >= remainder))
1191 memcpy(buffer, buffer+start_remain, remainder);
1193 memmove(buffer, buffer+start_remain, remainder);
1202 LOG(VB_RECORD, LOG_INFO,
LOC +
"run finishing up");
1238 const uint pid = tspacket_real.
PID();
1241 if ((
driver ==
"hdpvr") && (pid == 0x1001))
1249 const TSPacket &tspacket = (tspacket_fake)
1250 ? *tspacket_fake : tspacket_real;
1255 delete tspacket_fake;
1262 LOG(VB_RECORD, LOG_INFO,
LOC +
"Reset(void)");
1290 LOG(VB_RECORD, LOG_INFO,
LOC +
"PauseAndWait pause");
1306 LOG(VB_RECORD, LOG_INFO,
LOC +
"PauseAndWait unpause");
1330 LOG(VB_RECORD, LOG_INFO,
LOC +
"RestartEncoding");
1356 LOG(VB_RECORD, LOG_INFO,
LOC +
"StartEncoding");
1363 LOG(VB_GENERAL, LOG_ERR,
LOC +
1364 "StartEncoding: Can't open video device." +
ENO);
1365 _error =
"Failed to start recording";
1370 bool good_res =
true;
1384 for ( ; idx < 50; ++idx)
1392 LOG(VB_GENERAL, LOG_ERR,
LOC +
1393 "StartEncoding: read failing, re-opening device: " +
ENO);
1395 std::this_thread::sleep_for(std::chrono::milliseconds(2));
1400 LOG(VB_GENERAL, LOG_ERR,
LOC +
1401 "StartEncoding: Can't open video device." +
ENO);
1402 _error =
"Failed to start recording";
1408 LOG(VB_GENERAL, LOG_ERR,
LOC +
1409 QString(
"StartEncoding: read failed, retry in %1 msec:")
1410 .arg(100 * idx) +
ENO);
1411 std::this_thread::sleep_for(std::chrono::microseconds(idx * 100));
1416 LOG(VB_GENERAL, LOG_ERR,
LOC +
1417 "StartEncoding: read from video device failed." +
ENO);
1418 _error =
"Failed to start recording";
1425 LOG(VB_RECORD, LOG_WARNING,
LOC +
1426 QString(
"%1 read attempts required to start encoding").arg(idx));
1446 LOG(VB_RECORD, LOG_INFO,
LOC +
"StopEncoding");
1451 struct v4l2_encoder_cmd command;
1452 memset(&command, 0,
sizeof(
struct v4l2_encoder_cmd));
1453 command.cmd = V4L2_ENC_CMD_STOP;
1454 command.flags = V4L2_ENC_CMD_STOP_AT_GOP_END;
1459 bool stopped = 0 == ioctl(
readfd, VIDIOC_ENCODER_CMD, &command);
1462 LOG(VB_RECORD, LOG_INFO,
LOC +
"Encoding stopped");
1464 else if (errno != ENOTTY && errno != EINVAL)
1470 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"StopEncoding failed" +
ENO);
1476 std::this_thread::sleep_for(std::chrono::milliseconds(20));
1492 const QString & reason)
1496 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"%1 bitrate %2 kbps CBR")
1501 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"%1 bitrate %2/%3 kbps VBR")
1505 vector<struct v4l2_ext_control> ext_ctrls;
1506 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
1508 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR :
1509 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
1514 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
1522 LOG(VB_RECORD, LOG_INFO,
LOC +
"Checking Resolution");
1524 struct v4l2_format vfmt;
1525 memset(&vfmt, 0,
sizeof(vfmt));
1526 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1528 if (0 == ioctl(
chanfd, VIDIOC_G_FMT, &vfmt))
1530 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Got Resolution %1x%2")
1531 .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
1532 pix = vfmt.fmt.pix.width * vfmt.fmt.pix.height;
1537 LOG(VB_RECORD, LOG_INFO,
LOC +
"Giving up detecting resolution: " +
ENO);
1547 else if (pix >= 1920*1080)
1561 if (old_max == old_avg)
1563 LOG(VB_RECORD, LOG_INFO,
LOC +
1564 QString(
"Old bitrate %1 CBR").arg(old_avg));
1568 LOG(VB_RECORD, LOG_INFO,
LOC +
1569 QString(
"Old bitrate %1/%2 VBR") .arg(old_avg).arg(old_max));
1580 LOG(VB_VBI, LOG_INFO,
LOC + QString(
"FormatCC(0x%1,0x%2)")
1581 .arg(code1,0,16).arg(code2,0,16));
QString _error
non-empty iff irrecoverable recording error detected
Used to access the data of a Transport Stream packet.
const ProgramAssociationTable * PATSingleProgram(void) const
bool IsRunning(void) const
A QElapsedTimer based timer to replace use of QTime as a timer.
bool ProcessTSPacket(const TSPacket &tspacket) override
unsigned int medium_mpeg4avgbitrate
QWaitCondition unpauseWait
void SetOption(const QString &name, const QString &value) override
Set an specific option.
uint GetInputId(void)
Returns the inputid.
RecordingInfo * curRecording
volatile bool request_helper
uint GetFilteredAudioSampleRate(void) const
void use_I_forKeyframes(bool val)
uint GetFilteredAudioLayer(void) const
void Reset(void) override
Reset the recorder to the startup state.
bool _wait_for_keyframe_option
Wait for the a GOP/SEQ-start before sending data.
void run(void) override
run() starts the recording process, and does not exit until the recording is complete.
bool wait(unsigned long time=ULONG_MAX)
Wait for the MThread to exit, with a maximum timeout.
void ResetForNewFile(void) override
static void set_ctrls(int fd, vector< struct v4l2_ext_control > &ext_ctrls)
void SetBitrate(int bitrate, int maxbitrate, const QString &reason)
bool SetV4L2DeviceOptions(int chanfd)
QWaitCondition recordingWait
void HandleSingleProgramPAT(ProgramAssociationTable *pat, bool insert) override
void CloseVBIDevice(void)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
bool IsErrored(void) override
Tells us whether an unrecoverable error has been encountered.
int DesiredProgram(void) const
unsigned int high_mpeg4avgbitrate
void SetOption(const QString &opt, int value) override
handles the "wait_for_seqstart" option.
bool SetVBIOptions(int chanfd)
QMutex start_stop_encoding_lock
bool PauseAndWait(int timeout=100) override
If request_pause is true, sets pause and blocks up to timeout milliseconds or until unpaused,...
static bool GetV4LInfo(int videofd, QString &input, QString &driver, uint32_t &version, uint32_t &capabilities)
bool IsErrored(void) const
def read(device=None, features=[])
virtual QString getValue(void) const
MPEGStreamData * _stream_data
virtual bool IsPaused(bool holding_lock=false) const
Returns true iff recorder is paused.
uint Read(unsigned char *buf, uint count)
Try to Read count bytes from into buffer.
AVContainer m_containerFormat
Abstract base class for Video4Linux based recorders.
void FinishRecording(void) override
Flushes the ringbuffer, and if this is not a live LiveTV recording saves the position map and filesiz...
DeviceReadBuffer * _device_read_buffer
long long GetFramesWritten(void) override
Returns number of frames written to disk.
bool recording
True while recording is actually being performed.
RecordingGaps recordingGaps
This is the coordinating class of the Recorder Subsystem.
static void clear(SettingsMap &cache, SettingsMap &overrides, const QString &myKey)
bool request_recording
True if API call has requested a recording be [re]started.
static const char * streamType[]
unsigned int medium_mpeg4peakbitrate
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
QString GetSetting(const QString &key, const QString &defaultval="")
void SetDesiredProgram(int p)
bool HandleResolutionChanges(void)
void AddMPEGSPListener(MPEGSingleProgramStreamListener *)
void SetRequestPause(bool request)
void RemoveWritingListener(TSPacketListener *)
void RecorderPaused(void)
This is a callback, called by the "recorder" instance when it has actually paused.
uint GetFilteredStreamType(void) const
void AddAVListener(TSPacketListenerAV *)
virtual void SetRecordingStatus(RecStatus::Type status, const QString &file, int line)
virtual int ProcessData(const unsigned char *buffer, int len)
#define ENO
This can be appended to the LOG args with "+".
bool OpenV4L2DeviceAsInput(void)
static const int audRateL3[]
static const int audRateL2[]
void StopRecording(void) override
StopRecording() signals to the recorder that it should stop recording and exit cleanly.
bool SetVideoCaptureFormat(int chanfd)
void InitStreamData(void) override
int elapsed(void) const
Returns milliseconds elapsed since last start() or restart()
unsigned int low_mpeg4peakbitrate
void Pause(bool clear=true) override
Pause tells recorder to pause, it should not block.
void SetRecordingType(const QString &recording_type)
void Reset(const QString &streamName, int streamfd)
bool SetLanguageMode(int chanfd)
Set audio language mode.
#define LOG(_MASK_, _LEVEL_, _STRING_)
bool OpenMpegFileAsInput(void)
static const unsigned int kSize
const ProgramMapTable * PMTSingleProgram(void) const
uint GetFilteredAudioBitRate(uint audio_layer) const
void SetIntOption(RecordingProfile *profile, const QString &name)
bool Setup(const QString &streamName, int streamfd, uint readQuanta=sizeof(TSPacket), uint deviceBufferSize=0, uint deviceBufferCount=1)
bool ProcessTSPacket(const TSPacket &tspacket) override
bool RestartEncoding(void)
void AddWritingListener(TSPacketListener *)
unsigned int language
0 is Main Lang; 1 is SAP Lang; 2 is Dual
unsigned int low_mpeg4avgbitrate
unsigned int high_mpeg4peakbitrate
Buffers reads from device files.
bool SetRecordingVolume(int chanfd)
virtual void SetStreamData(MPEGStreamData *sd)
static const char * aspectRatio[]
void RemoveAVListener(TSPacketListenerAV *)
TSPacket * CreateClone() const
static const int audRateL1[]
void SetStrOption(RecordingProfile *profile, const QString &name)
void start(void)
starts measuring elapsed time.
void FormatCC(uint code1, uint code2) override
vector< unsigned char > _payload_buffer
void ClearPositionMap(MarkTypes type) const
Encapsulates data about MPEG stream and emits events for each table.
void FindPSKeyFrames(const uint8_t *buffer, uint len) override
void HandleSingleProgramPMT(ProgramMapTable *pmt, bool insert) override
static int find_index(const int *audio_rate, int value)
static void add_ext_ctrl(vector< struct v4l2_ext_control > &ctrl_list, uint32_t id, int32_t value)
static int streamtype_ivtv_to_v4l2(int st)
void SetOptionsFromProfile(RecordingProfile *profile, const QString &videodev, const QString &audiodev, const QString &vbidev) override
Sets basic recorder options.
unsigned char _continuity_counter[0x1fff+1]
virtual bool IsRecordingRequested(void)
Tells us if StopRecording() has been called.