Ticket #5443: hdpvr-0.13-recorder.patch
File hdpvr-0.13-recorder.patch, 47.3 KB (added by , 16 years ago) |
---|
-
libs/libmythtv/dvbrecorder.cpp
120 120 121 121 void DVBRecorder::TeardownAll(void) 122 122 { 123 // Make SURE that the device read thread is cleaned up -- John Poet123 // Make SURE that the device read thread is cleaned up 124 124 StopRecording(); 125 125 126 126 if (IsOpen()) -
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() … … 108 110 { 109 111 if (ringBuffer) 110 112 { 111 if ( _payload_buffer.size())113 if (!_payload_buffer.empty()) 112 114 { 113 115 ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 114 116 _payload_buffer.clear(); … … 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, uint len); 64 void ProcessTSdata(unsigned char * data, uint len, uint & leftover); 65 bool ProcessTSPacket(const TSPacket &tspacket); 63 66 64 67 void ResetForNewFile(void); 65 68 69 inline bool CheckCC(uint pid, uint cc); 70 66 71 bool deviceIsMpegFile; 67 72 int bufferSize; 68 73 … … 78 83 // State 79 84 bool recording; 80 85 bool encoding; 81 bool errored;82 86 83 87 // Pausing state 84 88 bool cleartimeonpause; 85 89 86 // Number of frames written87 long long framesWritten;88 89 90 // Encoding info 90 91 int width, height; 91 92 int bitrate, maxbitrate, streamtype, aspectratio; … … 97 98 int chanfd; 98 99 int readfd; 99 100 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 101 static const int audRateL1[]; 113 102 static const int audRateL2[]; 114 103 static const int audRateL3[]; 115 104 static const char *streamType[]; 116 105 static const char *aspectRatio[]; 117 106 static const unsigned int kBuildBufferMaxSize; 107 108 // TS 109 MPEGStreamData *_stream_data; 110 unsigned char _stream_id[0x1fff]; 111 unsigned char _pid_status[0x1fff]; 112 unsigned char _continuity_counter[0x1fff]; 113 static const unsigned char kPayloadStartSeen = 0x2; 114 115 // Statistics 116 mutable uint _continuity_error_count; 117 mutable uint _stream_overflow_count; 118 mutable uint _bad_packet_count; 118 119 }; 120 121 inline bool MpegRecorder::CheckCC(uint pid, uint new_cnt) 122 { 123 bool ok = ((((_continuity_counter[pid] + 1) & 0xf) == new_cnt) || 124 (_continuity_counter[pid] == 0xFF)); 125 126 _continuity_counter[pid] = new_cnt & 0xf; 127 128 return ok; 129 } 130 119 131 #endif -
libs/libmythtv/mpegrecorder.cpp
34 34 #include "util.h" 35 35 #include "cardutil.h" 36 36 37 // the audio and video PIDs are in the Program Map Table 38 // the PID of the PMT are specified in the Program Association Table 39 37 40 // ivtv header 38 41 extern "C" { 39 42 #include "ivtv_myth.h" … … 48 51 const int MpegRecorder::audRateL1[] = 49 52 { 50 53 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0 51 };54 }; 52 55 53 56 const int MpegRecorder::audRateL2[] = 54 57 { … … 73 76 "Square", "4:3", "16:9", "2.21:1", 0 74 77 }; 75 78 76 const unsigned int MpegRecorder::kBuildBufferMaxSize = 1024 * 1024; 77 78 MpegRecorder::MpegRecorder(TVRec *rec) : 79 RecorderBase(rec), 79 MpegRecorder::MpegRecorder(TVRec *rec) : DTVRecorder(rec), 80 80 // Debugging variables 81 81 deviceIsMpegFile(false), 82 bufferSize(4096),83 82 // Driver info 84 83 card(QString::null), driver(QString::null), 85 84 version(0), usingv4l2(false), … … 87 86 requires_special_pause(false), 88 87 // State 89 88 recording(false), encoding(false), 90 errored(false),91 89 // Pausing state 92 90 cleartimeonpause(false), 93 // Number of frames written94 framesWritten(0),95 91 // Encoding info 96 92 width(720), height(480), 97 93 bitrate(4500), maxbitrate(6000), … … 102 98 audvolume(80), language(0), 103 99 // Input file descriptors 104 100 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) 101 // TS packet handling 102 _stream_data(NULL) 112 103 { 113 104 SetPositionMapType(MARK_GOP_START); 114 105 } … … 116 107 MpegRecorder::~MpegRecorder() 117 108 { 118 109 TeardownAll(); 119 delete [] buildbuffer;120 110 } 121 111 122 112 void MpegRecorder::TeardownAll(void) 123 113 { 114 StopRecording(); 115 124 116 if (chanfd >= 0) 125 117 { 126 118 close(chanfd); … … 131 123 close(readfd); 132 124 readfd = -1; 133 125 } 126 134 127 } 135 128 136 129 static int find_index(const int *audio_rate, int value) … … 332 325 333 326 if (CardUtil::GetV4LInfo(chanfd, card, driver, version)) 334 327 { 328 // driver = "hdpvr"; 329 335 330 if (driver == "ivtv") 336 331 { 332 bufferSize = 4096; 333 337 334 usingv4l2 = (version >= IVTV_KERNEL_VERSION(0, 8, 0)); 338 335 has_v4l2_vbi = (version >= IVTV_KERNEL_VERSION(0, 3, 8)); 339 336 has_buggy_vbi = true; 340 337 requires_special_pause = 341 338 (version >= IVTV_KERNEL_VERSION(0, 10, 0)); 342 339 } 340 else if (driver == "hdpvr") 341 { 342 bufferSize = 1500 * TSPacket::SIZE; 343 usingv4l2 = true; 344 requires_special_pause = true; 345 346 bzero(_stream_id, sizeof(_stream_id)); 347 bzero(_pid_status, sizeof(_pid_status)); 348 memset(_continuity_counter, 0xff, sizeof(_continuity_counter)); 349 } 343 350 else 344 351 { 345 VERBOSE(VB_IMPORTANT, "\n\nNot ivtv driver??\n\n");352 VERBOSE(VB_IMPORTANT, "\n\nNot ivtv or hdpvr driver??\n\n"); 346 353 usingv4l2 = has_v4l2_vbi = true; 347 354 has_buggy_vbi = requires_special_pause = false; 348 355 } … … 354 361 355 362 struct v4l2_format vfmt; 356 363 bzero(&vfmt, sizeof(vfmt)); 357 364 358 365 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 359 366 360 367 if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) < 0) 361 368 { 362 369 VERBOSE(VB_IMPORTANT, LOC_ERR + "Error getting format" + ENO); 363 370 return false; 364 371 } 372 373 if (driver != "hdpvr") { 374 vfmt.fmt.pix.width = width; 375 vfmt.fmt.pix.height = height; 376 377 if (ioctl(chanfd, VIDIOC_S_FMT, &vfmt) < 0) 378 { 379 VERBOSE(VB_IMPORTANT, LOC_ERR + "Error setting format" + ENO); 380 return false; 381 } 365 382 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: 383 // Set audio language mode 384 bool do_audmode_set = true; 385 struct v4l2_tuner vt; 386 bzero(&vt, sizeof(struct v4l2_tuner)); 387 if (ioctl(chanfd, VIDIOC_G_TUNER, &vt) < 0) 388 { 389 VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get audio mode" + ENO); 390 do_audmode_set = false; 391 } 392 393 switch (language) 394 { 395 case 0: 388 396 vt.audmode = V4L2_TUNER_MODE_LANG1; 389 397 break; 390 case 1:398 case 1: 391 399 vt.audmode = V4L2_TUNER_MODE_LANG2; 392 400 break; 393 case 2:401 case 2: 394 402 if (usingv4l2) 395 403 vt.audmode = V4L2_TUNER_MODE_LANG1_LANG2; 396 404 else 397 405 vt.audmode = V4L2_TUNER_MODE_STEREO; 398 406 break; 399 default:407 default: 400 408 vt.audmode = V4L2_TUNER_MODE_LANG1; 401 }409 } 402 410 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 }411 int audio_layer = GetFilteredAudioLayer(); 412 if (do_audmode_set && (2 == language) && (1 == audio_layer)) 413 { 414 VERBOSE(VB_GENERAL, "Dual audio mode incompatible with Layer I audio." 415 "\n\t\t\tFalling back to Main Language"); 416 vt.audmode = V4L2_TUNER_MODE_LANG1; 417 } 410 418 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 }419 if (do_audmode_set && ioctl(chanfd, VIDIOC_S_TUNER, &vt) < 0) 420 { 421 VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to set audio mode" + ENO); 422 } 415 423 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 }424 // Get volume min/max values 425 struct v4l2_queryctrl qctrl; 426 qctrl.id = V4L2_CID_AUDIO_VOLUME; 427 if (ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) < 0) 428 { 429 VERBOSE(VB_IMPORTANT, LOC_WARN + 430 "Unable to get recording volume parameters(max/min)" + ENO + 431 "\n\t\t\tusing default range [0,65535]."); 432 qctrl.maximum = 65535; 433 qctrl.minimum = 0; 434 } 427 435 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));436 // calculate volume in card units. 437 int range = qctrl.maximum - qctrl.minimum; 438 int value = (int) ((range * audvolume * 0.01f) + qctrl.minimum); 439 int ctrl_volume = min(qctrl.maximum, max(qctrl.minimum, value)); 432 440 433 // Set recording volume434 struct v4l2_control ctrl;435 ctrl.id = V4L2_CID_AUDIO_VOLUME;436 ctrl.value = ctrl_volume;441 // Set recording volume 442 struct v4l2_control ctrl; 443 ctrl.id = V4L2_CID_AUDIO_VOLUME; 444 ctrl.value = ctrl_volume; 437 445 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."); 446 if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) < 0) 447 { 448 VERBOSE(VB_IMPORTANT, LOC_WARN + 449 "Unable to set recording volume" + ENO + "\n\t\t\t" + 450 "If you are using an AverMedia M179 card this is normal."); 451 } 443 452 } 444 453 445 454 bool ok = true; … … 457 466 458 467 SetVBIOptions(chanfd); 459 468 460 readfd = open(videodevice.ascii(), O_RDWR | O_NONBLOCK); 469 // hdpvr driver does not like NONBLOCK mode with select 470 if (driver == "hdpvr") 471 readfd = open(videodevice.ascii(), O_RDWR); 472 else 473 readfd = open(videodevice.ascii(), O_RDWR | O_NONBLOCK); 474 461 475 if (readfd < 0) 462 476 { 463 477 VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't open video device." + ENO); … … 475 489 { 476 490 switch (st) 477 491 { 478 479 480 481 482 483 484 492 case 2: st = 2; break; 493 case 10: 494 case 13: 495 case 14: st = 10; break; 496 case 11: st = 11; break; 497 case 12: st = 12; break; 498 default: st = 0; break; 485 499 } 486 500 } 501 else if (driver == "hdpvr") 502 { 503 // FIX ME! // I have no idea what to put here 504 switch (st) 505 { 506 case 2: st = 2; break; 507 case 10: 508 case 13: 509 case 14: st = 10; break; 510 case 11: st = 11; break; 511 case 12: st = 12; break; 512 default: st = 0; break; 513 } 514 } 487 515 488 516 if (st != (uint) streamtype) 489 517 { … … 502 530 503 531 sr = (driver == "ivtv") ? 48000 : sr; // only 48kHz works properly. 504 532 533 // hdpvr ? 534 535 505 536 if (sr != (uint) audsamplerate) 506 537 { 507 538 VERBOSE(VB_IMPORTANT, LOC_WARN + … … 512 543 513 544 switch (sr) 514 545 { 515 516 517 518 546 case 32000: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000; 547 case 44100: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100; 548 case 48000: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; 549 default: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; 519 550 } 520 551 } 521 552 … … 527 558 528 559 layer = (driver == "ivtv") ? 2 : layer; 529 560 561 // hdpvr? 562 563 530 564 if (layer != (uint) audtype) 531 565 { 532 566 VERBOSE(VB_IMPORTANT, LOC_WARN + … … 587 621 { 588 622 switch (st) 589 623 { 590 591 592 593 594 595 596 597 598 599 600 601 624 case 0: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS; 625 case 1: return V4L2_MPEG_STREAM_TYPE_MPEG2_TS; 626 case 2: return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD; 627 case 3: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS; /* PES A/V */ 628 case 5: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS; /* PES V */ 629 case 7: return V4L2_MPEG_STREAM_TYPE_MPEG2_PS; /* PES A */ 630 case 10: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD; 631 case 11: return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD; /* VCD */ 632 case 12: return V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD; 633 case 13: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD; /* DVD-Special 1 */ 634 case 14: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD; /* DVD-Special 2 */ 635 default: return V4L2_MPEG_STREAM_TYPE_MPEG2_TS; 602 636 } 603 637 } 604 638 605 639 bool MpegRecorder::SetV4L2DeviceOptions(int chanfd) 606 640 { 607 641 static const uint kNumControls = 7; 608 642 struct v4l2_ext_controls ctrls; 609 643 struct v4l2_ext_control ext_ctrl[kNumControls]; 610 644 QString control_description[kNumControls] = … … 625 659 uint audio_layer = GetFilteredAudioLayer(); 626 660 uint audbitrate = GetFilteredAudioBitRate(audio_layer); 627 661 628 ext_ctrl[0].id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ; 629 ext_ctrl[0].value = GetFilteredAudioSampleRate(); 662 if (driver != "hdpvr") { 663 ext_ctrl[0].id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ; 664 ext_ctrl[0].value = GetFilteredAudioSampleRate(); 665 666 ext_ctrl[1].id = V4L2_CID_MPEG_VIDEO_ASPECT; 667 ext_ctrl[1].value = aspectratio - 1; 668 669 ext_ctrl[2].id = V4L2_CID_MPEG_AUDIO_ENCODING; 670 ext_ctrl[2].value = audio_layer - 1; 671 672 ext_ctrl[3].id = V4L2_CID_MPEG_AUDIO_L2_BITRATE; 673 ext_ctrl[3].value = audbitrate - 1; 630 674 631 ext_ctrl[1].id = V4L2_CID_MPEG_VIDEO_ASPECT; 632 ext_ctrl[1].value = aspectratio - 1; 675 ext_ctrl[4].id = V4L2_CID_MPEG_STREAM_TYPE; 676 ext_ctrl[4].value = streamtype_ivtv_to_v4l2(GetFilteredStreamType()); 677 } 633 678 634 ext_ctrl[ 2].id = V4L2_CID_MPEG_AUDIO_ENCODING;635 ext_ctrl[ 2].value = audio_layer - 1;679 ext_ctrl[5].id = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK; 680 ext_ctrl[5].value = maxbitrate * 1000; 636 681 637 ext_ctrl[ 3].id = V4L2_CID_MPEG_AUDIO_L2_BITRATE;638 ext_ctrl[ 3].value = audbitrate - 1;682 ext_ctrl[6].id = V4L2_CID_MPEG_VIDEO_BITRATE; 683 ext_ctrl[6].value = (bitrate = min(bitrate, maxbitrate)) * 1000; 639 684 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 685 for (uint i = 0; i < kNumControls; i++) 650 686 { 651 687 int value = ext_ctrl[i].value; 652 688 689 if (value != 0) { 690 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG; 691 ctrls.count = 1; 692 ctrls.controls = ext_ctrl + i; 693 694 if (ioctl(chanfd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0) 695 { 696 VERBOSE(VB_IMPORTANT, LOC_ERR + 697 QString("Could not set %1 to %2") 698 .arg(control_description[i]).arg(value) + ENO); 699 } 700 } 701 } 702 703 if (driver != "hdpvr") { 704 // Get controls 705 ext_ctrl[0].id = V4L2_CID_MPEG_VIDEO_GOP_SIZE; 706 ext_ctrl[0].value = 0; 707 653 708 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG; 654 709 ctrls.count = 1; 655 ctrls.controls = ext_ctrl + i;656 657 if (ioctl(chanfd, VIDIOC_ S_EXT_CTRLS, &ctrls) < 0)710 ctrls.controls = ext_ctrl; 711 712 if (ioctl(chanfd, VIDIOC_G_EXT_CTRLS, &ctrls) < 0) 658 713 { 659 VERBOSE(VB_IMPORTANT, LOC_ ERR +660 QString("Could not set %1 to %2")661 .arg(control_description[i]).arg(value) + ENO);714 VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get " 715 "V4L2_CID_MPEG_VIDEO_GOP_SIZE, defaulting to 12" + ENO); 716 ext_ctrl[0].value = 12; 662 717 } 718 719 keyframedist = ext_ctrl[0].value; 663 720 } 664 721 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 722 return true; 683 723 } 684 724 … … 687 727 if (!vbimode) 688 728 return true; 689 729 730 if (driver == "hdpvr") 731 return true; 732 690 733 if (has_buggy_vbi) 691 734 { 692 735 cout<<" *********************** WARNING ***********************"<<endl; … … 717 760 718 761 if (ioctl(chanfd, IVTV_IOC_G_VBI_MODE, &vbifmt) >= 0) 719 762 { 720 VERBOSE(VB_RECORD, LOC + QString(721 763 VERBOSE(VB_RECORD, 764 LOC + QString("VBI service:%1, packet size:%2, io size:%3") 722 765 .arg(vbifmt.service_set).arg(vbifmt.packet_size) 723 766 .arg(vbifmt.io_size)); 724 767 } … … 733 776 bzero(&vbifmt, sizeof(struct v4l2_format)); 734 777 vbifmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; 735 778 vbifmt.fmt.sliced.service_set |= (1 == vbimode) ? 736 V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;779 V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525; 737 780 738 781 if (ioctl(chanfd, VIDIOC_S_FMT, &vbifmt) < 0) 739 782 { … … 809 852 { 810 853 if (!Open()) 811 854 { 812 errored= true;813 855 _error = true; 856 return; 814 857 } 815 858 816 if (!SetupRecording()) 817 { 818 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to setup recording."); 819 errored = true; 820 return; 859 _start_code = 0xffffffff; 860 _last_gop_seen = 0; 861 _frames_written_count = 0; 862 863 if (driver == "hdpvr") { 864 SetPositionMapType(MARK_GOP_BYFRAME); 865 866 if (_stream_data == NULL) { 867 MPEGStreamData *sd = new MPEGStreamData(1, true); 868 sd->Reset(); 869 sd->SetRecordingType(_recording_type); 870 SetStreamData(sd); 871 } 872 else 873 _stream_data->Reset(1); 874 875 // Make sure the first things in the file are a PAT & PMT 876 _wait_for_keyframe_option = false; 877 HandleSingleProgramPAT(_stream_data->PATSingleProgram()); 878 HandleSingleProgramPMT(_stream_data->PMTSingleProgram()); 879 _wait_for_keyframe_option = true; 821 880 } 881 else { 882 SetPositionMapType(MARK_GOP_START); 883 } 822 884 823 885 encoding = true; 824 886 recording = true; 887 825 888 unsigned char *buffer = new unsigned char[bufferSize + 1]; 826 int ret;889 uint remainder = 0; 827 890 891 int len; 892 828 893 MythTimer elapsedTimer; 829 894 float elapsed; 830 895 … … 839 904 if (PauseAndWait(100)) 840 905 continue; 841 906 842 if ((deviceIsMpegFile) && ( framesWritten))907 if ((deviceIsMpegFile) && (GetFramesWritten())) 843 908 { 844 909 elapsed = (elapsedTimer.elapsed() / 1000.0) + 1; 845 while (( framesWritten/ elapsed) > 30)910 while ((GetFramesWritten() / elapsed) > 30) 846 911 { 847 912 usleep(50000); 848 913 elapsed = (elapsedTimer.elapsed() / 1000.0) + 1; … … 852 917 if (readfd < 0) 853 918 readfd = open(videodevice.ascii(), O_RDWR); 854 919 855 tv.tv_sec = 5;856 tv.tv_usec = 0;857 FD_ZERO(&rdset);858 FD_SET(readfd, &rdset);859 860 920 #if defined(__FreeBSD__) 861 921 // HACK. FreeBSD PVR150/500 driver doesn't currently support select() 862 922 #else 863 switch (select(readfd + 1, &rdset, NULL, NULL, &tv)) 864 { 865 case -1: 923 // hdpvr driver does not like NONBLOCK mode with select 924 if (driver != "hdpvr") { 925 tv.tv_sec = 5; 926 tv.tv_usec = 0; 927 FD_ZERO(&rdset); 928 FD_SET(readfd, &rdset); 929 930 switch (select(readfd + 1, &rdset, NULL, NULL, &tv)) 931 { 932 case -1: 866 933 if (errno == EINTR) 867 934 continue; 868 935 869 936 VERBOSE(VB_IMPORTANT, LOC_ERR + "Select error" + ENO); 870 937 continue; 871 872 case 0:938 939 case 0: 873 940 VERBOSE(VB_IMPORTANT, LOC_ERR + "select timeout - " 874 941 "ivtv driver has stopped responding"); 875 942 876 943 if (close(readfd) != 0) 877 944 { 878 945 VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO); 879 946 } 880 947 881 948 readfd = -1; // Force PVR card to be reopened on next iteration 882 949 continue; 883 884 default: break; 950 951 default: break; 952 } 885 953 } 886 954 #endif 887 955 888 ret = read(readfd, buffer, bufferSize); 956 if (remainder) 957 VERBOSE(VB_RECORD, LOC + QString("Remainder %1, Reading %2 bytes") 958 .arg(remainder).arg(bufferSize - remainder)); 959 len = read(readfd, &(buffer[remainder]), bufferSize - remainder); 889 960 890 if ((ret == 0) && 891 (deviceIsMpegFile)) 961 if ((len == 0) && (deviceIsMpegFile)) 892 962 { 893 963 close(readfd); 894 964 readfd = open(videodevice.ascii(), O_RDONLY); 895 965 896 966 if (readfd >= 0) 897 ret = read(readfd, buffer, bufferSize); 898 if (ret <= 0) 967 len = read(readfd, &(buffer[remainder]), 968 bufferSize - remainder); 969 if (len <= 0) 899 970 { 900 971 encoding = false; 901 972 continue; 902 973 } 903 974 } 904 else if ( ret< 0 && errno != EAGAIN)975 else if (len < 0 && errno != EAGAIN) 905 976 { 906 977 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("error reading from: %1") 907 978 .arg(videodevice) + ENO); 908 909 979 continue; 910 980 } 911 else if ( ret> 0)981 else if (len > 0) 912 982 { 913 ProcessData(buffer, ret); 983 len += remainder; 984 985 if (driver == "hdpvr") 986 ProcessTSdata(buffer, len, remainder); 987 else 988 ProcessPSdata(buffer, len); 914 989 } 915 990 } 916 991 917 992 FinishRecording(); 993 TeardownAll(); 918 994 919 995 delete[] buffer; 920 996 recording = false; 921 997 } 922 998 923 bool MpegRecorder::SetupRecording(void)999 void MpegRecorder::ProcessPSdata(unsigned char *buffer, uint len) 924 1000 { 925 leftovers = 0xFFFFFFFF; 926 numgops = 0; 927 lastseqstart = 0; 928 return true; 1001 FindPSKeyFrames(buffer, len); 929 1002 } 930 1003 931 void MpegRecorder::FinishRecording(void) 1004 void MpegRecorder::ProcessTSdata(unsigned char * buffer, uint len, 1005 uint & remainder) 932 1006 { 933 ringBuffer->WriterFlush(); 1007 uint idx, pos; 1008 int synced_cnt = 0; 934 1009 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 } 1010 #if 0 1011 VERBOSE(VB_RECORD, LOC + QString("idx: %1, end: %2, remainder: %3, len: %4") 1012 .arg(TSPacket::SIZE - remainder) 1013 .arg(end) 1014 .arg(remainder) 1015 .arg(len)); 1016 #endif 1017 for (idx = 0; idx < len; ) { 1018 // Find header 1019 for (pos = idx; pos < len; ++pos) { 1020 if (buffer[pos] == SYNC_BYTE ) 1021 break; 1022 } 945 1023 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 1024 if (pos == len) { 1025 VERBOSE(VB_IMPORTANT, LOC_ERR + "No TS header."); 1026 break; 1027 } 951 1028 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; 1029 if (pos > idx) { 1030 VERBOSE(VB_IMPORTANT, LOC_ERR + 1031 QString("TS packet at %1 not in sync, after %2") 1032 .arg(pos).arg(synced_cnt)); 1033 synced_cnt = 0; 1034 } 1035 else 1036 ++synced_cnt; 957 1037 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; 1038 if ((len - pos) < TSPacket::SIZE) { 1039 remainder = len - pos; 1040 memmove(buffer, &buffer[pos], remainder); 1041 VERBOSE(VB_RECORD, LOC_ERR + 1042 QString("TS packet at %1 stradles end of buffer.") 1043 .arg(pos)); 1044 VERBOSE(VB_RECORD, LOC + 1045 QString("remainder: %1, idx: %2, pos: %3") 1046 .arg(remainder) 1047 .arg(idx) 1048 .arg(pos)); 1049 return; 1050 } 970 1051 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); 1052 ProcessTSPacket(* reinterpret_cast<const TSPacket *>(buffer + pos)); 978 1053 979 buildbuffersize = 4; 980 memcpy(buildbuffer, &state, 4); 1054 // Next packet 1055 idx = pos + TSPacket::SIZE; 1056 } 981 1057 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; 1058 remainder = 0; 1059 return; 1060 } 992 1061 993 if (buildbuffersize > 0) 994 ringBuffer->Write(buildbuffer, buildbuffersize); 1062 bool MpegRecorder::ProcessTSPacket(const TSPacket &tspacket) 1063 { 1064 if (!_stream_data) { 1065 VERBOSE(VB_RECORD, "ProcessTSPacket: !_stream_data"); 1066 return false; 1067 } 995 1068 996 buildbuffersize = 0; 997 } 998 } 1069 if (tspacket.TransportError() || tspacket.ScramplingControl()) 1070 return false; 999 1071 1000 if (state == SEQ_START) 1001 { 1002 lastseqstart = lastpackheaderpos; 1003 } 1072 if (tspacket.HasAdaptationField()) 1073 _stream_data->HandleAdaptationFieldControl(&tspacket); 1004 1074 1005 if (state == GOP_START && lastseqstart == lastpackheaderpos) 1006 { 1007 framesWritten = numgops * keyframedist; 1008 numgops++; 1009 HandleKeyframe(); 1010 } 1075 if (tspacket.HasPayload()) 1076 { 1077 const unsigned int lpid = tspacket.PID(); 1078 1079 // Pass or reject packets based on PID, and parse info from them 1080 if (lpid == _stream_data->VideoPIDSingleProgram()) 1081 { 1082 _buffer_packets = !FindH264Keyframes(&tspacket); 1083 1084 if (!_seen_sps) 1085 return true; 1011 1086 } 1012 else 1013 state = ((state << 8) | v) & 0xFFFFFF; 1014 } 1087 else if (_stream_data->IsAudioPID(lpid)) 1088 { 1089 _buffer_packets = !FindAudioKeyframes(&tspacket); 1090 } 1091 else if (GetStreamData()->IsListeningPID(lpid)) 1092 GetStreamData()->HandleTSTables(&tspacket); 1093 else if (GetStreamData()->IsWritingPID(lpid)) 1094 BufferedWrite(tspacket); 1015 1095 1016 leftovers = state; 1017 1018 if (buildbuffersize + leftlen > kBuildBufferMaxSize) 1019 { 1020 ringBuffer->Write(buildbuffer, buildbuffersize); 1021 buildbuffersize = 0; 1096 const uint pid = tspacket.PID(); 1097 1098 // Check continuity counter 1099 if ((pid != 0x1fff) && !CheckCC(pid, tspacket.ContinuityCounter())) 1100 { 1101 VERBOSE(VB_RECORD, LOC + 1102 QString("PID 0x%1 discontinuity detected").arg(pid,0,16)); 1103 _continuity_error_count++; 1104 } 1105 1106 // Sync recording start to first keyframe 1107 if (_wait_for_keyframe_option && _first_keyframe < 0) 1108 return true; 1109 1110 // Sync streams to the first Payload Unit Start Indicator 1111 // _after_ first keyframe iff _wait_for_keyframe_option is true 1112 if (!(_pid_status[pid] & kPayloadStartSeen) && tspacket.HasPayload()) 1113 { 1114 if (!tspacket.PayloadStart()) 1115 return true; // not payload start - drop packet 1116 1117 VERBOSE(VB_RECORD, 1118 QString("PID 0x%1 Found Payload Start").arg(pid,0,16)); 1119 1120 _pid_status[pid] |= kPayloadStartSeen; 1121 } 1122 1123 BufferedWrite(tspacket); 1022 1124 } 1023 1125 1024 // copy remaining.. 1025 memcpy(buildbuffer + buildbuffersize, bufstart, leftlen); 1026 buildbuffersize += leftlen; 1126 return true; 1027 1127 } 1028 1128 1029 1129 void MpegRecorder::StopRecording(void) … … 1033 1133 1034 1134 void MpegRecorder::ResetForNewFile(void) 1035 1135 { 1036 errored = false; 1037 framesWritten = 0; 1038 numgops = 0; 1039 lastseqstart = lastpackheaderpos = 0; 1136 DTVRecorder::ResetForNewFile(); 1040 1137 1041 positionMap.clear(); 1042 positionMapDelta.clear(); 1138 bzero(_stream_id, sizeof(_stream_id)); 1139 bzero(_pid_status, sizeof(_pid_status)); 1140 memset(_continuity_counter, 0xff, sizeof(_continuity_counter)); 1043 1141 } 1044 1142 1045 1143 void MpegRecorder::Reset(void) 1046 1144 { 1145 VERBOSE(VB_RECORD, LOC + "Reset(void)"); 1047 1146 ResetForNewFile(); 1048 1147 1049 leftovers = 0xFFFFFFFF; 1050 buildbuffersize = 0; 1148 _start_code = 0xffffffff; 1051 1149 1052 if (curRecording) 1053 curRecording->ClearPositionMap(MARK_GOP_START); 1150 if (curRecording) { 1151 if (driver == "hdpvr") { 1152 curRecording->ClearPositionMap(MARK_GOP_BYFRAME); 1153 } 1154 else { 1155 curRecording->ClearPositionMap(MARK_GOP_START); 1156 } 1157 } 1054 1158 } 1055 1159 1056 1160 void MpegRecorder::Pause(bool clear) … … 1095 1199 command.cmd = V4L2_ENC_CMD_START; 1096 1200 ioctl(readfd, VIDIOC_ENCODER_CMD, &command); 1097 1201 } 1202 1203 if (_stream_data) 1204 _stream_data->Reset(_stream_data->DesiredProgram()); 1098 1205 } 1099 1206 paused = false; 1100 1207 } 1101 1208 return paused; 1102 1209 } 1103 1210 1104 long long MpegRecorder::GetKeyframePosition(long long desired)1211 void MpegRecorder::SetStreamData(MPEGStreamData *data) 1105 1212 { 1106 QMutexLocker locker(&positionMapLock); 1107 long long ret = -1; 1213 VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- begin"); 1108 1214 1109 if (positionMap.find(desired) != positionMap.end()) 1110 ret = positionMap[desired]; 1215 if (data == _stream_data) 1216 { 1217 VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 0"); 1111 1218 1112 return ret; 1219 return; 1220 } 1221 1222 MPEGStreamData *old_data = _stream_data; 1223 _stream_data = data; 1224 if (old_data) 1225 delete old_data; 1226 1227 if (data) 1228 data->AddMPEGSPListener(this); 1229 1230 data->SetDesiredProgram(1); 1231 1232 VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 1"); 1113 1233 } 1114 1234 1115 // documented in recorderbase.h 1116 void MpegRecorder::SetNextRecording(const ProgramInfo *progInf, RingBuffer *rb) 1235 void MpegRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat) 1117 1236 { 1118 // First we do some of the time consuming stuff we can do now1119 SavePositionMap(true);1120 ringBuffer->WriterFlush();1121 if (curRecording) 1122 curRecording->SetFilesize(ringBuffer->GetRealFileSize());1237 if (!pat) 1238 { 1239 VERBOSE(VB_RECORD, LOC + "HandleSingleProgramPAT(NULL)"); 1240 return; 1241 } 1123 1242 1124 // Then we set the next info 1243 if (!ringBuffer) 1244 return; 1245 1246 uint posA[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() }; 1247 1248 uint next_cc = (pat->tsheader()->ContinuityCounter()+1)&0xf; 1249 pat->tsheader()->SetContinuityCounter(next_cc); 1250 DTVRecorder::BufferedWrite(*(reinterpret_cast<TSPacket*>(pat->tsheader()))); 1251 1252 uint posB[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() }; 1253 1254 #if 0 1255 if (posB[0] + posB[1] * TSPacket::SIZE > 1256 posA[0] + posA[1] * TSPacket::SIZE) 1125 1257 { 1126 QMutexLocker locker(&nextRingBufferLock); 1127 nextRecording = NULL; 1128 if (progInf) 1129 nextRecording = new ProgramInfo(*progInf); 1130 nextRingBuffer = rb; 1258 VERBOSE(VB_RECORD, LOC + "Wrote PAT @" 1259 << posA[0] << " + " << (posA[1] * TSPacket::SIZE)); 1131 1260 } 1261 else 1262 { 1263 VERBOSE(VB_RECORD, LOC + "Saw PAT but did not write to disk yet"); 1264 } 1265 #endif 1132 1266 } 1133 1267 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) 1268 void MpegRecorder::HandleSingleProgramPMT(ProgramMapTable *pmt) 1139 1269 { 1140 // Add key frame to position map 1141 positionMapLock.lock(); 1142 if (!positionMap.contains(numgops)) 1270 if (!pmt) { 1271 return; 1272 } 1273 1274 // collect stream types for H.264 (MPEG-4 AVC) keyframe detection 1275 for (uint i = 0; i < pmt->StreamCount(); i++) 1276 _stream_id[pmt->StreamPID(i)] = pmt->StreamType(i); 1277 1278 if (!ringBuffer) 1279 return; 1280 1281 unsigned char buf[8 * 1024]; 1282 uint next_cc = (pmt->tsheader()->ContinuityCounter()+1)&0xf; 1283 pmt->tsheader()->SetContinuityCounter(next_cc); 1284 uint size = pmt->WriteAsTSPackets(buf, next_cc); 1285 1286 uint posA[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() }; 1287 1288 for (uint i = 0; i < size ; i += TSPacket::SIZE) 1289 DTVRecorder::BufferedWrite(*(reinterpret_cast<TSPacket*>(&buf[i]))); 1290 1291 uint posB[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() }; 1292 1293 #if 1 1294 if (posB[0] + posB[1] * TSPacket::SIZE > 1295 posA[0] + posA[1] * TSPacket::SIZE) 1143 1296 { 1144 positionMapDelta[numgops] = lastpackheaderpos;1145 positionMap[numgops] = lastpackheaderpos;1297 VERBOSE(VB_RECORD, LOC + "Wrote PMT @" 1298 << posA[0] << " + " << (posA[1] * TSPacket::SIZE)); 1146 1299 } 1147 positionMapLock.unlock(); 1148 1149 // Perform ringbuffer switch if needed. 1150 CheckForRingBufferSwitch(); 1300 else 1301 { 1302 VERBOSE(VB_RECORD, LOC + "Saw PMT but did not write to disk yet"); 1303 } 1304 #endif 1151 1305 } 1152 1306