Ticket #5443: hdpvr-0.1-recorder.patch
File hdpvr-0.1-recorder.patch, 42.2 KB (added by , 16 years ago) |
---|
-
libs/libmythtv/dtvrecorder.h
65 65 bool FindH264Keyframes(const TSPacket* tspacket); 66 66 void HandleH264Keyframe(void); 67 67 68 // PS support (Hauppauge PVR-x50/PVR-500) 69 void HandlePSKeyframe(void); 70 bool FindPSKeyFrames(unsigned char *buffer, int len); 71 68 72 // For handling other (non audio/video) packets 69 73 bool FindOtherKeyframes(const TSPacket *tspacket); 70 74 … … 111 115 unsigned long long _frames_seen_count; 112 116 unsigned long long _frames_written_count; 113 117 118 int keyframedist; 119 114 120 // constants 115 121 /// If the number of regular frames detected since the last 116 122 /// detected keyframe exceeds this value, then we begin marking -
libs/libmythtv/dtvrecorder.cpp
14 14 15 15 extern "C" { 16 16 // from libavcodec 17 extern const uint8_t *ff_find_start_code(const uint8_t * restrict p, const uint8_t *end, uint32_t * restrict state);17 extern const uint8_t *ff_find_start_code(const uint8_t * restrict p, const uint8_t *end, uint32_t * restrict state); 18 18 } 19 19 20 20 #define LOC QString("DTVRec(%1): ").arg(tvrec->GetCaptureCardNum()) … … 27 27 * handle MPEG-2, MPEG-4, MPEG-4 AVC, DVB and ATSC streams. 28 28 * 29 29 * \sa DBox2Recorder, DVBRecorder, FirewireRecorder, 30 31 30 HDHRRecoreder, IPTVRecorder 31 */ 32 32 33 33 DTVRecorder::DTVRecorder(TVRec *rec) : 34 34 RecorderBase(rec), … … 54 54 // keyframe TS buffer 55 55 _buffer_packets(false), 56 56 // statistics 57 _frames_seen_count(0), _frames_written_count(0) 57 _frames_seen_count(0), _frames_written_count(0), 58 keyframedist(15) 58 59 { 59 60 SetPositionMapType(MARK_GOP_BYFRAME); 61 _payload_buffer.reserve(TSPacket::SIZE * (50 + 1)); 60 62 } 61 63 62 64 DTVRecorder::~DTVRecorder() … … 430 432 */ 431 433 bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket) 432 434 { 433 if (!ringBuffer) 435 if (!ringBuffer) { 436 VERBOSE(VB_IMPORTANT, LOC_ERR + "FindH264Keyframes: No ringbuffer"); 434 437 return false; 438 } 435 439 436 440 bool haveBufferedData = !_payload_buffer.empty(); 437 441 if (!tspacket->HasPayload()) // no payload to scan … … 440 444 const bool payloadStart = tspacket->PayloadStart(); 441 445 if (payloadStart) 442 446 { 447 //VERBOSE(VB_RECORD, LOC_ERR + "FindH264Keyframes: payloadStart"); 443 448 // reset PES sync state 444 449 _pes_synced = false; 445 450 _start_code = 0xffffffff; … … 459 464 if (i + 2 >= TSPacket::SIZE) 460 465 { 461 466 VERBOSE(VB_IMPORTANT, LOC_ERR + 462 "PES packet start code may overflow to next TS packet, aborting keyframe search"); 467 "PES packet start code may overflow to next TS " 468 "packet, aborting keyframe search"); 463 469 break; 464 470 } 465 471 … … 469 475 tspacket->data()[i++] != 0x01) 470 476 { 471 477 VERBOSE(VB_IMPORTANT, LOC_ERR + 472 "PES start code not found in TS packet with PUSI set");478 "PES start code not found in TS packet with PUSI set"); 473 479 break; 474 480 } 475 481 … … 477 483 if (i + 5 >= TSPacket::SIZE) 478 484 { 479 485 VERBOSE(VB_IMPORTANT, LOC_ERR + 480 "PES packet headers overflow to next TS packet, aborting keyframe search"); 486 "PES packet headers overflow to next TS packet, " 487 "aborting keyframe search"); 481 488 break; 482 489 } 483 490 … … 493 500 if ((i + 6 + pes_header_length) >= TSPacket::SIZE) 494 501 { 495 502 VERBOSE(VB_IMPORTANT, LOC_ERR + 496 "PES packet headers overflow to next TS packet, aborting keyframe search"); 503 "PES packet headers overflow to next TS packet, " 504 "aborting keyframe search"); 497 505 break; 498 506 } 499 507 500 // we now know where the PES payload is 501 // normally, we should have used 6, but use 5 because the for loop will bump i 508 // we now know where the PES payload is. 509 // normally, we should have used 6, 510 // but use 5 because the for loop will bump i 502 511 i += 5 + pes_header_length; 503 512 _pes_synced = true; 504 513 … … 511 520 break; 512 521 513 522 // scan for a NAL unit start code 514 uint32_t bytes_used = _h264_kf_seq.AddBytes(tspacket->data() + i, 515 TSPacket::SIZE - i, 516 ringBuffer->GetWritePosition()); 523 uint32_t bytes_used = 524 _h264_kf_seq.AddBytes(tspacket->data() + i, 525 TSPacket::SIZE - i, 526 ringBuffer->GetWritePosition()); 517 527 i += (bytes_used - 1); 518 528 519 529 // special handling when we've synced to a NAL unit … … 535 545 536 546 if (hasKeyFrame) 537 547 { 548 //VERBOSE(VB_RECORD, LOC_ERR + "FindH264Keyframes: hasKeyFrame"); 538 549 _last_keyframe_seen = _frames_seen_count; 539 550 HandleH264Keyframe(); 540 551 } 541 552 542 553 if (hasFrame) 543 554 { 555 //VERBOSE(VB_RECORD, LOC_ERR + "FindH264Keyframes: hasFrame"); 544 556 _frames_seen_count++; 545 557 if (!_wait_for_keyframe_option || _first_keyframe >= 0) 546 558 _frames_written_count++; … … 572 584 CheckForRingBufferSwitch(); 573 585 } 574 586 587 /** \fn DTVRecorder::HandlePSKeyframe(void) 588 * \brief This save the current frame to the position maps 589 * and handles ringbuffer switching. 590 */ 591 void DTVRecorder::HandlePSKeyframe(void) 592 { 593 if (!ringBuffer) 594 return; 595 596 unsigned long long frameNum = _last_gop_seen; 597 598 _first_keyframe = (_first_keyframe < 0) ? frameNum : _first_keyframe; 599 600 // Add key frame to position map 601 positionMapLock.lock(); 602 if (!positionMap.contains(frameNum)) 603 { 604 long long startpos = ringBuffer->GetWritePosition(); 605 // FIXME: handle keyframes with start code spanning over two ts packets 606 startpos += _payload_buffer.size(); 607 // VERBOSE(VB_RECORD, LOC + "mpHandleKeyframe frameNum: " << frameNum << ", startpos: " << startpos << " type " << positionMapType << "\n"); 608 positionMapDelta[frameNum] = startpos; 609 positionMap[frameNum] = startpos; 610 } 611 positionMapLock.unlock(); 612 613 // Perform ringbuffer switch if needed. 614 CheckForRingBufferSwitch(); 615 } 616 617 618 bool DTVRecorder::FindPSKeyFrames(unsigned char *buffer, int len) 619 { 620 unsigned char *bufptr = buffer, *bufstart = buffer; 621 uint v = 0; 622 int leftlen = len; 623 bool hasKeyFrame = false; 624 625 while (bufptr < buffer + len) 626 { 627 v = *bufptr++; 628 if (_start_code == 0x000001) 629 { 630 _start_code = ((_start_code << 8) | v) & 0xFFFFFF; 631 const int stream_id = _start_code & 0x000000ff; 632 633 if (stream_id == PESStreamID::PackHeader) 634 { 635 _last_keyframe_seen = ringBuffer->GetWritePosition() + 636 _payload_buffer.size(); 637 638 int curpos = bufptr - bufstart - 4; 639 if (curpos < 0) 640 { 641 // header was split 642 if (_payload_buffer.size() + curpos > 0) 643 ringBuffer->Write(&_payload_buffer[0], 644 _payload_buffer.size() + curpos); 645 646 _payload_buffer.resize(4); 647 memcpy(&_payload_buffer[0], &_start_code, 4); 648 649 leftlen = leftlen - curpos + 4; 650 bufstart = bufptr; 651 } 652 else 653 { 654 // header was entirely in this packet 655 int idx = _payload_buffer.size(); 656 _payload_buffer.resize(idx + curpos); 657 memcpy(&_payload_buffer[idx], bufstart, curpos); 658 659 bufstart += curpos; 660 leftlen -= curpos; 661 662 if (_payload_buffer.size() > 0) 663 ringBuffer->Write(&_payload_buffer[0], 664 _payload_buffer.size()); 665 _payload_buffer.clear(); 666 } 667 _frames_seen_count++; 668 } 669 else if (stream_id == PESStreamID::SequenceStartCode) 670 { 671 _last_seq_seen = _last_keyframe_seen; 672 } 673 else if (stream_id == PESStreamID::GOPStartCode && 674 _last_seq_seen == _last_keyframe_seen) 675 { 676 _frames_written_count = _last_gop_seen * keyframedist; 677 _last_gop_seen++; 678 HandlePSKeyframe(); 679 } 680 } 681 else 682 _start_code = ((_start_code << 8) | v) & 0xFFFFFF; 683 } 684 685 int idx = _payload_buffer.size(); 686 _payload_buffer.resize(idx + leftlen); 687 memcpy(&_payload_buffer[idx], bufstart, leftlen); 688 689 return hasKeyFrame; 690 } 691 692 575 693 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
libs/libmythtv/mpegrecorder.h
3 3 #ifndef MPEGRECORDER_H_ 4 4 #define MPEGRECORDER_H_ 5 5 6 #include "recorderbase.h" 6 #include "dtvrecorder.h" 7 #include "tspacket.h" 8 #include "mpegstreamdata.h" 7 9 8 10 struct AVFormatContext; 9 11 struct AVPacket; 10 12 11 class MpegRecorder : public RecorderBase 13 class MpegRecorder : public DTVRecorder, 14 public MPEGSingleProgramStreamListener 12 15 { 13 16 public: 14 17 MpegRecorder(TVRec*); … … 33 36 bool PauseAndWait(int timeout = 100); 34 37 35 38 bool IsRecording(void) { return recording; } 36 bool IsErrored(void) { return errored; }37 39 38 long long GetFramesWritten(void) { return framesWritten; }39 40 40 bool Open(void); 41 41 int GetVideoFd(void) { return chanfd; } 42 42 43 long long GetKeyframePosition(long long desired); 43 // TS 44 virtual void SetStreamData(MPEGStreamData*); 45 virtual MPEGStreamData *GetStreamData(void) { return _stream_data; } 44 46 45 void SetNextRecording(const ProgramInfo*, RingBuffer*); 47 // implements MPEGSingleProgramStreamListener 48 void HandleSingleProgramPAT(ProgramAssociationTable *pat); 49 void HandleSingleProgramPMT(ProgramMapTable *pmt); 46 50 47 51 private: 48 bool SetupRecording(void);49 void FinishRecording(void);50 void HandleKeyframe(void);51 52 52 void ProcessData(unsigned char *buffer, int len); 53 53 54 54 bool OpenMpegFileAsInput(void); … … 60 60 uint GetFilteredAudioSampleRate(void) const; 61 61 uint GetFilteredAudioLayer(void) const; 62 62 uint GetFilteredAudioBitRate(uint audio_layer) const; 63 void ProcessPSdata(unsigned char *buffer, int len); 64 void ProcessTSdata(unsigned char * data, int len, uint & leftover); 65 void ProcessTSPacket(const TSPacket &tspacket); 63 66 64 67 void ResetForNewFile(void); 65 68 … … 78 81 // State 79 82 bool recording; 80 83 bool encoding; 81 bool errored;82 84 83 85 // Pausing state 84 86 bool cleartimeonpause; 85 87 86 // Number of frames written87 long long framesWritten;88 89 88 // Encoding info 90 89 int width, height; 91 90 int bitrate, maxbitrate, streamtype, aspectratio; … … 97 96 int chanfd; 98 97 int readfd; 99 98 100 // Keyframe tracking inforamtion101 int keyframedist;102 bool gopset;103 unsigned int leftovers;104 long long lastpackheaderpos;105 long long lastseqstart;106 long long numgops;107 108 // buffer used for ...109 unsigned char *buildbuffer;110 unsigned int buildbuffersize;111 112 99 static const int audRateL1[]; 113 100 static const int audRateL2[]; 114 101 static const int audRateL3[]; 115 102 static const char *streamType[]; 116 103 static const char *aspectRatio[]; 117 104 static const unsigned int kBuildBufferMaxSize; 105 106 // TS 107 MPEGStreamData *_stream_data; 118 108 }; 119 109 #endif -
libs/libmythtv/cardutil.cpp
1473 1473 { 1474 1474 bool ok; 1475 1475 QStringList ret; 1476 1476 1477 int videofd = open(device.ascii(), O_RDWR); 1477 1478 if (videofd < 0) 1478 1479 { … … 1480 1481 "to probe its inputs.").arg(device); 1481 1482 return ret; 1482 1483 } 1484 1483 1485 InputNames list = CardUtil::probeV4LInputs(videofd, ok); 1484 1486 close(videofd); 1485 1487 -
libs/libmythtv/mpegrecorder.cpp
48 48 const int MpegRecorder::audRateL1[] = 49 49 { 50 50 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0 51 };51 }; 52 52 53 53 const int MpegRecorder::audRateL2[] = 54 54 { … … 73 73 "Square", "4:3", "16:9", "2.21:1", 0 74 74 }; 75 75 76 const unsigned int MpegRecorder::kBuildBufferMaxSize = 1024 * 1024; 77 78 MpegRecorder::MpegRecorder(TVRec *rec) : 79 RecorderBase(rec), 76 MpegRecorder::MpegRecorder(TVRec *rec) : DTVRecorder(rec), 80 77 // Debugging variables 81 78 deviceIsMpegFile(false), 82 bufferSize(4096),83 79 // Driver info 84 80 card(QString::null), driver(QString::null), 85 81 version(0), usingv4l2(false), … … 87 83 requires_special_pause(false), 88 84 // State 89 85 recording(false), encoding(false), 90 errored(false),91 86 // Pausing state 92 87 cleartimeonpause(false), 93 // Number of frames written94 framesWritten(0),95 88 // Encoding info 96 89 width(720), height(480), 97 90 bitrate(4500), maxbitrate(6000), … … 102 95 audvolume(80), language(0), 103 96 // Input file descriptors 104 97 chanfd(-1), readfd(-1), 105 // Keyframe tracking inforamtion 106 keyframedist(15), gopset(false), 107 leftovers(0), lastpackheaderpos(0), 108 lastseqstart(0), numgops(0), 109 // buffer used for ... 110 buildbuffer(new unsigned char[kBuildBufferMaxSize + 1]), 111 buildbuffersize(0) 98 // TS packet handling 99 _stream_data(NULL) 112 100 { 113 101 SetPositionMapType(MARK_GOP_START); 114 102 } … … 116 104 MpegRecorder::~MpegRecorder() 117 105 { 118 106 TeardownAll(); 119 delete [] buildbuffer;120 107 } 121 108 122 109 void MpegRecorder::TeardownAll(void) … … 332 319 333 320 if (CardUtil::GetV4LInfo(chanfd, card, driver, version)) 334 321 { 322 // driver = "hdpvr"; 323 335 324 if (driver == "ivtv") 336 325 { 326 bufferSize = 4096; 327 337 328 usingv4l2 = (version >= IVTV_KERNEL_VERSION(0, 8, 0)); 338 329 has_v4l2_vbi = (version >= IVTV_KERNEL_VERSION(0, 3, 8)); 339 330 has_buggy_vbi = true; 340 331 requires_special_pause = 341 332 (version >= IVTV_KERNEL_VERSION(0, 10, 0)); 342 333 } 334 else if (driver == "hdpvr") 335 { 336 bufferSize = 1500 * TSPacket::SIZE; 337 usingv4l2 = true; 338 } 343 339 else 344 340 { 345 VERBOSE(VB_IMPORTANT, "\n\nNot ivtv driver??\n\n");341 VERBOSE(VB_IMPORTANT, "\n\nNot ivtv or hdpvr driver??\n\n"); 346 342 usingv4l2 = has_v4l2_vbi = true; 347 343 has_buggy_vbi = requires_special_pause = false; 348 344 } … … 354 350 355 351 struct v4l2_format vfmt; 356 352 bzero(&vfmt, sizeof(vfmt)); 357 353 358 354 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 359 355 360 356 if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) < 0) 361 357 { 362 358 VERBOSE(VB_IMPORTANT, LOC_ERR + "Error getting format" + ENO); 363 359 return false; 364 360 } 361 362 if (driver != "hdpvr") { 363 vfmt.fmt.pix.width = width; 364 vfmt.fmt.pix.height = height; 365 366 if (ioctl(chanfd, VIDIOC_S_FMT, &vfmt) < 0) 367 { 368 VERBOSE(VB_IMPORTANT, LOC_ERR + "Error setting format" + ENO); 369 return false; 370 } 365 371 366 vfmt.fmt.pix.width = width; 367 vfmt.fmt.pix.height = height; 368 369 if (ioctl(chanfd, VIDIOC_S_FMT, &vfmt) < 0) 370 { 371 VERBOSE(VB_IMPORTANT, LOC_ERR + "Error setting format" + ENO); 372 return false; 373 } 374 375 // Set audio language mode 376 bool do_audmode_set = true; 377 struct v4l2_tuner vt; 378 bzero(&vt, sizeof(struct v4l2_tuner)); 379 if (ioctl(chanfd, VIDIOC_G_TUNER, &vt) < 0) 380 { 381 VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get audio mode" + ENO); 382 do_audmode_set = false; 383 } 384 385 switch (language) 386 { 387 case 0: 372 // Set audio language mode 373 bool do_audmode_set = true; 374 struct v4l2_tuner vt; 375 bzero(&vt, sizeof(struct v4l2_tuner)); 376 if (ioctl(chanfd, VIDIOC_G_TUNER, &vt) < 0) 377 { 378 VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get audio mode" + ENO); 379 do_audmode_set = false; 380 } 381 382 switch (language) 383 { 384 case 0: 388 385 vt.audmode = V4L2_TUNER_MODE_LANG1; 389 386 break; 390 case 1:387 case 1: 391 388 vt.audmode = V4L2_TUNER_MODE_LANG2; 392 389 break; 393 case 2:390 case 2: 394 391 if (usingv4l2) 395 392 vt.audmode = V4L2_TUNER_MODE_LANG1_LANG2; 396 393 else 397 394 vt.audmode = V4L2_TUNER_MODE_STEREO; 398 395 break; 399 default:396 default: 400 397 vt.audmode = V4L2_TUNER_MODE_LANG1; 401 }398 } 402 399 403 int audio_layer = GetFilteredAudioLayer();404 if (do_audmode_set && (2 == language) && (1 == audio_layer))405 {406 VERBOSE(VB_GENERAL, "Dual audio mode incompatible with Layer I audio."407 "\n\t\t\tFalling back to Main Language");408 vt.audmode = V4L2_TUNER_MODE_LANG1;409 }400 int audio_layer = GetFilteredAudioLayer(); 401 if (do_audmode_set && (2 == language) && (1 == audio_layer)) 402 { 403 VERBOSE(VB_GENERAL, "Dual audio mode incompatible with Layer I audio." 404 "\n\t\t\tFalling back to Main Language"); 405 vt.audmode = V4L2_TUNER_MODE_LANG1; 406 } 410 407 411 if (do_audmode_set && ioctl(chanfd, VIDIOC_S_TUNER, &vt) < 0)412 {413 VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to set audio mode" + ENO);414 }408 if (do_audmode_set && ioctl(chanfd, VIDIOC_S_TUNER, &vt) < 0) 409 { 410 VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to set audio mode" + ENO); 411 } 415 412 416 // Get volume min/max values417 struct v4l2_queryctrl qctrl;418 qctrl.id = V4L2_CID_AUDIO_VOLUME;419 if (ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) < 0)420 {421 VERBOSE(VB_IMPORTANT, LOC_WARN +422 "Unable to get recording volume parameters(max/min)" + ENO +423 "\n\t\t\tusing default range [0,65535].");424 qctrl.maximum = 65535;425 qctrl.minimum = 0;426 }413 // Get volume min/max values 414 struct v4l2_queryctrl qctrl; 415 qctrl.id = V4L2_CID_AUDIO_VOLUME; 416 if (ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) < 0) 417 { 418 VERBOSE(VB_IMPORTANT, LOC_WARN + 419 "Unable to get recording volume parameters(max/min)" + ENO + 420 "\n\t\t\tusing default range [0,65535]."); 421 qctrl.maximum = 65535; 422 qctrl.minimum = 0; 423 } 427 424 428 // calculate volume in card units.429 int range = qctrl.maximum - qctrl.minimum;430 int value = (int) ((range * audvolume * 0.01f) + qctrl.minimum);431 int ctrl_volume = min(qctrl.maximum, max(qctrl.minimum, value));425 // calculate volume in card units. 426 int range = qctrl.maximum - qctrl.minimum; 427 int value = (int) ((range * audvolume * 0.01f) + qctrl.minimum); 428 int ctrl_volume = min(qctrl.maximum, max(qctrl.minimum, value)); 432 429 433 // Set recording volume434 struct v4l2_control ctrl;435 ctrl.id = V4L2_CID_AUDIO_VOLUME;436 ctrl.value = ctrl_volume;430 // Set recording volume 431 struct v4l2_control ctrl; 432 ctrl.id = V4L2_CID_AUDIO_VOLUME; 433 ctrl.value = ctrl_volume; 437 434 438 if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) < 0) 439 { 440 VERBOSE(VB_IMPORTANT, LOC_WARN + 441 "Unable to set recording volume" + ENO + "\n\t\t\t" + 442 "If you are using an AverMedia M179 card this is normal."); 435 if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) < 0) 436 { 437 VERBOSE(VB_IMPORTANT, LOC_WARN + 438 "Unable to set recording volume" + ENO + "\n\t\t\t" + 439 "If you are using an AverMedia M179 card this is normal."); 440 } 443 441 } 444 442 445 443 bool ok = true; … … 457 455 458 456 SetVBIOptions(chanfd); 459 457 460 readfd = open(videodevice.ascii(), O_RDWR | O_NONBLOCK); 458 // hdpvr driver does not like NONBLOCK mode with select 459 if (driver == "hdpvr") 460 readfd = open(videodevice.ascii(), O_RDWR); 461 else 462 readfd = open(videodevice.ascii(), O_RDWR | O_NONBLOCK); 463 461 464 if (readfd < 0) 462 465 { 463 466 VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't open video device." + ENO); … … 475 478 { 476 479 switch (st) 477 480 { 478 479 480 481 482 483 484 481 case 2: st = 2; break; 482 case 10: 483 case 13: 484 case 14: st = 10; break; 485 case 11: st = 11; break; 486 case 12: st = 12; break; 487 default: st = 0; break; 485 488 } 486 489 } 490 else if (driver == "hdpvr") 491 { 492 // FIX ME! // I have no idea what to put here 493 switch (st) 494 { 495 case 2: st = 2; break; 496 case 10: 497 case 13: 498 case 14: st = 10; break; 499 case 11: st = 11; break; 500 case 12: st = 12; break; 501 default: st = 0; break; 502 } 503 } 487 504 488 505 if (st != (uint) streamtype) 489 506 { … … 502 519 503 520 sr = (driver == "ivtv") ? 48000 : sr; // only 48kHz works properly. 504 521 522 // hdpvr ? 523 524 505 525 if (sr != (uint) audsamplerate) 506 526 { 507 527 VERBOSE(VB_IMPORTANT, LOC_WARN + … … 512 532 513 533 switch (sr) 514 534 { 515 516 517 518 535 case 32000: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000; 536 case 44100: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100; 537 case 48000: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; 538 default: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; 519 539 } 520 540 } 521 541 … … 527 547 528 548 layer = (driver == "ivtv") ? 2 : layer; 529 549 550 // hdpvr? 551 552 530 553 if (layer != (uint) audtype) 531 554 { 532 555 VERBOSE(VB_IMPORTANT, LOC_WARN + … … 587 610 { 588 611 switch (st) 589 612 { 590 591 592 593 594 595 596 597 598 599 600 601 613 case 0: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS; 614 case 1: return V4L2_MPEG_STREAM_TYPE_MPEG2_TS; 615 case 2: return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD; 616 case 3: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS; /* PES A/V */ 617 case 5: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS; /* PES V */ 618 case 7: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS; /* PES A */ 619 case 10: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD; 620 case 11: return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD; /* VCD */ 621 case 12: return V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD; 622 case 13: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD; /* DVD-Special 1 */ 623 case 14: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD; /* DVD-Special 2 */ 624 default: return V4L2_MPEG_STREAM_TYPE_MPEG2_TS; 602 625 } 603 626 } 604 627 605 628 bool MpegRecorder::SetV4L2DeviceOptions(int chanfd) 606 629 { 607 630 static const uint kNumControls = 7; 608 631 struct v4l2_ext_controls ctrls; 609 632 struct v4l2_ext_control ext_ctrl[kNumControls]; 610 633 QString control_description[kNumControls] = … … 625 648 uint audio_layer = GetFilteredAudioLayer(); 626 649 uint audbitrate = GetFilteredAudioBitRate(audio_layer); 627 650 628 ext_ctrl[0].id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ; 629 ext_ctrl[0].value = GetFilteredAudioSampleRate(); 651 if (driver != "hdpvr") { 652 ext_ctrl[0].id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ; 653 ext_ctrl[0].value = GetFilteredAudioSampleRate(); 654 655 ext_ctrl[1].id = V4L2_CID_MPEG_VIDEO_ASPECT; 656 ext_ctrl[1].value = aspectratio - 1; 657 658 ext_ctrl[2].id = V4L2_CID_MPEG_AUDIO_ENCODING; 659 ext_ctrl[2].value = audio_layer - 1; 660 661 ext_ctrl[3].id = V4L2_CID_MPEG_AUDIO_L2_BITRATE; 662 ext_ctrl[3].value = audbitrate - 1; 630 663 631 ext_ctrl[1].id = V4L2_CID_MPEG_VIDEO_ASPECT; 632 ext_ctrl[1].value = aspectratio - 1; 664 ext_ctrl[4].id = V4L2_CID_MPEG_STREAM_TYPE; 665 ext_ctrl[4].value = streamtype_ivtv_to_v4l2(GetFilteredStreamType()); 666 } 633 667 634 ext_ctrl[ 2].id = V4L2_CID_MPEG_AUDIO_ENCODING;635 ext_ctrl[ 2].value = audio_layer - 1;668 ext_ctrl[5].id = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK; 669 ext_ctrl[5].value = maxbitrate * 1000; 636 670 637 ext_ctrl[ 3].id = V4L2_CID_MPEG_AUDIO_L2_BITRATE;638 ext_ctrl[ 3].value = audbitrate - 1;671 ext_ctrl[6].id = V4L2_CID_MPEG_VIDEO_BITRATE; 672 ext_ctrl[6].value = (bitrate = min(bitrate, maxbitrate)) * 1000; 639 673 640 ext_ctrl[4].id = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK;641 ext_ctrl[4].value = maxbitrate * 1000;642 643 ext_ctrl[5].id = V4L2_CID_MPEG_VIDEO_BITRATE;644 ext_ctrl[5].value = (bitrate = min(bitrate, maxbitrate)) * 1000;645 646 ext_ctrl[6].id = V4L2_CID_MPEG_STREAM_TYPE;647 ext_ctrl[6].value = streamtype_ivtv_to_v4l2(GetFilteredStreamType());648 649 674 for (uint i = 0; i < kNumControls; i++) 650 675 { 651 676 int value = ext_ctrl[i].value; 652 677 678 if (value != 0) { 679 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG; 680 ctrls.count = 1; 681 ctrls.controls = ext_ctrl + i; 682 683 if (ioctl(chanfd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0) 684 { 685 VERBOSE(VB_IMPORTANT, LOC_ERR + 686 QString("Could not set %1 to %2") 687 .arg(control_description[i]).arg(value) + ENO); 688 } 689 } 690 } 691 692 if (driver != "hdpvr") { 693 // Get controls 694 ext_ctrl[0].id = V4L2_CID_MPEG_VIDEO_GOP_SIZE; 695 ext_ctrl[0].value = 0; 696 653 697 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG; 654 698 ctrls.count = 1; 655 ctrls.controls = ext_ctrl + i;656 657 if (ioctl(chanfd, VIDIOC_ S_EXT_CTRLS, &ctrls) < 0)699 ctrls.controls = ext_ctrl; 700 701 if (ioctl(chanfd, VIDIOC_G_EXT_CTRLS, &ctrls) < 0) 658 702 { 659 VERBOSE(VB_IMPORTANT, LOC_ ERR +660 QString("Could not set %1 to %2")661 .arg(control_description[i]).arg(value) + ENO);703 VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get " 704 "V4L2_CID_MPEG_VIDEO_GOP_SIZE, defaulting to 12" + ENO); 705 ext_ctrl[0].value = 12; 662 706 } 707 708 keyframedist = ext_ctrl[0].value; 663 709 } 664 710 665 // Get controls666 ext_ctrl[0].id = V4L2_CID_MPEG_VIDEO_GOP_SIZE;667 ext_ctrl[0].value = 0;668 669 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;670 ctrls.count = 1;671 ctrls.controls = ext_ctrl;672 673 if (ioctl(chanfd, VIDIOC_G_EXT_CTRLS, &ctrls) < 0)674 {675 VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get "676 "V4L2_CID_MPEG_VIDEO_GOP_SIZE, defaulting to 12" + ENO);677 ext_ctrl[0].value = 12;678 }679 680 keyframedist = ext_ctrl[0].value;681 682 711 return true; 683 712 } 684 713 … … 687 716 if (!vbimode) 688 717 return true; 689 718 719 if (driver == "hdpvr") 720 return true; 721 690 722 if (has_buggy_vbi) 691 723 { 692 724 cout<<" *********************** WARNING ***********************"<<endl; … … 717 749 718 750 if (ioctl(chanfd, IVTV_IOC_G_VBI_MODE, &vbifmt) >= 0) 719 751 { 720 VERBOSE(VB_RECORD, LOC + QString(721 752 VERBOSE(VB_RECORD, 753 LOC + QString("VBI service:%1, packet size:%2, io size:%3") 722 754 .arg(vbifmt.service_set).arg(vbifmt.packet_size) 723 755 .arg(vbifmt.io_size)); 724 756 } … … 733 765 bzero(&vbifmt, sizeof(struct v4l2_format)); 734 766 vbifmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; 735 767 vbifmt.fmt.sliced.service_set |= (1 == vbimode) ? 736 V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;768 V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525; 737 769 738 770 if (ioctl(chanfd, VIDIOC_S_FMT, &vbifmt) < 0) 739 771 { … … 809 841 { 810 842 if (!Open()) 811 843 { 812 errored= true;813 844 _error = true; 845 return; 814 846 } 815 847 816 if (!SetupRecording()) 817 { 818 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to setup recording."); 819 errored = true; 820 return; 848 _start_code = 0xffffffff; 849 _last_gop_seen = 0; 850 _frames_written_count = 0; 851 852 if (driver == "hdpvr") { 853 SetPositionMapType(MARK_GOP_BYFRAME); 854 855 if (_stream_data == NULL) { 856 int progNum = 1; 857 MPEGStreamData *sd = new MPEGStreamData(progNum, true); 858 sd->SetCaching(true); 859 SetStreamData(sd); 860 } 821 861 } 862 else { 863 SetPositionMapType(MARK_GOP_START); 864 } 822 865 823 866 encoding = true; 824 867 recording = true; 825 unsigned char *buffer = new unsigned char[bufferSize + 1]; 868 869 // Add an extra TSPacket::SIZE for "leftover_bytes" 870 unsigned char *buffer = new unsigned char[bufferSize + TSPacket::SIZE + 1]; 871 unsigned char *bufstart = &buffer[TSPacket::SIZE]; 872 uint leftover_bytes = 0; 873 826 874 int ret; 827 875 828 876 MythTimer elapsedTimer; … … 839 887 if (PauseAndWait(100)) 840 888 continue; 841 889 842 if ((deviceIsMpegFile) && ( framesWritten))890 if ((deviceIsMpegFile) && (GetFramesWritten())) 843 891 { 844 892 elapsed = (elapsedTimer.elapsed() / 1000.0) + 1; 845 while (( framesWritten/ elapsed) > 30)893 while ((GetFramesWritten() / elapsed) > 30) 846 894 { 847 895 usleep(50000); 848 896 elapsed = (elapsedTimer.elapsed() / 1000.0) + 1; … … 852 900 if (readfd < 0) 853 901 readfd = open(videodevice.ascii(), O_RDWR); 854 902 855 tv.tv_sec = 5;856 tv.tv_usec = 0;857 FD_ZERO(&rdset);858 FD_SET(readfd, &rdset);859 860 903 #if defined(__FreeBSD__) 861 904 // HACK. FreeBSD PVR150/500 driver doesn't currently support select() 862 905 #else 863 switch (select(readfd + 1, &rdset, NULL, NULL, &tv)) 864 { 865 case -1: 906 // hdpvr driver does not like NONBLOCK mode with select 907 if (driver != "hdpvr") { 908 tv.tv_sec = 5; 909 tv.tv_usec = 0; 910 FD_ZERO(&rdset); 911 FD_SET(readfd, &rdset); 912 913 switch (select(readfd + 1, &rdset, NULL, NULL, &tv)) 914 { 915 case -1: 866 916 if (errno == EINTR) 867 917 continue; 868 918 869 919 VERBOSE(VB_IMPORTANT, LOC_ERR + "Select error" + ENO); 870 920 continue; 871 872 case 0:921 922 case 0: 873 923 VERBOSE(VB_IMPORTANT, LOC_ERR + "select timeout - " 874 924 "ivtv driver has stopped responding"); 875 925 876 926 if (close(readfd) != 0) 877 927 { 878 928 VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO); 879 929 } 880 930 881 931 readfd = -1; // Force PVR card to be reopened on next iteration 882 932 continue; 883 884 default: break; 933 934 default: break; 935 } 885 936 } 886 937 #endif 887 938 888 ret = read(readfd, buf fer, bufferSize);939 ret = read(readfd, bufstart, bufferSize); 889 940 890 if ((ret == 0) && 891 (deviceIsMpegFile)) 941 if ((ret == 0) && (deviceIsMpegFile)) 892 942 { 893 943 close(readfd); 894 944 readfd = open(videodevice.ascii(), O_RDONLY); 895 945 896 946 if (readfd >= 0) 897 ret = read(readfd, buf fer, bufferSize);947 ret = read(readfd, bufstart, bufferSize); 898 948 if (ret <= 0) 899 949 { 900 950 encoding = false; … … 905 955 { 906 956 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("error reading from: %1") 907 957 .arg(videodevice) + ENO); 908 909 958 continue; 910 959 } 911 960 else if (ret > 0) 912 961 { 913 ProcessData(buffer, ret); 962 if (driver == "hdpvr") 963 ProcessTSdata(buffer, ret, leftover_bytes); 964 else 965 ProcessPSdata(bufstart, ret); 914 966 } 915 967 } 916 968 … … 920 972 recording = false; 921 973 } 922 974 923 bool MpegRecorder::SetupRecording(void)975 void MpegRecorder::ProcessPSdata(unsigned char *buffer, int len) 924 976 { 925 leftovers = 0xFFFFFFFF; 926 numgops = 0; 927 lastseqstart = 0; 928 return true; 977 FindPSKeyFrames(buffer, len); 929 978 } 930 979 931 void MpegRecorder:: FinishRecording(void)980 void MpegRecorder::ProcessTSdata(unsigned char * data, int len, uint & leftover) 932 981 { 933 ringBuffer->WriterFlush(); 982 uint idx, pos; 983 uint last = TSPacket::SIZE + leftover + len; 934 984 935 if (curRecording) 936 { 937 curRecording->SetFilesize(ringBuffer->GetRealFileSize()); 938 SavePositionMap(true); 939 } 940 positionMapLock.lock(); 941 positionMap.clear(); 942 positionMapDelta.clear(); 943 positionMapLock.unlock(); 944 } 985 for (idx = TSPacket::SIZE - leftover; idx < last; ) { 986 // Find header 987 for (pos = idx; pos < last; ++pos) { 988 if (data[pos] == SYNC_BYTE ) 989 break; 990 } 945 991 946 #define PACK_HEADER 0x000001BA 947 #define GOP_START 0x000001B8 948 #define SEQ_START 0x000001B3 949 #define SLICE_MIN 0x00000101 950 #define SLICE_MAX 0x000001af 992 if (pos == last) { 993 VERBOSE(VB_IMPORTANT, LOC_ERR + "No TS header."); 994 break; 995 } 951 996 952 void MpegRecorder::ProcessData(unsigned char *buffer, int len) 953 { 954 unsigned char *bufptr = buffer, *bufstart = buffer; 955 unsigned int state = leftovers, v = 0; 956 int leftlen = len; 997 if (pos > idx) { 998 VERBOSE(VB_IMPORTANT, LOC_ERR + 999 QString("TS packet at %1 not in sync.").arg(pos)); 1000 } 957 1001 958 while (bufptr < buffer + len) 959 { 960 v = *bufptr++; 961 if (state == 0x000001) 962 { 963 state = ((state << 8) | v) & 0xFFFFFF; 964 965 if (state == PACK_HEADER) 966 { 967 long long startpos = ringBuffer->GetWritePosition(); 968 startpos += buildbuffersize + bufptr - bufstart - 4; 969 lastpackheaderpos = startpos; 1002 if ((last - pos) < TSPacket::SIZE) { 1003 VERBOSE(VB_RECORD, LOC_ERR + 1004 QString("TS packet at %1 stradles end of buffer.") 1005 .arg(pos)); 1006 leftover = last - pos; 1007 memmove(&data[TSPacket::SIZE - leftover], &data[pos], leftover); 1008 return; 1009 } 970 1010 971 int curpos = bufptr - bufstart - 4; 972 if (curpos < 0) 973 { 974 // header was split 975 buildbuffersize += curpos; 976 if (buildbuffersize > 0) 977 ringBuffer->Write(buildbuffer, buildbuffersize); 1011 ProcessTSPacket(* reinterpret_cast<const TSPacket *>(data + pos)); 978 1012 979 buildbuffersize = 4; 980 memcpy(buildbuffer, &state, 4); 1013 // Next packet 1014 idx = pos + TSPacket::SIZE; 1015 } 981 1016 982 leftlen = leftlen - curpos + 4; 983 bufstart = bufptr; 984 } 985 else 986 { 987 // header was entirely in this packet 988 memcpy(buildbuffer + buildbuffersize, bufstart, curpos); 989 buildbuffersize += curpos; 990 bufstart += curpos; 991 leftlen -= curpos; 1017 leftover = 0; 1018 return; 1019 } 992 1020 993 if (buildbuffersize > 0) 994 ringBuffer->Write(buildbuffer, buildbuffersize); 1021 void MpegRecorder::ProcessTSPacket(const TSPacket &tspacket) 1022 { 1023 if (!_stream_data) 1024 return; 995 1025 996 buildbuffersize = 0; 997 } 998 } 1026 if (tspacket.TransportError() || tspacket.ScramplingControl()) 1027 return; 999 1028 1000 if (state == SEQ_START) 1001 { 1002 lastseqstart = lastpackheaderpos; 1003 } 1029 if (tspacket.HasAdaptationField()) 1030 _stream_data->HandleAdaptationFieldControl(&tspacket); 1004 1031 1005 if (state == GOP_START && lastseqstart == lastpackheaderpos) 1006 { 1007 framesWritten = numgops * keyframedist; 1008 numgops++; 1009 HandleKeyframe(); 1010 } 1011 } 1012 else 1013 state = ((state << 8) | v) & 0xFFFFFF; 1014 } 1032 if (tspacket.HasPayload()) 1033 { 1034 const unsigned int lpid = tspacket.PID(); 1015 1035 1016 leftovers = state; 1036 // Pass or reject packets based on PID, and parse info from them 1037 // if (lpid == _stream_data->VideoPIDSingleProgram()) 1038 if (lpid == 4113) 1039 { 1040 _buffer_packets = !FindH264Keyframes(&tspacket); 1017 1041 1018 if (buildbuffersize + leftlen > kBuildBufferMaxSize) 1019 { 1020 ringBuffer->Write(buildbuffer, buildbuffersize); 1021 buildbuffersize = 0; 1042 if (_seen_sps) 1043 BufferedWrite(tspacket); 1044 } 1045 // else if (_stream_data->IsAudioPID(lpid)) 1046 else if (lpid == 4352) 1047 { 1048 _buffer_packets = !FindAudioKeyframes(&tspacket); 1049 BufferedWrite(tspacket); 1050 } 1051 else { 1052 BufferedWrite(tspacket); 1053 } 1022 1054 } 1023 1024 // copy remaining..1025 memcpy(buildbuffer + buildbuffersize, bufstart, leftlen);1026 buildbuffersize += leftlen;1027 1055 } 1028 1056 1029 1057 void MpegRecorder::StopRecording(void) … … 1033 1061 1034 1062 void MpegRecorder::ResetForNewFile(void) 1035 1063 { 1036 errored = false; 1037 framesWritten = 0; 1038 numgops = 0; 1039 lastseqstart = lastpackheaderpos = 0; 1064 DTVRecorder::ResetForNewFile(); 1040 1065 1041 positionMap.clear();1042 positionMapDelta.clear();1043 1066 } 1044 1067 1045 1068 void MpegRecorder::Reset(void) 1046 1069 { 1070 VERBOSE(VB_RECORD, LOC + "Reset(void)"); 1047 1071 ResetForNewFile(); 1048 1072 1049 leftovers = 0xFFFFFFFF; 1050 buildbuffersize = 0; 1073 _start_code = 0xffffffff; 1051 1074 1052 if (curRecording) 1053 curRecording->ClearPositionMap(MARK_GOP_START); 1075 if (curRecording) { 1076 if (driver == "hdpvr") { 1077 curRecording->ClearPositionMap(MARK_GOP_BYFRAME); 1078 } 1079 else { 1080 curRecording->ClearPositionMap(MARK_GOP_START); 1081 } 1082 } 1054 1083 } 1055 1084 1056 1085 void MpegRecorder::Pause(bool clear) … … 1095 1124 command.cmd = V4L2_ENC_CMD_START; 1096 1125 ioctl(readfd, VIDIOC_ENCODER_CMD, &command); 1097 1126 } 1127 1128 if (_stream_data) 1129 _stream_data->Reset(_stream_data->DesiredProgram()); 1098 1130 } 1099 1131 paused = false; 1100 1132 } 1101 1133 return paused; 1102 1134 } 1103 1135 1104 long long MpegRecorder::GetKeyframePosition(long long desired)1136 void MpegRecorder::SetStreamData(MPEGStreamData *data) 1105 1137 { 1106 QMutexLocker locker(&positionMapLock); 1107 long long ret = -1; 1138 VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- begin"); 1108 1139 1109 if (positionMap.find(desired) != positionMap.end()) 1110 ret = positionMap[desired]; 1140 if (data == _stream_data) 1141 { 1142 VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 0"); 1111 1143 1112 return ret; 1144 return; 1145 } 1146 1147 MPEGStreamData *old_data = _stream_data; 1148 _stream_data = data; 1149 if (old_data) 1150 delete old_data; 1151 1152 if (data) 1153 data->AddMPEGSPListener(this); 1154 1155 VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 1"); 1113 1156 } 1114 1157 1115 // documented in recorderbase.h 1116 void MpegRecorder::SetNextRecording(const ProgramInfo *progInf, RingBuffer *rb) 1158 void MpegRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat) 1117 1159 { 1118 // First we do some of the time consuming stuff we can do now 1119 SavePositionMap(true); 1120 ringBuffer->WriterFlush(); 1121 if (curRecording) 1122 curRecording->SetFilesize(ringBuffer->GetRealFileSize()); 1160 if (!pat) 1161 return; 1123 1162 1124 // Then we set the next info 1125 { 1126 QMutexLocker locker(&nextRingBufferLock); 1127 nextRecording = NULL; 1128 if (progInf) 1129 nextRecording = new ProgramInfo(*progInf); 1130 nextRingBuffer = rb; 1131 } 1163 int next = (pat->tsheader()->ContinuityCounter()+1)&0xf; 1164 pat->tsheader()->SetContinuityCounter(next); 1165 BufferedWrite(*(reinterpret_cast<const TSPacket*>(pat->tsheader()))); 1132 1166 } 1133 1167 1134 /** \fn MpegRecorder::HandleKeyframe(void) 1135 * \brief This save the current frame to the position maps 1136 * and handles ringbuffer switching. 1137 */ 1138 void MpegRecorder::HandleKeyframe(void) 1168 void MpegRecorder::HandleSingleProgramPMT(ProgramMapTable *pmt) 1139 1169 { 1140 // Add key frame to position map 1141 positionMapLock.lock(); 1142 if (!positionMap.contains(numgops)) 1143 { 1144 positionMapDelta[numgops] = lastpackheaderpos; 1145 positionMap[numgops] = lastpackheaderpos; 1146 } 1147 positionMapLock.unlock(); 1170 if (!pmt) 1171 return; 1148 1172 1149 // Perform ringbuffer switch if needed. 1150 CheckForRingBufferSwitch(); 1173 int next = (pmt->tsheader()->ContinuityCounter()+1)&0xf; 1174 pmt->tsheader()->SetContinuityCounter(next); 1175 BufferedWrite(*(reinterpret_cast<const TSPacket*>(pmt->tsheader()))); 1151 1176 } 1152