00001
00002
00003
00004 #include <ctime>
00005
00006
00007 #include <algorithm>
00008 #include <vector>
00009 using namespace std;
00010
00011
00012 #include <fcntl.h>
00013 #include <unistd.h>
00014 #include <inttypes.h>
00015
00016
00017 #include <sys/types.h>
00018 #include <sys/stat.h>
00019 #include <sys/ioctl.h>
00020 #include <sys/time.h>
00021 #include <sys/poll.h>
00022
00023 #include <linux/videodev2.h>
00024
00025 #include "mythconfig.h"
00026
00027
00028 extern "C" {
00029 #include "libavcodec/avcodec.h"
00030 }
00031
00032
00033 #include "mpegrecorder.h"
00034 #include "ringbuffer.h"
00035 #include "mythcorecontext.h"
00036 #include "programinfo.h"
00037 #include "recordingprofile.h"
00038 #include "tv_rec.h"
00039 #include "mythmiscutil.h"
00040 #include "cardutil.h"
00041
00042
00043 extern "C" {
00044 #include "ivtv_myth.h"
00045 }
00046
00047 #define IVTV_KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
00048
00049 #define LOC QString("MPEGRec(%1): ").arg(videodevice)
00050
00051 const int MpegRecorder::audRateL1[] =
00052 {
00053 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0
00054 };
00055
00056 const int MpegRecorder::audRateL2[] =
00057 {
00058 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0
00059 };
00060
00061 const int MpegRecorder::audRateL3[] =
00062 {
00063 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0
00064 };
00065
00066 const char* MpegRecorder::streamType[] =
00067 {
00068 "MPEG-2 PS", "MPEG-2 TS", "MPEG-1 VCD", "PES AV",
00069 "", "PES V", "", "PES A",
00070 "", "", "DVD", "VCD",
00071 "SVCD", "DVD-Special 1", "DVD-Special 2", 0
00072 };
00073
00074 const char* MpegRecorder::aspectRatio[] =
00075 {
00076 "Square", "4:3", "16:9", "2.21:1", 0
00077 };
00078
00079 MpegRecorder::MpegRecorder(TVRec *rec) :
00080 V4LRecorder(rec),
00081
00082 deviceIsMpegFile(false), bufferSize(0),
00083
00084 card(QString::null), driver(QString::null),
00085 version(0),
00086 supports_sliced_vbi(false),
00087
00088 start_stop_encoding_lock(QMutex::Recursive),
00089
00090 cleartimeonpause(false),
00091
00092 width(720), height(480),
00093 bitrate(4500), maxbitrate(6000),
00094 streamtype(0), aspectratio(2),
00095 audtype(2), audsamplerate(48000),
00096 audbitratel1(14), audbitratel2(14),
00097 audbitratel3(10),
00098 audvolume(80), language(0),
00099 low_mpeg4avgbitrate(4500), low_mpeg4peakbitrate(6000),
00100 medium_mpeg4avgbitrate(9000), medium_mpeg4peakbitrate(13500),
00101 high_mpeg4avgbitrate(13500), high_mpeg4peakbitrate(20200),
00102
00103 chanfd(-1), readfd(-1),
00104 _device_read_buffer(NULL)
00105 {
00106 }
00107
00108 MpegRecorder::~MpegRecorder()
00109 {
00110 TeardownAll();
00111 }
00112
00113 void MpegRecorder::TeardownAll(void)
00114 {
00115 StopRecording();
00116
00117 if (chanfd >= 0)
00118 {
00119 close(chanfd);
00120 chanfd = -1;
00121 }
00122 if (readfd >= 0)
00123 {
00124 close(readfd);
00125 readfd = -1;
00126 }
00127 }
00128
00129 static int find_index(const int *audio_rate, int value)
00130 {
00131 for (uint i = 0; audio_rate[i] != 0; i++)
00132 {
00133 if (audio_rate[i] == value)
00134 return i;
00135 }
00136
00137 return -1;
00138 }
00139
00140 void MpegRecorder::SetOption(const QString &opt, int value)
00141 {
00142 if (opt == "width")
00143 width = value;
00144 else if (opt == "height")
00145 height = value;
00146 else if (opt == "mpeg2bitrate")
00147 bitrate = value;
00148 else if (opt == "mpeg2maxbitrate")
00149 maxbitrate = value;
00150 else if (opt == "samplerate")
00151 audsamplerate = value;
00152 else if (opt == "mpeg2audbitratel1")
00153 {
00154 int index = find_index(audRateL1, value);
00155 if (index >= 0)
00156 audbitratel1 = index + 1;
00157 else
00158 {
00159 LOG(VB_GENERAL, LOG_ERR, LOC + "Audiorate(L1): " +
00160 QString("%1 is invalid").arg(value));
00161 }
00162 }
00163 else if (opt == "mpeg2audbitratel2")
00164 {
00165 int index = find_index(audRateL2, value);
00166 if (index >= 0)
00167 audbitratel2 = index + 1;
00168 else
00169 {
00170 LOG(VB_GENERAL, LOG_ERR, LOC + "Audiorate(L2): " +
00171 QString("%1 is invalid").arg(value));
00172 }
00173 }
00174 else if (opt == "mpeg2audbitratel3")
00175 {
00176 int index = find_index(audRateL3, value);
00177 if (index >= 0)
00178 audbitratel3 = index + 1;
00179 else
00180 {
00181 LOG(VB_GENERAL, LOG_ERR, LOC + "Audiorate(L2): " +
00182 QString("%1 is invalid").arg(value));
00183 }
00184 }
00185 else if (opt == "mpeg2audvolume")
00186 audvolume = value;
00187 else if (opt.right(16) == "_mpeg4avgbitrate")
00188 {
00189 if (opt.left(3) == "low")
00190 low_mpeg4avgbitrate = value;
00191 else if (opt.left(6) == "medium")
00192 medium_mpeg4avgbitrate = value;
00193 else if (opt.left(4) == "high")
00194 high_mpeg4avgbitrate = value;
00195 else
00196 V4LRecorder::SetOption(opt, value);
00197 }
00198 else if (opt.right(17) == "_mpeg4peakbitrate")
00199 {
00200 if (opt.left(3) == "low")
00201 low_mpeg4peakbitrate = value;
00202 else if (opt.left(6) == "medium")
00203 medium_mpeg4peakbitrate = value;
00204 else if (opt.left(4) == "high")
00205 high_mpeg4peakbitrate = value;
00206 else
00207 V4LRecorder::SetOption(opt, value);
00208 }
00209 else
00210 V4LRecorder::SetOption(opt, value);
00211 }
00212
00213 void MpegRecorder::SetOption(const QString &opt, const QString &value)
00214 {
00215 if (opt == "mpeg2streamtype")
00216 {
00217 bool found = false;
00218 for (unsigned int i = 0; i < sizeof(streamType) / sizeof(char*); i++)
00219 {
00220 if (QString(streamType[i]) == value)
00221 {
00222 streamtype = i;
00223 found = true;
00224 break;
00225 }
00226 }
00227
00228 if (!found)
00229 {
00230 LOG(VB_GENERAL, LOG_ERR, LOC + "MPEG2 stream type: " +
00231 QString("%1 is invalid").arg(value));
00232 }
00233 }
00234 else if (opt == "mpeg2language")
00235 {
00236 bool ok = false;
00237 language = value.toInt(&ok);
00238 if (!ok)
00239 {
00240 LOG(VB_GENERAL, LOG_ERR, LOC + "MPEG2 language (stereo) flag " +
00241 QString("'%1' is invalid").arg(value));
00242 }
00243 }
00244 else if (opt == "mpeg2aspectratio")
00245 {
00246 bool found = false;
00247 for (int i = 0; aspectRatio[i] != 0; i++)
00248 {
00249 if (QString(aspectRatio[i]) == value)
00250 {
00251 aspectratio = i + 1;
00252 found = true;
00253 break;
00254 }
00255 }
00256
00257 if (!found)
00258 {
00259 LOG(VB_GENERAL, LOG_ERR, LOC + "MPEG2 Aspect-ratio: " +
00260 QString("%1 is invalid").arg(value));
00261 }
00262 }
00263 else if (opt == "mpeg2audtype")
00264 {
00265 if (value == "Layer I")
00266 audtype = 1;
00267 else if (value == "Layer II")
00268 audtype = 2;
00269 else if (value == "Layer III")
00270 audtype = 3;
00271 else
00272 {
00273 LOG(VB_GENERAL, LOG_ERR, LOC + "MPEG2 audio layer: " +
00274 QString("%1 is invalid").arg(value));
00275 }
00276 }
00277 else if (opt == "audiocodec")
00278 {
00279 if (value == "AAC Hardware Encoder")
00280 audtype = 4;
00281 else if (value == "AC3 Hardware Encoder")
00282 audtype = 5;
00283 }
00284 else
00285 {
00286 V4LRecorder::SetOption(opt, value);
00287 }
00288 }
00289
00290 void MpegRecorder::SetOptionsFromProfile(RecordingProfile *profile,
00291 const QString &videodev,
00292 const QString &audiodev,
00293 const QString &vbidev)
00294 {
00295 (void)audiodev;
00296 (void)vbidev;
00297
00298 if (videodev.toLower().left(5) == "file:")
00299 {
00300 deviceIsMpegFile = true;
00301 bufferSize = 64000;
00302 QString newVideoDev = videodev;
00303 if (newVideoDev.startsWith("file:", Qt::CaseInsensitive))
00304 newVideoDev = newVideoDev.remove(0,5);
00305 SetOption("videodevice", newVideoDev);
00306 }
00307 else
00308 {
00309 SetOption("videodevice", videodev);
00310 }
00311 SetOption("vbidevice", vbidev);
00312 SetOption("audiodevice", audiodev);
00313
00314 SetOption("tvformat", gCoreContext->GetSetting("TVFormat"));
00315 SetOption("vbiformat", gCoreContext->GetSetting("VbiFormat"));
00316
00317 SetIntOption(profile, "mpeg2bitrate");
00318 SetIntOption(profile, "mpeg2maxbitrate");
00319 SetStrOption(profile, "mpeg2streamtype");
00320 SetStrOption(profile, "mpeg2aspectratio");
00321 SetStrOption(profile, "mpeg2language");
00322
00323 SetIntOption(profile, "samplerate");
00324 SetStrOption(profile, "mpeg2audtype");
00325 SetIntOption(profile, "mpeg2audbitratel1");
00326 SetIntOption(profile, "mpeg2audbitratel2");
00327 SetIntOption(profile, "mpeg2audbitratel3");
00328 SetIntOption(profile, "mpeg2audvolume");
00329
00330 SetIntOption(profile, "width");
00331 SetIntOption(profile, "height");
00332
00333 SetIntOption(profile, "low_mpeg4avgbitrate");
00334 SetIntOption(profile, "low_mpeg4peakbitrate");
00335 SetIntOption(profile, "medium_mpeg4avgbitrate");
00336 SetIntOption(profile, "medium_mpeg4peakbitrate");
00337 SetIntOption(profile, "high_mpeg4avgbitrate");
00338 SetIntOption(profile, "high_mpeg4peakbitrate");
00339
00340 SetStrOption(profile, "audiocodec");
00341 }
00342
00343
00344 void MpegRecorder::SetIntOption(RecordingProfile *profile, const QString &name)
00345 {
00346 const Setting *setting = profile->byName(name);
00347 if (setting)
00348 SetOption(name, setting->getValue().toInt());
00349 }
00350
00351
00352 void MpegRecorder::SetStrOption(RecordingProfile *profile, const QString &name)
00353 {
00354 const Setting *setting = profile->byName(name);
00355 if (setting)
00356 SetOption(name, setting->getValue());
00357 }
00358
00359 bool MpegRecorder::OpenMpegFileAsInput(void)
00360 {
00361 QByteArray vdevice = videodevice.toAscii();
00362 chanfd = readfd = open(vdevice.constData(), O_RDONLY);
00363
00364 if (readfd < 0)
00365 {
00366 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Can't open MPEG File '%1'")
00367 .arg(videodevice) + ENO);
00368
00369 return false;
00370 }
00371 return true;
00372 }
00373
00374 bool MpegRecorder::OpenV4L2DeviceAsInput(void)
00375 {
00376
00377 QMutexLocker locker(&start_stop_encoding_lock);
00378
00379 QByteArray vdevice = videodevice.toAscii();
00380 chanfd = open(vdevice.constData(), O_RDWR);
00381 if (chanfd < 0)
00382 {
00383 LOG(VB_GENERAL, LOG_ERR, LOC + "Can't open video device. " + ENO);
00384 return false;
00385 }
00386
00387 bufferSize = 4096;
00388
00389 bool supports_tuner = false, supports_audio = false;
00390 uint32_t capabilities = 0;
00391 if (CardUtil::GetV4LInfo(chanfd, card, driver, version, capabilities))
00392 {
00393 supports_sliced_vbi = !!(capabilities & V4L2_CAP_SLICED_VBI_CAPTURE);
00394 supports_tuner = !!(capabilities & V4L2_CAP_TUNER);
00395 supports_audio = !!(capabilities & V4L2_CAP_AUDIO);
00397 if (driver == "hdpvr")
00398 {
00399 bufferSize = 1500 * TSPacket::kSize;
00400 m_h264_parser.use_I_forKeyframes(false);
00401 }
00402 }
00403
00404 if (!(capabilities & V4L2_CAP_VIDEO_CAPTURE))
00405 {
00406 LOG(VB_GENERAL, LOG_ERR, LOC + "V4L version 1, unsupported");
00407 close(chanfd);
00408 chanfd = -1;
00409 return false;
00410 }
00411
00412 if (!SetVideoCaptureFormat(chanfd))
00413 {
00414 close(chanfd);
00415 chanfd = -1;
00416 return false;
00417 }
00418
00419 if (supports_tuner)
00420 SetLanguageMode(chanfd);
00421
00422 if (supports_audio)
00423 SetRecordingVolume(chanfd);
00424
00425 if (!SetV4L2DeviceOptions(chanfd))
00426 {
00427 close(chanfd);
00428 chanfd = -1;
00429 return false;
00430 }
00431
00432 SetVBIOptions(chanfd);
00433
00434 readfd = open(vdevice.constData(), O_RDWR | O_NONBLOCK);
00435
00436 if (readfd < 0)
00437 {
00438 LOG(VB_GENERAL, LOG_ERR, LOC + "Can't open video device." + ENO);
00439 close(chanfd);
00440 chanfd = -1;
00441 return false;
00442 }
00443
00444 if (_device_read_buffer)
00445 {
00446 if (_device_read_buffer->IsRunning())
00447 _device_read_buffer->Stop();
00448
00449 delete _device_read_buffer;
00450 _device_read_buffer = NULL;
00451 }
00452
00453 _device_read_buffer = new DeviceReadBuffer(this);
00454
00455 if (!_device_read_buffer)
00456 {
00457 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to allocate DRB buffer");
00458 _error = "Failed to allocate DRB buffer";
00459 close(chanfd);
00460 chanfd = -1;
00461 close(readfd);
00462 readfd = -1;
00463 return false;
00464 }
00465
00466 if (!_device_read_buffer->Setup(vdevice.constData(), readfd))
00467 {
00468 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to setup DRB buffer");
00469 _error = "Failed to setup DRB buffer";
00470 close(chanfd);
00471 chanfd = -1;
00472 close(readfd);
00473 readfd = -1;
00474 return false;
00475 }
00476
00477 LOG(VB_RECORD, LOG_INFO, LOC + "DRB ready");
00478
00479 if (vbi_fd >= 0)
00480 vbi_thread = new VBIThread(this);
00481
00482 return true;
00483 }
00484
00485
00486 bool MpegRecorder::SetVideoCaptureFormat(int chanfd)
00487 {
00488 if (driver == "hdpvr")
00489 return true;
00490
00491 struct v4l2_format vfmt;
00492 memset(&vfmt, 0, sizeof(vfmt));
00493
00494 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00495
00496 if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) < 0)
00497 {
00498 LOG(VB_GENERAL, LOG_ERR, LOC + "Error getting format" + ENO);
00499 return false;
00500 }
00501
00502 vfmt.fmt.pix.width = width;
00503 vfmt.fmt.pix.height = height;
00504
00505 if (ioctl(chanfd, VIDIOC_S_FMT, &vfmt) < 0)
00506 {
00507 LOG(VB_GENERAL, LOG_ERR, LOC + "Error setting format" + ENO);
00508 return false;
00509 }
00510
00511 return true;
00512 }
00513
00515 bool MpegRecorder::SetLanguageMode(int chanfd)
00516 {
00517 struct v4l2_tuner vt;
00518 memset(&vt, 0, sizeof(struct v4l2_tuner));
00519 if (ioctl(chanfd, VIDIOC_G_TUNER, &vt) < 0)
00520 {
00521 LOG(VB_GENERAL, LOG_WARNING, LOC + "Unable to get audio mode" + ENO);
00522 return false;
00523 }
00524
00525 switch (language)
00526 {
00527 case 0:
00528 vt.audmode = V4L2_TUNER_MODE_LANG1;
00529 break;
00530 case 1:
00531 vt.audmode = V4L2_TUNER_MODE_LANG2;
00532 break;
00533 case 2:
00534 vt.audmode = V4L2_TUNER_MODE_LANG1_LANG2;
00535 break;
00536 default:
00537 vt.audmode = V4L2_TUNER_MODE_LANG1;
00538 }
00539
00540 int audio_layer = GetFilteredAudioLayer();
00541 bool success = true;
00542 if ((2 == language) && (1 == audio_layer))
00543 {
00544 LOG(VB_GENERAL, LOG_WARNING,
00545 "Dual audio mode incompatible with Layer I audio."
00546 "\n\t\t\tFalling back to Main Language");
00547 vt.audmode = V4L2_TUNER_MODE_LANG1;
00548 success = false;
00549 }
00550
00551 if (ioctl(chanfd, VIDIOC_S_TUNER, &vt) < 0)
00552 {
00553 LOG(VB_GENERAL, LOG_WARNING, LOC + "Unable to set audio mode" + ENO);
00554 success = false;
00555 }
00556
00557 return success;
00558 }
00559
00560 bool MpegRecorder::SetRecordingVolume(int chanfd)
00561 {
00562
00563 struct v4l2_queryctrl qctrl;
00564 memset(&qctrl, 0 , sizeof(struct v4l2_queryctrl));
00565 qctrl.id = V4L2_CID_AUDIO_VOLUME;
00566 if ((ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) < 0) ||
00567 (qctrl.flags & V4L2_CTRL_FLAG_DISABLED))
00568 {
00569 LOG(VB_CHANNEL, LOG_WARNING,
00570 LOC + "Audio volume control not supported.");
00571 return false;
00572 }
00573
00574
00575 int range = qctrl.maximum - qctrl.minimum;
00576 int value = (int) ((range * audvolume * 0.01f) + qctrl.minimum);
00577 int ctrl_volume = min(qctrl.maximum, max(qctrl.minimum, value));
00578
00579
00580 struct v4l2_control ctrl;
00581 ctrl.id = V4L2_CID_AUDIO_VOLUME;
00582 ctrl.value = ctrl_volume;
00583
00584 if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) < 0)
00585 {
00586 LOG(VB_GENERAL, LOG_WARNING, LOC +
00587 "Unable to set recording volume" + ENO + "\n\t\t\t" +
00588 "If you are using an AverMedia M179 card this is normal.");
00589 return false;
00590 }
00591
00592 return true;
00593 }
00594
00595 uint MpegRecorder::GetFilteredStreamType(void) const
00596 {
00597 uint st = (uint) streamtype;
00598
00599 if (driver == "ivtv")
00600 {
00601 switch (st)
00602 {
00603 case 2: st = 2; break;
00604 case 10:
00605 case 13:
00606 case 14: st = 10; break;
00607 case 11: st = 11; break;
00608 case 12: st = 12; break;
00609 default: st = 0; break;
00610 }
00611 }
00612
00613 if (st != (uint) streamtype)
00614 {
00615 LOG(VB_GENERAL, LOG_WARNING, LOC +
00616 QString("Stream type '%1'\n\t\t\t"
00617 "is not supported by %2 driver, using '%3' instead.")
00618 .arg(streamType[streamtype]).arg(driver).arg(streamType[st]));
00619 }
00620
00621 return st;
00622 }
00623
00624 uint MpegRecorder::GetFilteredAudioSampleRate(void) const
00625 {
00626 uint sr = (uint) audsamplerate;
00627
00628 sr = (driver == "ivtv") ? 48000 : sr;
00629
00630 if (sr != (uint) audsamplerate)
00631 {
00632 LOG(VB_GENERAL, LOG_WARNING, LOC +
00633 QString("Audio sample rate %1 Hz\n\t\t\t"
00634 "is not supported by %2 driver, using %3 Hz instead.")
00635 .arg(audsamplerate).arg(driver).arg(sr));
00636 }
00637
00638 switch (sr)
00639 {
00640 case 32000: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000;
00641 case 44100: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100;
00642 case 48000: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
00643 default: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
00644 }
00645 }
00646
00647 uint MpegRecorder::GetFilteredAudioLayer(void) const
00648 {
00649 uint layer = (uint) audtype;
00650
00651 layer = max(min(layer, 3U), 1U);
00652
00653 layer = (driver == "ivtv") ? 2 : layer;
00654
00655 if (layer != (uint) audtype)
00656 {
00657 LOG(VB_GENERAL, LOG_WARNING, LOC +
00658 QString("MPEG layer %1 does not work properly\n\t\t\t"
00659 "with %2 driver. Using MPEG layer %3 audio instead.")
00660 .arg(audtype).arg(driver).arg(layer));
00661 }
00662
00663 return layer;
00664 }
00665
00666 uint MpegRecorder::GetFilteredAudioBitRate(uint audio_layer) const
00667 {
00668 return ((2 == audio_layer) ? max(audbitratel2, 10) :
00669 ((3 == audio_layer) ? audbitratel3 : max(audbitratel1, 6)));
00670 }
00671
00672 static int streamtype_ivtv_to_v4l2(int st)
00673 {
00674 switch (st)
00675 {
00676 case 0: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
00677 case 1: return V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
00678 case 2: return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD;
00679 case 3: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
00680 case 5: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
00681 case 7: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
00682 case 10: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
00683 case 11: return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD;
00684 case 12: return V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD;
00685 case 13: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
00686 case 14: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
00687 default: return V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
00688 }
00689 }
00690
00691 static void add_ext_ctrl(vector<struct v4l2_ext_control> &ctrl_list,
00692 uint32_t id, int32_t value)
00693 {
00694 struct v4l2_ext_control tmp_ctrl;
00695 memset(&tmp_ctrl, 0, sizeof(struct v4l2_ext_control));
00696 tmp_ctrl.id = id;
00697 tmp_ctrl.value = value;
00698 ctrl_list.push_back(tmp_ctrl);
00699 }
00700
00701 static void set_ctrls(int fd, vector<struct v4l2_ext_control> &ext_ctrls)
00702 {
00703 static QMutex control_description_lock;
00704 static QMap<uint32_t,QString> control_description;
00705
00706 control_description_lock.lock();
00707 if (control_description.isEmpty())
00708 {
00709 control_description[V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ] =
00710 "Audio Sampling Frequency";
00711 control_description[V4L2_CID_MPEG_VIDEO_ASPECT] =
00712 "Video Aspect ratio";
00713 control_description[V4L2_CID_MPEG_AUDIO_ENCODING] =
00714 "Audio Encoding";
00715 control_description[V4L2_CID_MPEG_AUDIO_L2_BITRATE] =
00716 "Audio L2 Bitrate";
00717 control_description[V4L2_CID_MPEG_VIDEO_BITRATE_PEAK] =
00718 "Video Peak Bitrate";
00719 control_description[V4L2_CID_MPEG_VIDEO_BITRATE] =
00720 "Video Average Bitrate";
00721 control_description[V4L2_CID_MPEG_STREAM_TYPE] =
00722 "MPEG Stream type";
00723 control_description[V4L2_CID_MPEG_VIDEO_BITRATE_MODE] =
00724 "MPEG Bitrate mode";
00725 }
00726 control_description_lock.unlock();
00727
00728 for (uint i = 0; i < ext_ctrls.size(); i++)
00729 {
00730 struct v4l2_ext_controls ctrls;
00731 memset(&ctrls, 0, sizeof(struct v4l2_ext_controls));
00732
00733 int value = ext_ctrls[i].value;
00734
00735 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
00736 ctrls.count = 1;
00737 ctrls.controls = &ext_ctrls[i];
00738
00739 if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
00740 {
00741 QMutexLocker locker(&control_description_lock);
00742 LOG(VB_GENERAL, LOG_ERR, QString("mpegrecorder.cpp:set_ctrls(): ") +
00743 QString("Could not set %1 to %2")
00744 .arg(control_description[ext_ctrls[i].id]).arg(value) +
00745 ENO);
00746 }
00747 }
00748 }
00749
00750 bool MpegRecorder::SetV4L2DeviceOptions(int chanfd)
00751 {
00752 vector<struct v4l2_ext_control> ext_ctrls;
00753
00754
00755 if (driver != "hdpvr")
00756 {
00757 if (driver.left(7) != "saa7164")
00758 {
00759 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
00760 GetFilteredAudioSampleRate());
00761
00762 uint audio_layer = GetFilteredAudioLayer();
00763 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_ENCODING,
00764 audio_layer - 1);
00765
00766 uint audbitrate = GetFilteredAudioBitRate(audio_layer);
00767 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_L2_BITRATE,
00768 audbitrate - 1);
00769 }
00770
00771 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_ASPECT,
00772 aspectratio - 1);
00773
00774 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_STREAM_TYPE,
00775 streamtype_ivtv_to_v4l2(GetFilteredStreamType()));
00776
00777 }
00778 else
00779 {
00780 maxbitrate = high_mpeg4peakbitrate;
00781 bitrate = high_mpeg4avgbitrate;
00782 }
00783 maxbitrate = std::max(maxbitrate, bitrate);
00784
00785 if (driver == "hdpvr" || driver.left(7) == "saa7164")
00786 {
00787 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
00788 (maxbitrate == bitrate) ?
00789 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR :
00790 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
00791 }
00792
00793 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE,
00794 bitrate * 1000);
00795
00796 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
00797 maxbitrate * 1000);
00798
00799 set_ctrls(chanfd, ext_ctrls);
00800
00801 bool ok;
00802 int audioinput = audiodevice.toUInt(&ok);
00803 if (ok)
00804 {
00805 struct v4l2_audio ain;
00806 memset(&ain, 0, sizeof(ain));
00807 ain.index = audioinput;
00808 if (ioctl(chanfd, VIDIOC_ENUMAUDIO, &ain) < 0)
00809 {
00810 LOG(VB_GENERAL, LOG_WARNING, LOC + "Unable to get audio input.");
00811 }
00812 else
00813 {
00814 ain.index = audioinput;
00815 if (ioctl(chanfd, VIDIOC_S_AUDIO, &ain) < 0)
00816 {
00817 LOG(VB_GENERAL, LOG_WARNING,
00818 LOC + "Unable to set audio input.");
00819 }
00820 }
00821 }
00822
00823
00824 if (driver == "hdpvr" && audioinput != 2)
00825 {
00826 struct v4l2_queryctrl qctrl;
00827 qctrl.id = V4L2_CID_MPEG_AUDIO_ENCODING;
00828
00829 if (!ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl))
00830 {
00831 uint audio_enc = max(min(audtype-1, qctrl.maximum), qctrl.minimum);
00832 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_ENCODING, audio_enc);
00833 }
00834 else
00835 {
00836 LOG(VB_GENERAL, LOG_WARNING, LOC +
00837 "Unable to get supported audio codecs." + ENO);
00838 }
00839 }
00840
00841 return true;
00842 }
00843
00844 bool MpegRecorder::SetVBIOptions(int chanfd)
00845 {
00846 if (VBIMode::None == vbimode)
00847 return true;
00848
00849 if (driver == "hdpvr")
00850 return true;
00851
00852 #ifdef V4L2_CAP_SLICED_VBI_CAPTURE
00853 if (supports_sliced_vbi)
00854 {
00855 struct v4l2_format vbifmt;
00856 memset(&vbifmt, 0, sizeof(struct v4l2_format));
00857 vbifmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
00858 vbifmt.fmt.sliced.service_set |= (VBIMode::PAL_TT == vbimode) ?
00859 V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
00860
00861 if (ioctl(chanfd, VIDIOC_S_FMT, &vbifmt) < 0)
00862 {
00863 LOG(VB_GENERAL, LOG_WARNING, LOC +
00864 "Unable to enable VBI embedding" + ENO);
00865 }
00866 else if (ioctl(chanfd, VIDIOC_G_FMT, &vbifmt) >= 0)
00867 {
00868 LOG(VB_RECORD, LOG_INFO,
00869 LOC + QString("VBI service: %1, io size: %2")
00870 .arg(vbifmt.fmt.sliced.service_set)
00871 .arg(vbifmt.fmt.sliced.io_size));
00872
00873 struct v4l2_ext_control vbi_ctrl;
00874 vbi_ctrl.id = V4L2_CID_MPEG_STREAM_VBI_FMT;
00875 vbi_ctrl.value = V4L2_MPEG_STREAM_VBI_FMT_IVTV;
00876
00877 struct v4l2_ext_controls ctrls;
00878 memset(&ctrls, 0, sizeof(struct v4l2_ext_controls));
00879 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
00880 ctrls.count = 1;
00881 ctrls.controls = &vbi_ctrl;
00882
00883 if (ioctl(chanfd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
00884 {
00885 LOG(VB_GENERAL, LOG_WARNING, LOC +
00886 "Unable to set VBI embedding format" + ENO);
00887 }
00888 else
00889 {
00890 return true;
00891 }
00892 }
00893 }
00894 #endif // V4L2_CAP_SLICED_VBI_CAPTURE
00895
00896 return OpenVBIDevice() >= 0;
00897 }
00898
00899 bool MpegRecorder::Open(void)
00900 {
00901 ResetForNewFile();
00902 return (deviceIsMpegFile) ? OpenMpegFileAsInput() : OpenV4L2DeviceAsInput();
00903 }
00904
00905 void MpegRecorder::run(void)
00906 {
00907 if (!Open())
00908 {
00909 if (_error.isEmpty())
00910 _error = "Failed to open V4L device";
00911 return;
00912 }
00913
00914 bool has_select = true;
00915
00916 #if defined(__FreeBSD__)
00917
00918 has_select = false;
00919 #endif
00920
00921 if (driver == "hdpvr")
00922 {
00923 int progNum = 1;
00924 MPEGStreamData *sd = new MPEGStreamData(progNum, true);
00925 sd->SetRecordingType(_recording_type);
00926 DTVRecorder::SetStreamData(sd);
00927
00928 _stream_data->AddAVListener(this);
00929 _stream_data->AddWritingListener(this);
00930
00931
00932 _wait_for_keyframe_option = false;
00933 HandleSingleProgramPAT(_stream_data->PATSingleProgram());
00934 HandleSingleProgramPMT(_stream_data->PMTSingleProgram());
00935 _wait_for_keyframe_option = true;
00936 }
00937
00938 {
00939 QMutexLocker locker(&pauseLock);
00940 request_recording = true;
00941 request_helper = true;
00942 recording = true;
00943 recordingWait.wakeAll();
00944 }
00945
00946 unsigned char *buffer = new unsigned char[bufferSize + 1];
00947 int len;
00948 int remainder = 0;
00949
00950 MythTimer elapsedTimer;
00951 float elapsed;
00952 long long bytesRead = 0;
00953 int dummyBPS = 0;
00954
00955 if (getenv("DUMMYBPS"))
00956 {
00957 dummyBPS = atoi(getenv("DUMMYBPS")) / 8;
00958 LOG(VB_GENERAL, LOG_INFO,
00959 LOC + QString("Throttling dummy recorder to %1 bits per second")
00960 .arg(dummyBPS * 8));
00961 }
00962
00963 struct timeval tv;
00964 fd_set rdset;
00965
00966 if (deviceIsMpegFile)
00967 elapsedTimer.start();
00968 else if (_device_read_buffer)
00969 {
00970 LOG(VB_RECORD, LOG_INFO, LOC + "Initial startup of recorder");
00971 StartEncoding();
00972 }
00973
00974 QByteArray vdevice = videodevice.toAscii();
00975 while (IsRecordingRequested() && !IsErrored())
00976 {
00977 if (PauseAndWait(100))
00978 continue;
00979
00980 if (deviceIsMpegFile)
00981 {
00982 if (dummyBPS && bytesRead)
00983 {
00984 elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
00985 while ((bytesRead / elapsed) > dummyBPS)
00986 {
00987 usleep(50000);
00988 elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
00989 }
00990 }
00991 else if (GetFramesWritten())
00992 {
00993 elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
00994 while ((GetFramesWritten() / elapsed) > 30)
00995 {
00996 usleep(50000);
00997 elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
00998 }
00999 }
01000 }
01001
01002 if (_device_read_buffer)
01003 {
01004 len = _device_read_buffer->Read(
01005 &(buffer[remainder]), bufferSize - remainder);
01006
01007
01008 if (_device_read_buffer->IsErrored())
01009 {
01010 LOG(VB_GENERAL, LOG_ERR, LOC + "Device error detected");
01011
01012 RestartEncoding();
01013 }
01014 else if (_device_read_buffer->IsEOF() &&
01015 IsRecordingRequested())
01016 {
01017 LOG(VB_GENERAL, LOG_ERR, LOC + "Device EOF detected");
01018 _error = "Device EOF detected";
01019 }
01020 }
01021 else
01022 {
01023 if (has_select)
01024 {
01025 tv.tv_sec = 5;
01026 tv.tv_usec = 0;
01027 FD_ZERO(&rdset);
01028 FD_SET(readfd, &rdset);
01029
01030 switch (select(readfd + 1, &rdset, NULL, NULL, &tv))
01031 {
01032 case -1:
01033 if (errno == EINTR)
01034 continue;
01035
01036 LOG(VB_GENERAL, LOG_ERR, LOC + "Select error" + ENO);
01037 continue;
01038
01039 case 0:
01040 LOG(VB_GENERAL, LOG_ERR, LOC + "select timeout - "
01041 "driver has stopped responding");
01042
01043 if (close(readfd) != 0)
01044 {
01045 LOG(VB_GENERAL, LOG_ERR, LOC + "Close error" + ENO);
01046 }
01047
01048
01049 readfd = -1;
01050 continue;
01051
01052 default:
01053 break;
01054 }
01055 }
01056
01057 len = read(readfd, &(buffer[remainder]), bufferSize - remainder);
01058
01059 if (len < 0 && !has_select)
01060 {
01061 QMutexLocker locker(&pauseLock);
01062 if (request_recording && !request_pause)
01063 unpauseWait.wait(&pauseLock, 25);
01064 continue;
01065 }
01066
01067 if ((len == 0) && (deviceIsMpegFile))
01068 {
01069 close(readfd);
01070 readfd = open(vdevice.constData(), O_RDONLY);
01071
01072 if (readfd >= 0)
01073 {
01074 len = read(readfd,
01075 &(buffer[remainder]), bufferSize - remainder);
01076 }
01077
01078 if (len <= 0)
01079 {
01080 _error = "Failed to read from video file";
01081 continue;
01082 }
01083 }
01084 else if (len < 0 && errno != EAGAIN)
01085 {
01086 LOG(VB_GENERAL, LOG_ERR, LOC + QString("error reading from: %1")
01087 .arg(videodevice) + ENO);
01088 continue;
01089 }
01090 }
01091
01092 if (len > 0)
01093 {
01094 bytesRead += len;
01095 len += remainder;
01096
01097 if (driver == "hdpvr")
01098 {
01099 remainder = _stream_data->ProcessData(buffer, len);
01100 int start_remain = len - remainder;
01101 if (remainder && (start_remain >= remainder))
01102 memcpy(buffer, buffer+start_remain, remainder);
01103 else if (remainder)
01104 memmove(buffer, buffer+start_remain, remainder);
01105 }
01106 else
01107 {
01108 FindPSKeyFrames(buffer, len);
01109 }
01110 }
01111 }
01112
01113 LOG(VB_RECORD, LOG_INFO, LOC + "run finishing up");
01114
01115 StopEncoding();
01116
01117 {
01118 QMutexLocker locker(&pauseLock);
01119 request_helper = false;
01120 }
01121
01122 if (vbi_thread)
01123 {
01124 vbi_thread->wait();
01125 delete vbi_thread;
01126 vbi_thread = NULL;
01127 CloseVBIDevice();
01128 }
01129
01130 FinishRecording();
01131
01132 delete[] buffer;
01133
01134 if (driver == "hdpvr")
01135 {
01136 _stream_data->RemoveWritingListener(this);
01137 _stream_data->RemoveAVListener(this);
01138 DTVRecorder::SetStreamData(NULL);
01139 }
01140
01141 QMutexLocker locker(&pauseLock);
01142 request_recording = false;
01143 recording = false;
01144 recordingWait.wakeAll();
01145 }
01146
01147 void MpegRecorder::StopRecording(void)
01148 {
01149 MpegRecorder::StopEncoding();
01150 V4LRecorder::StopRecording();
01151 }
01152
01153 bool MpegRecorder::ProcessTSPacket(const TSPacket &tspacket_real)
01154 {
01155 const uint pid = tspacket_real.PID();
01156
01157 TSPacket *tspacket_fake = NULL;
01158 if ((driver == "hdpvr") && (pid == 0x1001))
01159 {
01160 tspacket_fake = tspacket_real.CreateClone();
01161 uint cc = (_continuity_counter[pid] == 0xFF) ?
01162 0 : (_continuity_counter[pid] + 1) & 0xf;
01163 tspacket_fake->SetContinuityCounter(cc);
01164 }
01165
01166 const TSPacket &tspacket = (tspacket_fake)
01167 ? *tspacket_fake : tspacket_real;
01168
01169 bool ret = DTVRecorder::ProcessTSPacket(tspacket);
01170
01171 if (tspacket_fake)
01172 delete tspacket_fake;
01173
01174 return ret;
01175 }
01176
01177 void MpegRecorder::Reset(void)
01178 {
01179 LOG(VB_RECORD, LOG_INFO, LOC + "Reset(void)");
01180 ResetForNewFile();
01181
01182 _start_code = 0xffffffff;
01183
01184 if (curRecording)
01185 {
01186 curRecording->ClearPositionMap(MARK_GOP_BYFRAME);
01187 }
01188 if (_stream_data)
01189 _stream_data->Reset(_stream_data->DesiredProgram());
01190 }
01191
01192 void MpegRecorder::Pause(bool clear)
01193 {
01194 QMutexLocker locker(&pauseLock);
01195 cleartimeonpause = clear;
01196 paused = false;
01197 request_pause = true;
01198 }
01199
01200 bool MpegRecorder::PauseAndWait(int timeout)
01201 {
01202 QMutexLocker locker(&pauseLock);
01203 if (request_pause)
01204 {
01205 if (!IsPaused(true))
01206 {
01207 LOG(VB_RECORD, LOG_INFO, LOC + "PauseAndWait pause");
01208
01209 StopEncoding();
01210
01211 paused = true;
01212 pauseWait.wakeAll();
01213
01214 if (tvrec)
01215 tvrec->RecorderPaused();
01216 }
01217
01218 unpauseWait.wait(&pauseLock, timeout);
01219 }
01220
01221 if (!request_pause && IsPaused(true))
01222 {
01223 LOG(VB_RECORD, LOG_INFO, LOC + "PauseAndWait unpause");
01224
01225 if (driver == "hdpvr")
01226 {
01227 m_h264_parser.Reset();
01228 _wait_for_keyframe_option = true;
01229 _seen_sps = false;
01230
01231 SetV4L2DeviceOptions(chanfd);
01232 }
01233
01234 StartEncoding();
01235
01236 if (_stream_data)
01237 _stream_data->Reset(_stream_data->DesiredProgram());
01238
01239 paused = false;
01240 }
01241
01242 return IsPaused(true);
01243 }
01244
01245 void MpegRecorder::RestartEncoding(void)
01246 {
01247 LOG(VB_RECORD, LOG_INFO, LOC + "RestartEncoding");
01248
01249 QMutexLocker locker(&start_stop_encoding_lock);
01250
01251 StopEncoding();
01252
01253
01254 if (_stream_data &&
01255 _stream_data->PATSingleProgram() &&
01256 _stream_data->PMTSingleProgram())
01257 {
01258 _wait_for_keyframe_option = false;
01259 HandleSingleProgramPAT(_stream_data->PATSingleProgram());
01260 HandleSingleProgramPMT(_stream_data->PMTSingleProgram());
01261 }
01262
01263 if (driver == "hdpvr")
01264 SetV4L2DeviceOptions(chanfd);
01265
01266 StartEncoding();
01267 }
01268
01269 bool MpegRecorder::StartEncoding(void)
01270 {
01271 QMutexLocker locker(&start_stop_encoding_lock);
01272
01273 struct v4l2_encoder_cmd command;
01274 memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
01275 command.cmd = V4L2_ENC_CMD_START;
01276
01277 if (driver == "hdpvr")
01278 HandleResolutionChanges();
01279
01280 LOG(VB_RECORD, LOG_INFO, LOC + "StartEncoding");
01281
01282 if (readfd < 0)
01283 {
01284 readfd = open(videodevice.toAscii().constData(), O_RDWR | O_NONBLOCK);
01285 if (readfd < 0)
01286 {
01287 LOG(VB_GENERAL, LOG_ERR, LOC +
01288 "StartEncoding: Can't open video device." + ENO);
01289 _error = "Failed to start recording";
01290 return false;
01291 }
01292 }
01293
01294 bool started = 0 == ioctl(readfd, VIDIOC_ENCODER_CMD, &command);
01295 if (started)
01296 {
01297 if (driver == "hdpvr")
01298 {
01299 m_h264_parser.Reset();
01300 _wait_for_keyframe_option = true;
01301 _seen_sps = false;
01302 }
01303
01304 LOG(VB_RECORD, LOG_INFO, LOC + "Encoding started");
01305 }
01306 else if ((ENOTTY == errno) || (EINVAL == errno))
01307 {
01308
01309
01310
01311 started = true;
01312 }
01313 else
01314 {
01315 LOG(VB_GENERAL, LOG_WARNING, LOC + "StartEncoding failed" + ENO);
01316 }
01317
01318 if (_device_read_buffer)
01319 {
01320 _device_read_buffer->Reset(videodevice.toAscii().constData(), readfd);
01321 _device_read_buffer->Start();
01322 }
01323
01324 return true;
01325 }
01326
01327 void MpegRecorder::StopEncoding(void)
01328 {
01329 QMutexLocker locker(&start_stop_encoding_lock);
01330
01331 LOG(VB_RECORD, LOG_INFO, LOC + "StopEncoding");
01332
01333 if (readfd < 0)
01334 return;
01335
01336 struct v4l2_encoder_cmd command;
01337 memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
01338 command.cmd = V4L2_ENC_CMD_STOP;
01339 command.flags = V4L2_ENC_CMD_STOP_AT_GOP_END;
01340
01341 bool stopped = 0 == ioctl(readfd, VIDIOC_ENCODER_CMD, &command);
01342 if (stopped)
01343 {
01344 LOG(VB_RECORD, LOG_INFO, LOC + "Encoding stopped");
01345 }
01346 else if ((ENOTTY == errno) || (EINVAL == errno))
01347 {
01348
01349
01350
01351 stopped = true;
01352 }
01353 else
01354 {
01355 LOG(VB_GENERAL, LOG_WARNING, LOC + "StopEncoding failed" + ENO);
01356 }
01357
01358 if (_device_read_buffer && _device_read_buffer->IsRunning())
01359 {
01360 usleep(20 * 1000);
01361 _device_read_buffer->Stop();
01362 }
01363
01364
01365 close(readfd);
01366 readfd = -1;
01367 }
01368
01369 void MpegRecorder::SetStreamData(void)
01370 {
01371 _stream_data->AddMPEGSPListener(this);
01372 _stream_data->SetDesiredProgram(1);
01373 }
01374
01375 void MpegRecorder::SetBitrate(int bitrate, int maxbitrate,
01376 const QString & reason)
01377 {
01378 if (maxbitrate == bitrate)
01379 {
01380 LOG(VB_RECORD, LOG_INFO, LOC + QString("%1 bitrate %2 kbps CBR")
01381 .arg(reason).arg(bitrate));
01382 }
01383 else
01384 {
01385 LOG(VB_RECORD, LOG_INFO, LOC + QString("%1 bitrate %2/%3 kbps VBR")
01386 .arg(reason).arg(bitrate).arg(maxbitrate));
01387 }
01388
01389 vector<struct v4l2_ext_control> ext_ctrls;
01390 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
01391 (maxbitrate == bitrate) ?
01392 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR :
01393 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
01394
01395 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE,
01396 bitrate * 1000);
01397
01398 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
01399 maxbitrate * 1000);
01400
01401 set_ctrls(readfd, ext_ctrls);
01402 }
01403
01404 void MpegRecorder::HandleResolutionChanges(void)
01405 {
01406 LOG(VB_RECORD, LOG_INFO, LOC + "Checking Resolution");
01407 uint pix = 0;
01408 struct v4l2_format vfmt;
01409 memset(&vfmt, 0, sizeof(vfmt));
01410 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
01411
01412 if (0 == ioctl(chanfd, VIDIOC_G_FMT, &vfmt))
01413 {
01414 LOG(VB_RECORD, LOG_INFO, LOC + QString("Got Resolution %1x%2")
01415 .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
01416 pix = vfmt.fmt.pix.width * vfmt.fmt.pix.height;
01417 }
01418
01419 if (!pix)
01420 {
01421 LOG(VB_RECORD, LOG_INFO, LOC + "Giving up detecting resolution");
01422 return;
01423 }
01424
01425 int old_max = maxbitrate, old_avg = bitrate;
01426 if (pix <= 768*568)
01427 {
01428 maxbitrate = low_mpeg4peakbitrate;
01429 bitrate = low_mpeg4avgbitrate;
01430 }
01431 else if (pix >= 1920*1080)
01432 {
01433 maxbitrate = high_mpeg4peakbitrate;
01434 bitrate = high_mpeg4avgbitrate;
01435 }
01436 else
01437 {
01438 maxbitrate = medium_mpeg4peakbitrate;
01439 bitrate = medium_mpeg4avgbitrate;
01440 }
01441 maxbitrate = std::max(maxbitrate, bitrate);
01442
01443 if ((old_max != maxbitrate) || (old_avg != bitrate))
01444 {
01445 if (old_max == old_avg)
01446 {
01447 LOG(VB_RECORD, LOG_INFO, LOC +
01448 QString("Old bitrate %1 CBR").arg(old_avg));
01449 }
01450 else
01451 {
01452 LOG(VB_RECORD, LOG_INFO,LOC +
01453 QString("Old bitrate %1/%2 VBR") .arg(old_avg).arg(old_max));
01454 }
01455
01456 SetBitrate(bitrate, maxbitrate, "New");
01457 }
01458 }
01459
01460 void MpegRecorder::FormatCC(uint code1, uint code2)
01461 {
01462 LOG(VB_VBI, LOG_INFO, LOC + QString("FormatCC(0x%1,0x%2)")
01463 .arg(code1,0,16).arg(code2,0,16));
01464
01465
01466
01467
01469 }