00001
00002
00003
00004 #include <ctime>
00005
00006
00007 #include <pthread.h>
00008 #include <fcntl.h>
00009 #include <unistd.h>
00010 #include <inttypes.h>
00011
00012
00013 #include <sys/types.h>
00014 #include <sys/stat.h>
00015 #include <sys/ioctl.h>
00016 #include <sys/time.h>
00017
00018 #include <algorithm>
00019 using namespace std;
00020
00021
00022 extern "C" {
00023 #include "../libavcodec/avcodec.h"
00024 }
00025
00026
00027 #include "mpegrecorder.h"
00028 #include "RingBuffer.h"
00029 #include "mythcontext.h"
00030 #include "programinfo.h"
00031 #include "recordingprofile.h"
00032 #include "tv_rec.h"
00033 #include "videodev_myth.h"
00034 #include "util.h"
00035 #include "cardutil.h"
00036
00037
00038 extern "C" {
00039 #include "ivtv_myth.h"
00040 }
00041
00042 #define IVTV_KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
00043
00044 #define LOC QString("MPEGRec(%1): ").arg(videodevice)
00045 #define LOC_WARN QString("MPEGRec(%1) Warning: ").arg(videodevice)
00046 #define LOC_ERR QString("MPEGRec(%1) Error: ").arg(videodevice)
00047
00048 const int MpegRecorder::audRateL1[] =
00049 {
00050 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0
00051 };
00052
00053 const int MpegRecorder::audRateL2[] =
00054 {
00055 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0
00056 };
00057
00058 const int MpegRecorder::audRateL3[] =
00059 {
00060 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0
00061 };
00062
00063 const char* MpegRecorder::streamType[] =
00064 {
00065 "MPEG-2 PS", "MPEG-2 TS", "MPEG-1 VCD", "PES AV",
00066 "", "PES V", "", "PES A",
00067 "", "", "DVD", "VCD",
00068 "SVCD", "DVD-Special 1", "DVD-Special 2", 0
00069 };
00070
00071 const char* MpegRecorder::aspectRatio[] =
00072 {
00073 "Square", "4:3", "16:9", "2.21:1", 0
00074 };
00075
00076 const unsigned int MpegRecorder::kBuildBufferMaxSize = 1024 * 1024;
00077
00078 MpegRecorder::MpegRecorder(TVRec *rec) :
00079 RecorderBase(rec),
00080
00081 deviceIsMpegFile(false),
00082 bufferSize(4096),
00083
00084 card(QString::null), driver(QString::null),
00085 version(0), usingv4l2(false),
00086 has_buggy_vbi(true), has_v4l2_vbi(false),
00087 requires_special_pause(false),
00088
00089 recording(false), encoding(false),
00090 errored(false),
00091
00092 cleartimeonpause(false),
00093
00094 framesWritten(0),
00095
00096 width(720), height(480),
00097 bitrate(4500), maxbitrate(6000),
00098 streamtype(0), aspectratio(2),
00099 audtype(2), audsamplerate(48000),
00100 audbitratel1(14), audbitratel2(14),
00101 audbitratel3(10),
00102 audvolume(80), language(0),
00103
00104 chanfd(-1), readfd(-1),
00105
00106 keyframedist(15), gopset(false),
00107 leftovers(0), lastpackheaderpos(0),
00108 lastseqstart(0), numgops(0),
00109
00110 buildbuffer(new unsigned char[kBuildBufferMaxSize + 1]),
00111 buildbuffersize(0)
00112 {
00113 SetPositionMapType(MARK_GOP_START);
00114 }
00115
00116 MpegRecorder::~MpegRecorder()
00117 {
00118 TeardownAll();
00119 delete [] buildbuffer;
00120 }
00121
00122 void MpegRecorder::TeardownAll(void)
00123 {
00124 if (chanfd >= 0)
00125 {
00126 close(chanfd);
00127 chanfd = -1;
00128 }
00129 if (readfd >= 0)
00130 {
00131 close(readfd);
00132 readfd = -1;
00133 }
00134 }
00135
00136 static int find_index(const int *audio_rate, int value)
00137 {
00138 for (uint i = 0; audio_rate[i] != 0; i++)
00139 {
00140 if (audio_rate[i] == value)
00141 return i;
00142 }
00143
00144 return -1;
00145 }
00146
00147 void MpegRecorder::SetOption(const QString &opt, int value)
00148 {
00149 if (opt == "width")
00150 width = value;
00151 else if (opt == "height")
00152 height = value;
00153 else if (opt == "mpeg2bitrate")
00154 bitrate = value;
00155 else if (opt == "mpeg2maxbitrate")
00156 maxbitrate = value;
00157 else if (opt == "samplerate")
00158 audsamplerate = value;
00159 else if (opt == "mpeg2audbitratel1")
00160 {
00161 int index = find_index(audRateL1, value);
00162 if (index >= 0)
00163 audbitratel1 = index + 1;
00164 else
00165 {
00166 VERBOSE(VB_IMPORTANT, LOC_ERR + "Audiorate(L1): " +
00167 QString("%1 is invalid").arg(value));
00168 }
00169 }
00170 else if (opt == "mpeg2audbitratel2")
00171 {
00172 int index = find_index(audRateL2, value);
00173 if (index >= 0)
00174 audbitratel2 = index + 1;
00175 else
00176 {
00177 VERBOSE(VB_IMPORTANT, LOC_ERR + "Audiorate(L2): " +
00178 QString("%1 is invalid").arg(value));
00179 }
00180 }
00181 else if (opt == "mpeg2audbitratel3")
00182 {
00183 int index = find_index(audRateL3, value);
00184 if (index >= 0)
00185 audbitratel3 = index + 1;
00186 else
00187 {
00188 VERBOSE(VB_IMPORTANT, LOC_ERR + "Audiorate(L2): " +
00189 QString("%1 is invalid").arg(value));
00190 }
00191 }
00192 else if (opt == "mpeg2audvolume")
00193 audvolume = value;
00194 else
00195 RecorderBase::SetOption(opt, value);
00196 }
00197
00198 void MpegRecorder::SetOption(const QString &opt, const QString &value)
00199 {
00200 if (opt == "mpeg2streamtype")
00201 {
00202 bool found = false;
00203 for (unsigned int i = 0; i < sizeof(streamType) / sizeof(char*); i++)
00204 {
00205 if (QString(streamType[i]) == value)
00206 {
00207 streamtype = i;
00208 found = true;
00209 break;
00210 }
00211 }
00212
00213 if (!found)
00214 {
00215 VERBOSE(VB_IMPORTANT, LOC_ERR + "MPEG2 stream type: " +
00216 QString("%1 is invalid").arg(value));
00217 }
00218 }
00219 else if (opt == "mpeg2language")
00220 {
00221 bool ok = false;
00222 language = value.toInt(&ok);
00223 if (!ok)
00224 {
00225 VERBOSE(VB_IMPORTANT, LOC_ERR + "MPEG2 language (stereo) flag " +
00226 QString("'%1' is invalid").arg(value));
00227 }
00228 }
00229 else if (opt == "mpeg2aspectratio")
00230 {
00231 bool found = false;
00232 for (int i = 0; aspectRatio[i] != 0; i++)
00233 {
00234 if (QString(aspectRatio[i]) == value)
00235 {
00236 aspectratio = i + 1;
00237 found = true;
00238 break;
00239 }
00240 }
00241
00242 if (!found)
00243 {
00244 VERBOSE(VB_IMPORTANT, LOC_ERR + "MPEG2 Aspect-ratio: " +
00245 QString("%1 is invalid").arg(value));
00246 }
00247 }
00248 else if (opt == "mpeg2audtype")
00249 {
00250 if (value == "Layer I")
00251 audtype = 1;
00252 else if (value == "Layer II")
00253 audtype = 2;
00254 else if (value == "Layer III")
00255 audtype = 3;
00256 else
00257 {
00258 VERBOSE(VB_IMPORTANT, LOC_ERR + "MPEG2 audio layer: " +
00259 QString("%1 is invalid").arg(value));
00260 }
00261 }
00262 else
00263 {
00264 RecorderBase::SetOption(opt, value);
00265 }
00266 }
00267
00268 void MpegRecorder::SetOptionsFromProfile(RecordingProfile *profile,
00269 const QString &videodev,
00270 const QString &audiodev,
00271 const QString &vbidev)
00272 {
00273 (void)audiodev;
00274 (void)vbidev;
00275
00276 if (videodev.lower().left(5) == "file:")
00277 {
00278 deviceIsMpegFile = true;
00279 bufferSize = 64000;
00280 QString newVideoDev = videodev;
00281 if (newVideoDev.startsWith("file:", false))
00282 newVideoDev = newVideoDev.remove(0,5);
00283 SetOption("videodevice", newVideoDev);
00284 }
00285 else
00286 {
00287 SetOption("videodevice", videodev);
00288 }
00289
00290 SetOption("tvformat", gContext->GetSetting("TVFormat"));
00291 SetOption("vbiformat", gContext->GetSetting("VbiFormat"));
00292
00293 SetIntOption(profile, "mpeg2bitrate");
00294 SetIntOption(profile, "mpeg2maxbitrate");
00295 SetStrOption(profile, "mpeg2streamtype");
00296 SetStrOption(profile, "mpeg2aspectratio");
00297 SetStrOption(profile, "mpeg2language");
00298
00299 SetIntOption(profile, "samplerate");
00300 SetStrOption(profile, "mpeg2audtype");
00301 SetIntOption(profile, "mpeg2audbitratel1");
00302 SetIntOption(profile, "mpeg2audbitratel2");
00303 SetIntOption(profile, "mpeg2audbitratel3");
00304 SetIntOption(profile, "mpeg2audvolume");
00305
00306 SetIntOption(profile, "width");
00307 SetIntOption(profile, "height");
00308 }
00309
00310 bool MpegRecorder::OpenMpegFileAsInput(void)
00311 {
00312 chanfd = readfd = open(videodevice.ascii(), O_RDONLY);
00313
00314 if (readfd < 0)
00315 {
00316 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Can't open MPEG File '%1'")
00317 .arg(videodevice) + ENO);
00318
00319 return false;
00320 }
00321 return true;
00322 }
00323
00324 bool MpegRecorder::OpenV4L2DeviceAsInput(void)
00325 {
00326 chanfd = open(videodevice.ascii(), O_RDWR);
00327 if (chanfd < 0)
00328 {
00329 VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't open video device. " + ENO);
00330 return false;
00331 }
00332
00333 if (CardUtil::GetV4LInfo(chanfd, card, driver, version))
00334 {
00335 if (driver == "ivtv")
00336 {
00337 usingv4l2 = (version >= IVTV_KERNEL_VERSION(0, 8, 0));
00338 has_v4l2_vbi = (version >= IVTV_KERNEL_VERSION(0, 3, 8));
00339 has_buggy_vbi = true;
00340 requires_special_pause =
00341 (version >= IVTV_KERNEL_VERSION(0, 10, 0));
00342 }
00343 else
00344 {
00345 VERBOSE(VB_IMPORTANT, "\n\nNot ivtv driver??\n\n");
00346 usingv4l2 = has_v4l2_vbi = true;
00347 has_buggy_vbi = requires_special_pause = false;
00348 }
00349 }
00350
00351 VERBOSE(VB_RECORD, LOC + QString("usingv4l2(%1) has_v4l2_vbi(%2) "
00352 "has_buggy_vbi(%3)")
00353 .arg(usingv4l2).arg(has_v4l2_vbi).arg(has_buggy_vbi));
00354
00355 struct v4l2_format vfmt;
00356 bzero(&vfmt, sizeof(vfmt));
00357
00358 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00359
00360 if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) < 0)
00361 {
00362 VERBOSE(VB_IMPORTANT, LOC_ERR + "Error getting format" + ENO);
00363 return false;
00364 }
00365
00366 vfmt.fmt.pix.width = width;
00367 vfmt.fmt.pix.height = height;
00368
00369 if (ioctl(chanfd, VIDIOC_S_FMT, &vfmt) < 0)
00370 {
00371 VERBOSE(VB_IMPORTANT, LOC_ERR + "Error setting format" + ENO);
00372 return false;
00373 }
00374
00375
00376 bool do_audmode_set = true;
00377 struct v4l2_tuner vt;
00378 bzero(&vt, sizeof(struct v4l2_tuner));
00379 if (ioctl(chanfd, VIDIOC_G_TUNER, &vt) < 0)
00380 {
00381 VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get audio mode" + ENO);
00382 do_audmode_set = false;
00383 }
00384
00385 switch (language)
00386 {
00387 case 0:
00388 vt.audmode = V4L2_TUNER_MODE_LANG1;
00389 break;
00390 case 1:
00391 vt.audmode = V4L2_TUNER_MODE_LANG2;
00392 break;
00393 case 2:
00394 if (usingv4l2)
00395 vt.audmode = V4L2_TUNER_MODE_LANG1_LANG2;
00396 else
00397 vt.audmode = V4L2_TUNER_MODE_STEREO;
00398 break;
00399 default:
00400 vt.audmode = V4L2_TUNER_MODE_LANG1;
00401 }
00402
00403 int audio_layer = GetFilteredAudioLayer();
00404 if (do_audmode_set && (2 == language) && (1 == audio_layer))
00405 {
00406 VERBOSE(VB_GENERAL, "Dual audio mode incompatible with Layer I audio."
00407 "\n\t\t\tFalling back to Main Language");
00408 vt.audmode = V4L2_TUNER_MODE_LANG1;
00409 }
00410
00411 if (do_audmode_set && ioctl(chanfd, VIDIOC_S_TUNER, &vt) < 0)
00412 {
00413 VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to set audio mode" + ENO);
00414 }
00415
00416
00417 struct v4l2_queryctrl qctrl;
00418 qctrl.id = V4L2_CID_AUDIO_VOLUME;
00419 if (ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) < 0)
00420 {
00421 VERBOSE(VB_IMPORTANT, LOC_WARN +
00422 "Unable to get recording volume parameters(max/min)" + ENO +
00423 "\n\t\t\tusing default range [0,65535].");
00424 qctrl.maximum = 65535;
00425 qctrl.minimum = 0;
00426 }
00427
00428
00429 int range = qctrl.maximum - qctrl.minimum;
00430 int value = (int) ((range * audvolume * 0.01f) + qctrl.minimum);
00431 int ctrl_volume = min(qctrl.maximum, max(qctrl.minimum, value));
00432
00433
00434 struct v4l2_control ctrl;
00435 ctrl.id = V4L2_CID_AUDIO_VOLUME;
00436 ctrl.value = ctrl_volume;
00437
00438 if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) < 0)
00439 {
00440 VERBOSE(VB_IMPORTANT, LOC_WARN +
00441 "Unable to set recording volume" + ENO + "\n\t\t\t" +
00442 "If you are using an AverMedia M179 card this is normal.");
00443 }
00444
00445 bool ok = true;
00446 if (usingv4l2)
00447 ok = SetV4L2DeviceOptions(chanfd);
00448 else
00449 {
00450 ok = SetIVTVDeviceOptions(chanfd);
00451 if (!ok)
00452 usingv4l2 = ok = SetV4L2DeviceOptions(chanfd);
00453 }
00454
00455 if (!ok)
00456 return false;
00457
00458 SetVBIOptions(chanfd);
00459
00460 readfd = open(videodevice.ascii(), O_RDWR | O_NONBLOCK);
00461 if (readfd < 0)
00462 {
00463 VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't open video device." + ENO);
00464 return false;
00465 }
00466
00467 return true;
00468 }
00469
00470 uint MpegRecorder::GetFilteredStreamType(void) const
00471 {
00472 uint st = (uint) streamtype;
00473
00474 if (driver == "ivtv")
00475 {
00476 switch (st)
00477 {
00478 case 2: st = 2; break;
00479 case 10:
00480 case 13:
00481 case 14: st = 10; break;
00482 case 11: st = 11; break;
00483 case 12: st = 12; break;
00484 default: st = 0; break;
00485 }
00486 }
00487
00488 if (st != (uint) streamtype)
00489 {
00490 VERBOSE(VB_IMPORTANT, LOC_WARN +
00491 QString("Stream type '%1'\n\t\t\t"
00492 "is not supported by %2 driver, using '%3' instead.")
00493 .arg(streamType[streamtype]).arg(driver).arg(streamType[st]));
00494 }
00495
00496 return st;
00497 }
00498
00499 uint MpegRecorder::GetFilteredAudioSampleRate(void) const
00500 {
00501 uint sr = (uint) audsamplerate;
00502
00503 sr = (driver == "ivtv") ? 48000 : sr;
00504
00505 if (sr != (uint) audsamplerate)
00506 {
00507 VERBOSE(VB_IMPORTANT, LOC_WARN +
00508 QString("Audio sample rate %1 Hz\n\t\t\t"
00509 "is not supported by %2 driver, using %3 Hz instead.")
00510 .arg(audsamplerate).arg(driver).arg(sr));
00511 }
00512
00513 switch (sr)
00514 {
00515 case 32000: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000;
00516 case 44100: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100;
00517 case 48000: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
00518 default: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
00519 }
00520 }
00521
00522 uint MpegRecorder::GetFilteredAudioLayer(void) const
00523 {
00524 uint layer = (uint) audtype;
00525
00526 layer = max(min(layer, 3U), 1U);
00527
00528 layer = (driver == "ivtv") ? 2 : layer;
00529
00530 if (layer != (uint) audtype)
00531 {
00532 VERBOSE(VB_IMPORTANT, LOC_WARN +
00533 QString("MPEG layer %1 does not work properly\n\t\t\t"
00534 "with %2 driver. Using MPEG layer %3 audio instead.")
00535 .arg(audtype).arg(driver).arg(layer));
00536 }
00537
00538 return layer;
00539 }
00540
00541 uint MpegRecorder::GetFilteredAudioBitRate(uint audio_layer) const
00542 {
00543 return ((2 == audio_layer) ? max(audbitratel2, 10) :
00544 ((3 == audio_layer) ? audbitratel3 : max(audbitratel1, 6)));
00545 }
00546
00547 bool MpegRecorder::SetIVTVDeviceOptions(int chanfd)
00548 {
00549 struct ivtv_ioctl_codec ivtvcodec;
00550 bzero(&ivtvcodec, sizeof(ivtvcodec));
00551
00552 if (ioctl(chanfd, IVTV_IOC_G_CODEC, &ivtvcodec) < 0)
00553 {
00554
00555
00556
00557 VERBOSE((22 == errno) ? VB_RECORD : VB_IMPORTANT,
00558 ((22 == errno) ? LOC_WARN : LOC_ERR) +
00559 "Error getting codec params using old IVTV ioctl" + ENO);
00560 return false;
00561 }
00562
00563 uint audio_rate = GetFilteredAudioSampleRate();
00564 uint audio_layer = GetFilteredAudioLayer();
00565 uint audbitrate = GetFilteredAudioBitRate(audio_layer);
00566
00567 ivtvcodec.audio_bitmask = audio_rate | (audio_layer << 2);
00568 ivtvcodec.audio_bitmask |= audbitrate << 4;
00569 ivtvcodec.aspect = aspectratio;
00570 ivtvcodec.bitrate = min(bitrate, maxbitrate) * 1000;
00571 ivtvcodec.bitrate_peak = maxbitrate * 1000;
00572 ivtvcodec.framerate = ntsc_framerate ? 0 : 1;
00573 ivtvcodec.stream_type = GetFilteredStreamType();
00574
00575 if (ioctl(chanfd, IVTV_IOC_S_CODEC, &ivtvcodec) < 0)
00576 {
00577 VERBOSE(VB_IMPORTANT, LOC_ERR + "Error setting codec params" + ENO);
00578 return false;
00579 }
00580
00581 keyframedist = (ivtvcodec.framerate) ? 12 : keyframedist;
00582
00583 return true;
00584 }
00585
00586 static int streamtype_ivtv_to_v4l2(int st)
00587 {
00588 switch (st)
00589 {
00590 case 0: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
00591 case 1: return V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
00592 case 2: return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD;
00593 case 3: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
00594 case 5: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
00595 case 7: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
00596 case 10: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
00597 case 11: return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD;
00598 case 12: return V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD;
00599 case 13: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
00600 case 14: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
00601 default: return V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
00602 }
00603 }
00604
00605 bool MpegRecorder::SetV4L2DeviceOptions(int chanfd)
00606 {
00607 static const uint kNumControls = 7;
00608 struct v4l2_ext_controls ctrls;
00609 struct v4l2_ext_control ext_ctrl[kNumControls];
00610 QString control_description[kNumControls] =
00611 {
00612 "Audio Sampling Frequency",
00613 "Video Aspect ratio",
00614 "Audio Encoding",
00615 "Audio L2 Bitrate",
00616 "Video Peak Bitrate",
00617 "Video Average Bitrate",
00618 "MPEG Stream type",
00619 };
00620
00621
00622 bzero(&ctrls, sizeof(struct v4l2_ext_controls));
00623 bzero(&ext_ctrl, sizeof(struct v4l2_ext_control) * kNumControls);
00624
00625 uint audio_layer = GetFilteredAudioLayer();
00626 uint audbitrate = GetFilteredAudioBitRate(audio_layer);
00627
00628 ext_ctrl[0].id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ;
00629 ext_ctrl[0].value = GetFilteredAudioSampleRate();
00630
00631 ext_ctrl[1].id = V4L2_CID_MPEG_VIDEO_ASPECT;
00632 ext_ctrl[1].value = aspectratio - 1;
00633
00634 ext_ctrl[2].id = V4L2_CID_MPEG_AUDIO_ENCODING;
00635 ext_ctrl[2].value = audio_layer - 1;
00636
00637 ext_ctrl[3].id = V4L2_CID_MPEG_AUDIO_L2_BITRATE;
00638 ext_ctrl[3].value = audbitrate - 1;
00639
00640 ext_ctrl[4].id = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK;
00641 ext_ctrl[4].value = maxbitrate * 1000;
00642
00643 ext_ctrl[5].id = V4L2_CID_MPEG_VIDEO_BITRATE;
00644 ext_ctrl[5].value = (bitrate = min(bitrate, maxbitrate)) * 1000;
00645
00646 ext_ctrl[6].id = V4L2_CID_MPEG_STREAM_TYPE;
00647 ext_ctrl[6].value = streamtype_ivtv_to_v4l2(GetFilteredStreamType());
00648
00649 for (uint i = 0; i < kNumControls; i++)
00650 {
00651 int value = ext_ctrl[i].value;
00652
00653 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
00654 ctrls.count = 1;
00655 ctrls.controls = ext_ctrl + i;
00656
00657 if (ioctl(chanfd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
00658 {
00659 VERBOSE(VB_IMPORTANT, LOC_ERR +
00660 QString("Could not set %1 to %2")
00661 .arg(control_description[i]).arg(value) + ENO);
00662 }
00663 }
00664
00665
00666 ext_ctrl[0].id = V4L2_CID_MPEG_VIDEO_GOP_SIZE;
00667 ext_ctrl[0].value = 0;
00668
00669 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
00670 ctrls.count = 1;
00671 ctrls.controls = ext_ctrl;
00672
00673 if (ioctl(chanfd, VIDIOC_G_EXT_CTRLS, &ctrls) < 0)
00674 {
00675 VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get "
00676 "V4L2_CID_MPEG_VIDEO_GOP_SIZE, defaulting to 12" + ENO);
00677 ext_ctrl[0].value = 12;
00678 }
00679
00680 keyframedist = ext_ctrl[0].value;
00681
00682 return true;
00683 }
00684
00685 bool MpegRecorder::SetVBIOptions(int chanfd)
00686 {
00687 if (!vbimode)
00688 return true;
00689
00690 if (has_buggy_vbi)
00691 {
00692 cout<<" *********************** WARNING ***********************"<<endl;
00693 cout<<" ivtv drivers prior to 0.10.0 can cause lockups when "<<endl;
00694 cout<<" reading VBI. Drivers between 0.10.5 and 1.0.3+ do not "<<endl;
00695 cout<<" properly capture VBI data on PVR-250 and PVR-350 cards."<<endl;
00696 cout<<endl;
00697 }
00698
00699
00702 #ifdef IVTV_IOC_S_VBI_EMBED
00703
00704 if (!has_v4l2_vbi)
00705 {
00706 struct ivtv_sliced_vbi_format vbifmt;
00707 bzero(&vbifmt, sizeof(struct ivtv_sliced_vbi_format));
00708 vbifmt.service_set = (1 == vbimode) ? VBI_TYPE_TELETEXT : VBI_TYPE_CC;
00709
00710 if (ioctl(chanfd, IVTV_IOC_S_VBI_MODE, &vbifmt) < 0)
00711 {
00712 VERBOSE(VB_IMPORTANT, LOC_WARN +
00713 "Can't enable VBI recording (1)" + ENO);
00714
00715 return false;
00716 }
00717
00718 if (ioctl(chanfd, IVTV_IOC_G_VBI_MODE, &vbifmt) >= 0)
00719 {
00720 VERBOSE(VB_RECORD, LOC + QString(
00721 "VBI service:%1, packet size:%2, io size:%3")
00722 .arg(vbifmt.service_set).arg(vbifmt.packet_size)
00723 .arg(vbifmt.io_size));
00724 }
00725 }
00726 #endif // IVTV_IOC_S_VBI_EMBED
00727
00728 #ifdef V4L2_CAP_SLICED_VBI_CAPTURE
00729
00730 if (has_v4l2_vbi)
00731 {
00732 struct v4l2_format vbifmt;
00733 bzero(&vbifmt, sizeof(struct v4l2_format));
00734 vbifmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
00735 vbifmt.fmt.sliced.service_set |= (1 == vbimode) ?
00736 V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
00737
00738 if (ioctl(chanfd, VIDIOC_S_FMT, &vbifmt) < 0)
00739 {
00740 VERBOSE(VB_IMPORTANT, LOC_WARN +
00741 "Can't enable VBI recording (3)" + ENO);
00742
00743 return false;
00744 }
00745
00746 if (ioctl(chanfd, VIDIOC_G_FMT, &vbifmt) >= 0)
00747 {
00748 VERBOSE(VB_RECORD, LOC + QString("VBI service: %1, io size: %2")
00749 .arg(vbifmt.fmt.sliced.service_set)
00750 .arg(vbifmt.fmt.sliced.io_size));
00751 }
00752 }
00753 #endif // V4L2_CAP_SLICED_VBI_CAPTURE
00754
00755
00758 #ifdef IVTV_IOC_S_VBI_EMBED
00759
00760 if (!usingv4l2)
00761 {
00762 int embedon = 1;
00763 if (ioctl(chanfd, IVTV_IOC_S_VBI_EMBED, &embedon) < 0)
00764 {
00765 VERBOSE(VB_IMPORTANT, LOC_WARN +
00766 "Can't enable VBI recording (4)" + ENO);
00767
00768 return false;
00769 }
00770 }
00771 #endif // IVTV_IOC_S_VBI_EMBED
00772
00773 #ifdef V4L2_CAP_SLICED_VBI_CAPTURE
00774
00775 if (usingv4l2)
00776 {
00777 struct v4l2_ext_control vbi_ctrl;
00778 vbi_ctrl.id = V4L2_CID_MPEG_STREAM_VBI_FMT;
00779 vbi_ctrl.value = V4L2_MPEG_STREAM_VBI_FMT_IVTV;
00780
00781 struct v4l2_ext_controls ctrls;
00782 bzero(&ctrls, sizeof(struct v4l2_ext_controls));
00783 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
00784 ctrls.count = 1;
00785 ctrls.controls = &vbi_ctrl;
00786
00787 if (ioctl(chanfd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
00788 {
00789 VERBOSE(VB_IMPORTANT, LOC_WARN +
00790 "Can't enable VBI recording (5)" + ENO);
00791
00792 return false;
00793 }
00794 }
00795 #endif // V4L2_CAP_SLICED_VBI_CAPTURE
00796
00797 return true;
00798 }
00799
00800 bool MpegRecorder::Open(void)
00801 {
00802 if (deviceIsMpegFile)
00803 return OpenMpegFileAsInput();
00804 else
00805 return OpenV4L2DeviceAsInput();
00806 }
00807
00808 void MpegRecorder::StartRecording(void)
00809 {
00810 if (!Open())
00811 {
00812 errored = true;
00813 return;
00814 }
00815
00816 if (!SetupRecording())
00817 {
00818 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to setup recording.");
00819 errored = true;
00820 return;
00821 }
00822
00823 encoding = true;
00824 recording = true;
00825 unsigned char *buffer = new unsigned char[bufferSize + 1];
00826 int ret;
00827
00828 MythTimer elapsedTimer;
00829 float elapsed;
00830
00831 struct timeval tv;
00832 fd_set rdset;
00833
00834 if (deviceIsMpegFile)
00835 elapsedTimer.start();
00836
00837 while (encoding)
00838 {
00839 if (PauseAndWait(100))
00840 continue;
00841
00842 if ((deviceIsMpegFile) && (framesWritten))
00843 {
00844 elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
00845 while ((framesWritten / elapsed) > 30)
00846 {
00847 usleep(50000);
00848 elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
00849 }
00850 }
00851
00852 if (readfd < 0)
00853 readfd = open(videodevice.ascii(), O_RDWR);
00854
00855 tv.tv_sec = 5;
00856 tv.tv_usec = 0;
00857 FD_ZERO(&rdset);
00858 FD_SET(readfd, &rdset);
00859
00860 #if defined(__FreeBSD__)
00861
00862 #else
00863 switch (select(readfd + 1, &rdset, NULL, NULL, &tv))
00864 {
00865 case -1:
00866 if (errno == EINTR)
00867 continue;
00868
00869 VERBOSE(VB_IMPORTANT, LOC_ERR + "Select error" + ENO);
00870 continue;
00871
00872 case 0:
00873 VERBOSE(VB_IMPORTANT, LOC_ERR + "select timeout - "
00874 "ivtv driver has stopped responding");
00875
00876 if (close(readfd) != 0)
00877 {
00878 VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO);
00879 }
00880
00881 readfd = -1;
00882 continue;
00883
00884 default: break;
00885 }
00886 #endif
00887
00888 ret = read(readfd, buffer, bufferSize);
00889
00890 if ((ret == 0) &&
00891 (deviceIsMpegFile))
00892 {
00893 close(readfd);
00894 readfd = open(videodevice.ascii(), O_RDONLY);
00895
00896 if (readfd >= 0)
00897 ret = read(readfd, buffer, bufferSize);
00898 if (ret <= 0)
00899 {
00900 encoding = false;
00901 continue;
00902 }
00903 }
00904 else if (ret < 0 && errno != EAGAIN)
00905 {
00906 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("error reading from: %1")
00907 .arg(videodevice) + ENO);
00908
00909 continue;
00910 }
00911 else if (ret > 0)
00912 {
00913 ProcessData(buffer, ret);
00914 }
00915 }
00916
00917 FinishRecording();
00918
00919 delete[] buffer;
00920 recording = false;
00921 }
00922
00923 bool MpegRecorder::SetupRecording(void)
00924 {
00925 leftovers = 0xFFFFFFFF;
00926 numgops = 0;
00927 lastseqstart = 0;
00928 return true;
00929 }
00930
00931 void MpegRecorder::FinishRecording(void)
00932 {
00933 ringBuffer->WriterFlush();
00934
00935 if (curRecording)
00936 {
00937 curRecording->SetFilesize(ringBuffer->GetRealFileSize());
00938 SavePositionMap(true);
00939 }
00940 positionMapLock.lock();
00941 positionMap.clear();
00942 positionMapDelta.clear();
00943 positionMapLock.unlock();
00944 }
00945
00946 #define PACK_HEADER 0x000001BA
00947 #define GOP_START 0x000001B8
00948 #define SEQ_START 0x000001B3
00949 #define SLICE_MIN 0x00000101
00950 #define SLICE_MAX 0x000001af
00951
00952 void MpegRecorder::ProcessData(unsigned char *buffer, int len)
00953 {
00954 unsigned char *bufptr = buffer, *bufstart = buffer;
00955 unsigned int state = leftovers, v = 0;
00956 int leftlen = len;
00957
00958 while (bufptr < buffer + len)
00959 {
00960 v = *bufptr++;
00961 if (state == 0x000001)
00962 {
00963 state = ((state << 8) | v) & 0xFFFFFF;
00964
00965 if (state == PACK_HEADER)
00966 {
00967 long long startpos = ringBuffer->GetWritePosition();
00968 startpos += buildbuffersize + bufptr - bufstart - 4;
00969 lastpackheaderpos = startpos;
00970
00971 int curpos = bufptr - bufstart - 4;
00972 if (curpos < 0)
00973 {
00974
00975 buildbuffersize += curpos;
00976 if (buildbuffersize > 0)
00977 ringBuffer->Write(buildbuffer, buildbuffersize);
00978
00979 buildbuffersize = 4;
00980 memcpy(buildbuffer, &state, 4);
00981
00982 leftlen = leftlen - curpos + 4;
00983 bufstart = bufptr;
00984 }
00985 else
00986 {
00987
00988 memcpy(buildbuffer + buildbuffersize, bufstart, curpos);
00989 buildbuffersize += curpos;
00990 bufstart += curpos;
00991 leftlen -= curpos;
00992
00993 if (buildbuffersize > 0)
00994 ringBuffer->Write(buildbuffer, buildbuffersize);
00995
00996 buildbuffersize = 0;
00997 }
00998 }
00999
01000 if (state == SEQ_START)
01001 {
01002 lastseqstart = lastpackheaderpos;
01003 }
01004
01005 if (state == GOP_START && lastseqstart == lastpackheaderpos)
01006 {
01007 framesWritten = numgops * keyframedist;
01008 numgops++;
01009 HandleKeyframe();
01010 }
01011 }
01012 else
01013 state = ((state << 8) | v) & 0xFFFFFF;
01014 }
01015
01016 leftovers = state;
01017
01018 if (buildbuffersize + leftlen > kBuildBufferMaxSize)
01019 {
01020 ringBuffer->Write(buildbuffer, buildbuffersize);
01021 buildbuffersize = 0;
01022 }
01023
01024
01025 memcpy(buildbuffer + buildbuffersize, bufstart, leftlen);
01026 buildbuffersize += leftlen;
01027 }
01028
01029 void MpegRecorder::StopRecording(void)
01030 {
01031 encoding = false;
01032 }
01033
01034 void MpegRecorder::ResetForNewFile(void)
01035 {
01036 errored = false;
01037 framesWritten = 0;
01038 numgops = 0;
01039 lastseqstart = lastpackheaderpos = 0;
01040
01041 positionMap.clear();
01042 positionMapDelta.clear();
01043 }
01044
01045 void MpegRecorder::Reset(void)
01046 {
01047 ResetForNewFile();
01048
01049 leftovers = 0xFFFFFFFF;
01050 buildbuffersize = 0;
01051
01052 if (curRecording)
01053 curRecording->ClearPositionMap(MARK_GOP_START);
01054 }
01055
01056 void MpegRecorder::Pause(bool clear)
01057 {
01058 cleartimeonpause = clear;
01059 paused = false;
01060 request_pause = true;
01061 }
01062
01063 bool MpegRecorder::PauseAndWait(int timeout)
01064 {
01065 if (request_pause)
01066 {
01067 if (!paused)
01068 {
01069 if (requires_special_pause)
01070 {
01071
01072
01073 struct v4l2_encoder_cmd command;
01074 memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
01075 command.cmd = V4L2_ENC_CMD_STOP;
01076 ioctl(readfd, VIDIOC_ENCODER_CMD, &command);
01077 }
01078
01079 paused = true;
01080 pauseWait.wakeAll();
01081 if (tvrec)
01082 tvrec->RecorderPaused();
01083 }
01084 unpauseWait.wait(timeout);
01085 }
01086 if (!request_pause)
01087 {
01088 if (paused)
01089 {
01090 if (requires_special_pause)
01091 {
01092
01093
01094 struct v4l2_encoder_cmd command;
01095 command.cmd = V4L2_ENC_CMD_START;
01096 ioctl(readfd, VIDIOC_ENCODER_CMD, &command);
01097 }
01098 }
01099 paused = false;
01100 }
01101 return paused;
01102 }
01103
01104 long long MpegRecorder::GetKeyframePosition(long long desired)
01105 {
01106 QMutexLocker locker(&positionMapLock);
01107 long long ret = -1;
01108
01109 if (positionMap.find(desired) != positionMap.end())
01110 ret = positionMap[desired];
01111
01112 return ret;
01113 }
01114
01115
01116 void MpegRecorder::SetNextRecording(const ProgramInfo *progInf, RingBuffer *rb)
01117 {
01118
01119 SavePositionMap(true);
01120 ringBuffer->WriterFlush();
01121 if (curRecording)
01122 curRecording->SetFilesize(ringBuffer->GetRealFileSize());
01123
01124
01125 {
01126 QMutexLocker locker(&nextRingBufferLock);
01127 nextRecording = NULL;
01128 if (progInf)
01129 nextRecording = new ProgramInfo(*progInf);
01130 nextRingBuffer = rb;
01131 }
01132 }
01133
01138 void MpegRecorder::HandleKeyframe(void)
01139 {
01140
01141 positionMapLock.lock();
01142 if (!positionMap.contains(numgops))
01143 {
01144 positionMapDelta[numgops] = lastpackheaderpos;
01145 positionMap[numgops] = lastpackheaderpos;
01146 }
01147 positionMapLock.unlock();
01148
01149
01150 CheckForRingBufferSwitch();
01151 }
01152