|
MythTV
0.26-pre
|
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 }
1.7.6.1