MythTV  0.26-pre
mpegrecorder.cpp
Go to the documentation of this file.
00001 // -*- Mode: c++ -*-
00002 
00003 // C headers
00004 #include <ctime>
00005 
00006 // C++ headers
00007 #include <algorithm>
00008 #include <vector>
00009 using namespace std;
00010 
00011 // POSIX headers
00012 #include <fcntl.h>
00013 #include <unistd.h>
00014 #include <inttypes.h>
00015 
00016 // System headers
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 // avlib headers
00028 extern "C" {
00029 #include "libavcodec/avcodec.h"
00030 }
00031 
00032 // MythTV headers
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 // ivtv header
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     // Debugging variables
00082     deviceIsMpegFile(false),      bufferSize(0),
00083     // Driver info
00084     card(QString::null),          driver(QString::null),
00085     version(0),
00086     supports_sliced_vbi(false),
00087     // State
00088     start_stop_encoding_lock(QMutex::Recursive),
00089     // Pausing state
00090     cleartimeonpause(false),
00091     // Encoding info
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     // Input file descriptors
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); // on failure language will be 0
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 // same as the base class, it just doesn't complain if an option is missing
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 // same as the base class, it just doesn't complain if an option is missing
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     // open implicitly starts encoding, so we need the lock..
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);    // we don't care if this fails...
00421 
00422     if (supports_audio)
00423         SetRecordingVolume(chanfd); // we don't care if this fails...
00424 
00425     if (!SetV4L2DeviceOptions(chanfd))
00426     {
00427         close(chanfd);
00428         chanfd = -1;
00429         return false;
00430     }
00431 
00432     SetVBIOptions(chanfd); // we don't care if this fails...
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     // Get volume min/max values
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     // calculate volume in card units.
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     // Set recording volume
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; // only 48kHz works properly.
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;  /* PES A/V    */
00680         case 5:  return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;  /* PES V      */
00681         case 7:  return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;  /* PES A      */
00682         case 10: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
00683         case 11: return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD; /* VCD */
00684         case 12: return V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD;
00685         case 13: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD; /* DVD-Special 1 */
00686         case 14: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD; /* DVD-Special 2 */
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     // Set controls
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     // query supported audio codecs if spdif is not used
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     // HACK. FreeBSD PVR150/500 driver doesn't currently support select()
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         // Make sure the first things in the file are a PAT & PMT
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;  // Bytes per second, but env var is BITS PER SECOND
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             // Check for DRB errors
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                         // Force card to be reopened on next iteration..
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)) // PCRPID for HD-PVR
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             // HD-PVR will sometimes reset to defaults
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     // Make sure the next things in the file are a PAT & PMT
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") // HD-PVR will sometimes reset to defaults
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         // Some drivers do not support this ioctl at all.  It is marked as
01309         // "experimental" in the V4L2 API spec. These drivers return EINVAL
01310         // in older kernels and ENOTTY in 3.1+
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         // Some drivers do not support this ioctl at all.  It is marked as
01349         // "experimental" in the V4L2 API spec. These drivers return EINVAL
01350         // in older kernels and ENOTTY in 3.1+
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); // allow last bits of data through..
01361         _device_read_buffer->Stop();
01362     }
01363 
01364     // close the fd so streamoff/streamon work in V4LChannel
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; // nothing to do, we don't have a resolution yet
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     // TODO add to CC data vector
01465 
01466     // TODO find video frames in output and insert cc_data
01467     // as CEA-708 user_data packets containing CEA-608 captions
01469 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends