Ticket #5443: hdpvr-0.14-recorder.patch
File hdpvr-0.14-recorder.patch, 49.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, 15 public TSPacketListener, 16 public TSPacketListenerAV 12 17 { 13 18 public: 14 19 MpegRecorder(TVRec*); … … 33 38 bool PauseAndWait(int timeout = 100); 34 39 35 40 bool IsRecording(void) { return recording; } 36 bool IsErrored(void) { return errored; }37 41 38 long long GetFramesWritten(void) { return framesWritten; }39 40 42 bool Open(void); 41 43 int GetVideoFd(void) { return chanfd; } 42 44 43 long long GetKeyframePosition(long long desired); 45 // TS 46 virtual void SetStreamData(MPEGStreamData*); 47 virtual MPEGStreamData *GetStreamData(void) { return _stream_data; } 44 48 45 void SetNextRecording(const ProgramInfo*, RingBuffer*); 49 // TSPacketListenerAV 50 bool ProcessVideoTSPacket(const TSPacket& tspacket); 51 bool ProcessAudioTSPacket(const TSPacket& tspacket); 52 bool ProcessAVTSPacket(const TSPacket &tspacket); 46 53 54 // implements MPEGSingleProgramStreamListener 55 void HandleSingleProgramPAT(ProgramAssociationTable *pat); 56 void HandleSingleProgramPMT(ProgramMapTable *pmt); 57 47 58 private: 48 bool SetupRecording(void);49 void FinishRecording(void);50 void HandleKeyframe(void);51 52 59 void ProcessData(unsigned char *buffer, int len); 53 60 54 61 bool OpenMpegFileAsInput(void); … … 60 67 uint GetFilteredAudioSampleRate(void) const; 61 68 uint GetFilteredAudioLayer(void) const; 62 69 uint GetFilteredAudioBitRate(uint audio_layer) const; 70 void ProcessPSdata(unsigned char *buffer, uint len); 63 71 72 // TSPacketListener 73 bool ProcessTSPacket(const TSPacket &tspacket); 74 64 75 void ResetForNewFile(void); 65 76 77 inline bool CheckCC(uint pid, uint cc); 78 66 79 bool deviceIsMpegFile; 67 80 int bufferSize; 68 81 … … 78 91 // State 79 92 bool recording; 80 93 bool encoding; 81 bool errored;82 94 83 95 // Pausing state 84 96 bool cleartimeonpause; 85 97 86 // Number of frames written87 long long framesWritten;88 89 98 // Encoding info 90 99 int width, height; 91 100 int bitrate, maxbitrate, streamtype, aspectratio; … … 97 106 int chanfd; 98 107 int readfd; 99 108 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 109 static const int audRateL1[]; 113 110 static const int audRateL2[]; 114 111 static const int audRateL3[]; 115 112 static const char *streamType[]; 116 113 static const char *aspectRatio[]; 117 114 static const unsigned int kBuildBufferMaxSize; 115 116 // TS 117 MPEGStreamData *_stream_data; 118 unsigned char _stream_id[0x1fff]; 119 unsigned char _pid_status[0x1fff]; 120 unsigned char _continuity_counter[0x1fff]; 121 static const unsigned char kPayloadStartSeen = 0x2; 122 123 // Statistics 124 mutable uint _continuity_error_count; 125 mutable uint _stream_overflow_count; 126 mutable uint _bad_packet_count; 118 127 }; 128 129 inline bool MpegRecorder::CheckCC(uint pid, uint new_cnt) 130 { 131 bool ok = ((((_continuity_counter[pid] + 1) & 0xf) == new_cnt) || 132 (_continuity_counter[pid] == 0xFF)); 133 134 _continuity_counter[pid] = new_cnt & 0xf; 135 136 return ok; 137 } 138 119 139 #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 = 500 * 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 { … … 805 848 return OpenV4L2DeviceAsInput(); 806 849 } 807 850 851 void MpegRecorder::StopRecording(void) 852 { 853 encoding = false; 854 } 855 856 void MpegRecorder::ResetForNewFile(void) 857 { 858 DTVRecorder::ResetForNewFile(); 859 860 bzero(_stream_id, sizeof(_stream_id)); 861 bzero(_pid_status, sizeof(_pid_status)); 862 memset(_continuity_counter, 0xff, sizeof(_continuity_counter)); 863 } 864 865 void MpegRecorder::Reset(void) 866 { 867 VERBOSE(VB_RECORD, LOC + "Reset(void)"); 868 ResetForNewFile(); 869 870 _start_code = 0xffffffff; 871 872 if (curRecording) { 873 if (driver == "hdpvr") { 874 curRecording->ClearPositionMap(MARK_GOP_BYFRAME); 875 } 876 else { 877 curRecording->ClearPositionMap(MARK_GOP_START); 878 } 879 } 880 } 881 882 void MpegRecorder::Pause(bool clear) 883 { 884 cleartimeonpause = clear; 885 paused = false; 886 request_pause = true; 887 } 888 889 bool MpegRecorder::PauseAndWait(int timeout) 890 { 891 if (request_pause) 892 { 893 if (!paused) 894 { 895 VERBOSE(VB_RECORD, "MpegRecorder::PauseAndWait pausing"); 896 if (requires_special_pause) 897 { 898 // Some ivtv drivers require streaming to be disabled before 899 // an input switch and other channel format setting. 900 struct v4l2_encoder_cmd command; 901 memset(&command, 0, sizeof(struct v4l2_encoder_cmd)); 902 command.cmd = V4L2_ENC_CMD_STOP; 903 ioctl(readfd, VIDIOC_ENCODER_CMD, &command); 904 } 905 906 paused = true; 907 pauseWait.wakeAll(); 908 if (tvrec) 909 tvrec->RecorderPaused(); 910 } 911 unpauseWait.wait(timeout); 912 } 913 if (!request_pause) 914 { 915 if (paused) 916 { 917 VERBOSE(VB_RECORD, "MpegRecorder::PauseAndWait un-pausing"); 918 if (requires_special_pause) 919 { 920 // Some ivtv drivers require streaming to be disabled before 921 // an input switch and other channel format setting. 922 struct v4l2_encoder_cmd command; 923 command.cmd = V4L2_ENC_CMD_START; 924 ioctl(readfd, VIDIOC_ENCODER_CMD, &command); 925 } 926 927 if (_stream_data) 928 _stream_data->Reset(_stream_data->DesiredProgram()); 929 } 930 paused = false; 931 } 932 return paused; 933 } 934 935 void MpegRecorder::SetStreamData(MPEGStreamData *data) 936 { 937 VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- begin"); 938 939 if (data == _stream_data) 940 { 941 VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 0"); 942 943 return; 944 } 945 946 MPEGStreamData *old_data = _stream_data; 947 _stream_data = data; 948 if (old_data) 949 delete old_data; 950 951 if (data) 952 data->AddMPEGSPListener(this); 953 954 data->SetDesiredProgram(1); 955 956 VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 1"); 957 } 958 808 959 void MpegRecorder::StartRecording(void) 809 960 { 810 961 if (!Open()) 811 962 { 812 errored= true;813 963 _error = true; 964 return; 814 965 } 815 966 816 if (!SetupRecording()) 817 { 818 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to setup recording."); 819 errored = true; 820 return; 967 VERBOSE(VB_RECORD, "MpegRecorder::StartRecording"); 968 969 _start_code = 0xffffffff; 970 _last_gop_seen = 0; 971 _frames_written_count = 0; 972 973 if (driver == "hdpvr") { 974 SetPositionMapType(MARK_GOP_BYFRAME); 975 976 if (_stream_data == NULL) { 977 MPEGStreamData *sd = new MPEGStreamData(1, true); 978 sd->Reset(); 979 sd->SetRecordingType(_recording_type); 980 SetStreamData(sd); 981 } 982 else 983 _stream_data->Reset(1); 984 985 _stream_data->AddAVListener(this); 986 _stream_data->AddWritingListener(this); 987 988 // Make sure the first things in the file are a PAT & PMT 989 _wait_for_keyframe_option = false; 990 HandleSingleProgramPAT(_stream_data->PATSingleProgram()); 991 HandleSingleProgramPMT(_stream_data->PMTSingleProgram()); 992 _wait_for_keyframe_option = true; 821 993 } 994 else { 995 SetPositionMapType(MARK_GOP_START); 996 } 822 997 823 998 encoding = true; 824 999 recording = true; 1000 825 1001 unsigned char *buffer = new unsigned char[bufferSize + 1]; 826 int ret;1002 uint remainder = 0; 827 1003 1004 int len; 1005 828 1006 MythTimer elapsedTimer; 829 1007 float elapsed; 830 1008 … … 839 1017 if (PauseAndWait(100)) 840 1018 continue; 841 1019 842 if ((deviceIsMpegFile) && ( framesWritten))1020 if ((deviceIsMpegFile) && (GetFramesWritten())) 843 1021 { 844 1022 elapsed = (elapsedTimer.elapsed() / 1000.0) + 1; 845 while (( framesWritten/ elapsed) > 30)1023 while ((GetFramesWritten() / elapsed) > 30) 846 1024 { 847 1025 usleep(50000); 848 1026 elapsed = (elapsedTimer.elapsed() / 1000.0) + 1; … … 852 1030 if (readfd < 0) 853 1031 readfd = open(videodevice.ascii(), O_RDWR); 854 1032 855 tv.tv_sec = 5;856 tv.tv_usec = 0;857 FD_ZERO(&rdset);858 FD_SET(readfd, &rdset);859 860 1033 #if defined(__FreeBSD__) 861 1034 // HACK. FreeBSD PVR150/500 driver doesn't currently support select() 862 1035 #else 863 switch (select(readfd + 1, &rdset, NULL, NULL, &tv)) 864 { 865 case -1: 1036 // hdpvr driver does not like NONBLOCK mode with select 1037 if (driver != "hdpvr") { 1038 tv.tv_sec = 5; 1039 tv.tv_usec = 0; 1040 FD_ZERO(&rdset); 1041 FD_SET(readfd, &rdset); 1042 1043 switch (select(readfd + 1, &rdset, NULL, NULL, &tv)) 1044 { 1045 case -1: 866 1046 if (errno == EINTR) 867 1047 continue; 868 1048 869 1049 VERBOSE(VB_IMPORTANT, LOC_ERR + "Select error" + ENO); 870 1050 continue; 871 872 case 0:1051 1052 case 0: 873 1053 VERBOSE(VB_IMPORTANT, LOC_ERR + "select timeout - " 874 1054 "ivtv driver has stopped responding"); 875 1055 876 1056 if (close(readfd) != 0) 877 1057 { 878 1058 VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO); 879 1059 } 880 1060 881 1061 readfd = -1; // Force PVR card to be reopened on next iteration 882 1062 continue; 883 884 default: break; 1063 1064 default: break; 1065 } 885 1066 } 886 1067 #endif 887 1068 888 ret = read(readfd, buffer, bufferSize); 1069 if (remainder) 1070 VERBOSE(VB_RECORD, LOC + QString("Remainder %1, Reading %2 bytes") 1071 .arg(remainder).arg(bufferSize - remainder)); 1072 len = read(readfd, &(buffer[remainder]), bufferSize - remainder); 889 1073 890 if ((ret == 0) && 891 (deviceIsMpegFile)) 1074 if ((len == 0) && (deviceIsMpegFile)) 892 1075 { 893 1076 close(readfd); 894 1077 readfd = open(videodevice.ascii(), O_RDONLY); 895 1078 896 1079 if (readfd >= 0) 897 ret = read(readfd, buffer, bufferSize); 898 if (ret <= 0) 1080 len = read(readfd, &(buffer[remainder]), 1081 bufferSize - remainder); 1082 if (len <= 0) 899 1083 { 900 1084 encoding = false; 901 1085 continue; 902 1086 } 903 1087 } 904 else if ( ret< 0 && errno != EAGAIN)1088 else if (len < 0 && errno != EAGAIN) 905 1089 { 906 1090 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("error reading from: %1") 907 1091 .arg(videodevice) + ENO); 908 909 1092 continue; 910 1093 } 911 else if ( ret> 0)1094 else if (len > 0) 912 1095 { 913 ProcessData(buffer, ret); 1096 len += remainder; 1097 1098 if (driver == "hdpvr") 1099 remainder = _stream_data->ProcessData(buffer, len); 1100 else 1101 ProcessPSdata(buffer, len); 914 1102 } 915 1103 } 916 1104 917 1105 FinishRecording(); 1106 TeardownAll(); 918 1107 919 1108 delete[] buffer; 920 1109 recording = false; 1110 1111 VERBOSE(VB_RECORD, "MpegRecorder::StartRecording done"); 921 1112 } 922 1113 923 bool MpegRecorder::SetupRecording(void)1114 void MpegRecorder::ProcessPSdata(unsigned char *buffer, uint len) 924 1115 { 925 leftovers = 0xFFFFFFFF; 926 numgops = 0; 927 lastseqstart = 0; 928 return true; 1116 FindPSKeyFrames(buffer, len); 929 1117 } 930 1118 931 void MpegRecorder::FinishRecording(void)1119 bool MpegRecorder::ProcessTSPacket(const TSPacket &tspacket) 932 1120 { 933 ringBuffer->WriterFlush();1121 const uint pid = tspacket.PID(); 934 1122 935 if (curRecording) 1123 // Check continuity counter 1124 if ((pid != 0x1fff) && !CheckCC(pid, tspacket.ContinuityCounter())) 936 1125 { 937 curRecording->SetFilesize(ringBuffer->GetRealFileSize()); 938 SavePositionMap(true); 1126 VERBOSE(VB_RECORD, LOC + 1127 QString("PID 0x%1 discontinuity detected").arg(pid,0,16)); 1128 _continuity_error_count++; 939 1129 } 940 positionMapLock.lock(); 941 positionMap.clear(); 942 positionMapDelta.clear(); 943 positionMapLock.unlock(); 1130 1131 // Only write the packet 1132 // if audio/video key-frames have been found 1133 if (_wait_for_keyframe_option && _first_keyframe < 0) 1134 return true; 1135 1136 _buffer_packets = true; 1137 1138 BufferedWrite(tspacket); 1139 1140 return true; 944 1141 } 945 1142 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 951 952 void MpegRecorder::ProcessData(unsigned char *buffer, int len) 1143 bool MpegRecorder::ProcessVideoTSPacket(const TSPacket &tspacket) 953 1144 { 954 unsigned char *bufptr = buffer, *bufstart = buffer; 955 unsigned int state = leftovers, v = 0; 956 int leftlen = len; 1145 uint streamType = _stream_id[tspacket.PID()]; 957 1146 958 while (bufptr < buffer + len) 1147 // Check for keyframes and count frames 1148 if (streamType == StreamID::H264Video) 959 1149 { 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; 1150 _buffer_packets = !FindH264Keyframes(&tspacket); 1151 if (!_seen_sps) 1152 return true; 1153 } 1154 else 1155 { 1156 _buffer_packets = !FindMPEG2Keyframes(&tspacket); 1157 } 970 1158 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); 1159 return ProcessAVTSPacket(tspacket); 1160 } 978 1161 979 buildbuffersize = 4; 980 memcpy(buildbuffer, &state, 4); 1162 bool MpegRecorder::ProcessAudioTSPacket(const TSPacket &tspacket) 1163 { 1164 _buffer_packets = !FindAudioKeyframes(&tspacket); 1165 return ProcessAVTSPacket(tspacket); 1166 } 981 1167 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; 1168 /// Common code for processing either audio or video packets 1169 bool MpegRecorder::ProcessAVTSPacket(const TSPacket &tspacket) 1170 { 1171 const uint pid = tspacket.PID(); 992 1172 993 if (buildbuffersize > 0) 994 ringBuffer->Write(buildbuffer, buildbuffersize); 1173 // Check continuity counter 1174 if ((pid != 0x1fff) && !CheckCC(pid, tspacket.ContinuityCounter())) 1175 { 1176 VERBOSE(VB_RECORD, LOC + 1177 QString("PID 0x%1 discontinuity detected").arg(pid,0,16)); 1178 _continuity_error_count++; 1179 } 995 1180 996 buildbuffersize = 0;997 }998 }1181 // Sync recording start to first keyframe 1182 if (_wait_for_keyframe_option && _first_keyframe < 0) 1183 return true; 999 1184 1000 if (state == SEQ_START) 1001 { 1002 lastseqstart = lastpackheaderpos; 1003 } 1185 // Sync streams to the first Payload Unit Start Indicator 1186 // _after_ first keyframe iff _wait_for_keyframe_option is true 1187 if (!(_pid_status[pid] & kPayloadStartSeen) && tspacket.HasPayload()) 1188 { 1189 if (!tspacket.PayloadStart()) 1190 return true; // not payload start - drop packet 1004 1191 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 } 1192 VERBOSE(VB_RECORD, 1193 QString("PID 0x%1 Found Payload Start").arg(pid,0,16)); 1015 1194 1016 leftovers = state; 1017 1018 if (buildbuffersize + leftlen > kBuildBufferMaxSize) 1019 { 1020 ringBuffer->Write(buildbuffer, buildbuffersize); 1021 buildbuffersize = 0; 1195 _pid_status[pid] |= kPayloadStartSeen; 1022 1196 } 1023 1197 1024 // copy remaining.. 1025 memcpy(buildbuffer + buildbuffersize, bufstart, leftlen); 1026 buildbuffersize += leftlen; 1027 } 1198 BufferedWrite(tspacket); 1028 1199 1029 void MpegRecorder::StopRecording(void) 1030 { 1031 encoding = false; 1200 return true; 1032 1201 } 1033 1202 1034 void MpegRecorder::ResetForNewFile(void) 1203 1204 void MpegRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat) 1035 1205 { 1036 errored = false; 1037 framesWritten = 0; 1038 numgops = 0; 1039 lastseqstart = lastpackheaderpos = 0; 1206 if (!pat) 1207 { 1208 VERBOSE(VB_RECORD, LOC + "HandleSingleProgramPAT(NULL)"); 1209 return; 1210 } 1040 1211 1041 positionMap.clear(); 1042 positionMapDelta.clear(); 1043 } 1212 if (!ringBuffer) 1213 return; 1044 1214 1045 void MpegRecorder::Reset(void) 1046 { 1047 ResetForNewFile(); 1215 uint posA[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() }; 1048 1216 1049 leftovers = 0xFFFFFFFF; 1050 buildbuffersize = 0; 1217 uint next_cc = (pat->tsheader()->ContinuityCounter()+1)&0xf; 1218 pat->tsheader()->SetContinuityCounter(next_cc); 1219 DTVRecorder::BufferedWrite(*(reinterpret_cast<TSPacket*>(pat->tsheader()))); 1051 1220 1052 if (curRecording) 1053 curRecording->ClearPositionMap(MARK_GOP_START); 1054 } 1221 uint posB[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() }; 1055 1222 1056 void MpegRecorder::Pause(bool clear) 1057 { 1058 cleartimeonpause = clear; 1059 paused = false; 1060 request_pause = true; 1061 } 1062 1063 bool MpegRecorder::PauseAndWait(int timeout) 1064 { 1065 if (request_pause) 1223 #if 0 1224 if (posB[0] + posB[1] * TSPacket::SIZE > 1225 posA[0] + posA[1] * TSPacket::SIZE) 1066 1226 { 1067 if (!paused) 1068 { 1069 if (requires_special_pause) 1070 { 1071 // Some ivtv drivers require streaming to be disabled before 1072 // an input switch and other channel format setting. 1073 struct v4l2_encoder_cmd command; 1074 memset(&command, 0, sizeof(struct v4l2_encoder_cmd)); 1075 command.cmd = V4L2_ENC_CMD_STOP; 1076 ioctl(readfd, VIDIOC_ENCODER_CMD, &command); 1077 } 1078 1079 paused = true; 1080 pauseWait.wakeAll(); 1081 if (tvrec) 1082 tvrec->RecorderPaused(); 1083 } 1084 unpauseWait.wait(timeout); 1227 VERBOSE(VB_RECORD, LOC + "Wrote PAT @" 1228 << posA[0] << " + " << (posA[1] * TSPacket::SIZE)); 1085 1229 } 1086 if (!request_pause)1230 else 1087 1231 { 1088 if (paused) 1089 { 1090 if (requires_special_pause) 1091 { 1092 // Some ivtv drivers require streaming to be disabled before 1093 // an input switch and other channel format setting. 1094 struct v4l2_encoder_cmd command; 1095 command.cmd = V4L2_ENC_CMD_START; 1096 ioctl(readfd, VIDIOC_ENCODER_CMD, &command); 1097 } 1098 } 1099 paused = false; 1232 VERBOSE(VB_RECORD, LOC + "Saw PAT but did not write to disk yet"); 1100 1233 } 1101 return paused; 1234 #endif 1102 1235 } 1103 1236 1104 long long MpegRecorder::GetKeyframePosition(long long desired)1237 void MpegRecorder::HandleSingleProgramPMT(ProgramMapTable *pmt) 1105 1238 { 1106 QMutexLocker locker(&positionMapLock); 1107 long long ret = -1; 1239 if (!pmt) { 1240 return; 1241 } 1108 1242 1109 if (positionMap.find(desired) != positionMap.end()) 1110 ret = positionMap[desired]; 1243 // collect stream types for H.264 (MPEG-4 AVC) keyframe detection 1244 for (uint i = 0; i < pmt->StreamCount(); i++) 1245 _stream_id[pmt->StreamPID(i)] = pmt->StreamType(i); 1111 1246 1112 return ret;1113 } 1247 if (!ringBuffer) 1248 return; 1114 1249 1115 // documented in recorderbase.h 1116 void MpegRecorder::SetNextRecording(const ProgramInfo *progInf, RingBuffer *rb) 1117 { 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()); 1250 unsigned char buf[8 * 1024]; 1251 uint next_cc = (pmt->tsheader()->ContinuityCounter()+1)&0xf; 1252 pmt->tsheader()->SetContinuityCounter(next_cc); 1253 uint size = pmt->WriteAsTSPackets(buf, next_cc); 1123 1254 1124 // Then we set the next info 1255 uint posA[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() }; 1256 1257 for (uint i = 0; i < size ; i += TSPacket::SIZE) 1258 DTVRecorder::BufferedWrite(*(reinterpret_cast<TSPacket*>(&buf[i]))); 1259 1260 uint posB[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() }; 1261 1262 #if 0 1263 if (posB[0] + posB[1] * TSPacket::SIZE > 1264 posA[0] + posA[1] * TSPacket::SIZE) 1125 1265 { 1126 QMutexLocker locker(&nextRingBufferLock); 1127 nextRecording = NULL; 1128 if (progInf) 1129 nextRecording = new ProgramInfo(*progInf); 1130 nextRingBuffer = rb; 1266 VERBOSE(VB_RECORD, LOC + "Wrote PMT @" 1267 << posA[0] << " + " << (posA[1] * TSPacket::SIZE)); 1131 1268 } 1132 } 1133 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) 1139 { 1140 // Add key frame to position map 1141 positionMapLock.lock(); 1142 if (!positionMap.contains(numgops)) 1269 else 1143 1270 { 1144 positionMapDelta[numgops] = lastpackheaderpos; 1145 positionMap[numgops] = lastpackheaderpos; 1271 VERBOSE(VB_RECORD, LOC + "Saw PMT but did not write to disk yet"); 1146 1272 } 1147 positionMapLock.unlock(); 1148 1149 // Perform ringbuffer switch if needed. 1150 CheckForRingBufferSwitch(); 1273 #endif 1151 1274 } 1152 1275