diff --git a/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp b/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp
index 60549f8..b1b63e2 100644
|
a
|
b
|
DTVRecorder::DTVRecorder(TVRec *rec) :
|
| 87 | 87 | { |
| 88 | 88 | SetPositionMapType(MARK_GOP_BYFRAME); |
| 89 | 89 | _payload_buffer.reserve(TSPacket::kSize * (50 + 1)); |
| | 90 | |
| 90 | 91 | ResetForNewFile(); |
| | 92 | |
| | 93 | memset(_stream_id, 0, sizeof(_stream_id)); |
| | 94 | memset(_pid_status, 0, sizeof(_pid_status)); |
| | 95 | memset(_continuity_counter, 0xff, sizeof(_continuity_counter)); |
| 91 | 96 | } |
| 92 | 97 | |
| 93 | 98 | DTVRecorder::~DTVRecorder() |
| … |
… |
void DTVRecorder::SetOptionsFromProfile(RecordingProfile *profile,
|
| 147 | 152 | void DTVRecorder::FinishRecording(void) |
| 148 | 153 | { |
| 149 | 154 | if (ringBuffer) |
| 150 | | { |
| 151 | | if (!_payload_buffer.empty()) |
| 152 | | { |
| 153 | | ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); |
| 154 | | _payload_buffer.clear(); |
| 155 | | } |
| 156 | 155 | ringBuffer->WriterFlush(); |
| 157 | | } |
| 158 | 156 | |
| 159 | 157 | if (curRecording) |
| 160 | 158 | { |
| … |
… |
void DTVRecorder::ResetForNewFile(void)
|
| 171 | 169 | LOG(VB_RECORD, LOG_INFO, LOC + "ResetForNewFile(void)"); |
| 172 | 170 | QMutexLocker locker(&positionMapLock); |
| 173 | 171 | |
| 174 | | // _first_keyframe, _seen_psp and m_h264_parser should |
| | 172 | // _seen_psp and m_h264_parser should |
| 175 | 173 | // not be reset here. This will only be called just as |
| 176 | 174 | // we're seeing the first packet of a new keyframe for |
| 177 | 175 | // writing to the new file and anything that makes the |
| … |
… |
void DTVRecorder::ResetForNewFile(void)
|
| 180 | 178 | // -- Daniel Kristjansson 2011-02-26 |
| 181 | 179 | |
| 182 | 180 | _start_code = 0xffffffff; |
| 183 | | //_first_keyframe |
| | 181 | _first_keyframe = -1; |
| 184 | 182 | _has_written_other_keyframe = false; |
| 185 | 183 | _last_keyframe_seen = 0; |
| 186 | 184 | _last_gop_seen = 0; |
| … |
… |
void DTVRecorder::ResetForNewFile(void)
|
| 191 | 189 | //_recording |
| 192 | 190 | _error = QString(); |
| 193 | 191 | |
| 194 | | memset(_stream_id, 0, sizeof(_stream_id)); |
| 195 | | memset(_pid_status, 0, sizeof(_pid_status)); |
| 196 | | memset(_continuity_counter, 0xff, sizeof(_continuity_counter)); |
| 197 | | |
| 198 | 192 | _progressive_sequence = 0; |
| 199 | 193 | _repeat_pict = 0; |
| 200 | 194 | |
| 201 | | _pes_synced = false; |
| | 195 | //_pes_synced |
| 202 | 196 | //_seen_sps |
| 203 | 197 | positionMap.clear(); |
| 204 | 198 | positionMapDelta.clear(); |
| 205 | 199 | durationMap.clear(); |
| 206 | 200 | durationMapDelta.clear(); |
| 207 | | _payload_buffer.clear(); |
| 208 | 201 | |
| 209 | 202 | locker.unlock(); |
| 210 | 203 | ClearStatistics(); |
| … |
… |
void DTVRecorder::ClearStatistics(void)
|
| 215 | 208 | RecorderBase::ClearStatistics(); |
| 216 | 209 | |
| 217 | 210 | memset(_ts_count, 0, sizeof(_ts_count)); |
| 218 | | for (int i = 0; i < 256; i++) |
| | 211 | for (int i = 0; i < 256; ++i) |
| 219 | 212 | _ts_last[i] = -1LL; |
| 220 | | for (int i = 0; i < 256; i++) |
| | 213 | for (int i = 0; i < 256; ++i) |
| 221 | 214 | _ts_first[i] = -1LL; |
| 222 | 215 | //_ts_first_dt -- doesn't need to be cleared only used if _ts_first>=0 |
| 223 | 216 | _packet_count.fetchAndStoreRelaxed(0); |
| … |
… |
void DTVRecorder::InitStreamData(void)
|
| 277 | 270 | void DTVRecorder::BufferedWrite(const TSPacket &tspacket) |
| 278 | 271 | { |
| 279 | 272 | // delay until first GOP to avoid decoder crash on res change |
| 280 | | if (_wait_for_keyframe_option && _first_keyframe<0) |
| | 273 | if (!_buffer_packets && _wait_for_keyframe_option && _first_keyframe < 0) |
| 281 | 274 | return; |
| 282 | 275 | |
| 283 | 276 | if (curRecording && timeOfFirstDataIsSet.testAndSetRelaxed(0,1)) |
| … |
… |
static const uint frameRateMap[16] = {
|
| 403 | 396 | */ |
| 404 | 397 | bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket) |
| 405 | 398 | { |
| 406 | | bool haveBufferedData = !_payload_buffer.empty(); |
| 407 | 399 | if (!tspacket->HasPayload()) // no payload to scan |
| 408 | | return !haveBufferedData; |
| | 400 | return _first_keyframe >= 0; |
| 409 | 401 | |
| 410 | 402 | if (!ringBuffer) |
| 411 | | return !haveBufferedData; |
| | 403 | return _first_keyframe >= 0; |
| 412 | 404 | |
| 413 | 405 | // if packet contains start of PES packet, start |
| 414 | 406 | // looking for first byte of MPEG start code (3 bytes 0 0 1) |
| … |
… |
bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket)
|
| 540 | 532 | |
| 541 | 533 | if (hasKeyFrame) |
| 542 | 534 | { |
| | 535 | #if 0 |
| | 536 | LOG(VB_RECORD, LOG_ERR, LOC + QString |
| | 537 | ("Keyframe @ %1 + %2 = %3") |
| | 538 | .arg(ringBuffer->GetWritePosition()) |
| | 539 | .arg(_payload_buffer.size()) |
| | 540 | .arg(ringBuffer->GetWritePosition() + _payload_buffer.size())); |
| | 541 | #endif |
| 543 | 542 | _last_keyframe_seen = _frames_seen_count; |
| 544 | | HandleKeyframe(_frames_written_count, TSPacket::kSize); |
| | 543 | HandleKeyframe(0); |
| 545 | 544 | } |
| 546 | 545 | |
| 547 | 546 | if (hasFrame) |
| 548 | 547 | { |
| | 548 | #if 0 |
| | 549 | LOG(VB_RECORD, LOG_ERR, LOC + QString |
| | 550 | ("Frame @ %1 + %2 = %3") |
| | 551 | .arg(ringBuffer->GetWritePosition()) |
| | 552 | .arg(_payload_buffer.size()) |
| | 553 | .arg(ringBuffer->GetWritePosition() + _payload_buffer.size())); |
| | 554 | #endif |
| | 555 | _buffer_packets = false; // We know know if it is a keyframe, or not |
| 549 | 556 | _frames_seen_count++; |
| 550 | | if (!_wait_for_keyframe_option || _first_keyframe>=0) |
| | 557 | if (!_wait_for_keyframe_option || _first_keyframe >= 0) |
| 551 | 558 | UpdateFramesWritten(); |
| | 559 | else |
| | 560 | { |
| | 561 | /* Found a frame that is not a keyframe, and we want to |
| | 562 | * start on a keyframe */ |
| | 563 | _payload_buffer.clear(); |
| | 564 | } |
| 552 | 565 | } |
| 553 | 566 | |
| 554 | 567 | if ((aspectRatio > 0) && (aspectRatio != m_videoAspect)) |
| … |
… |
bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket)
|
| 572 | 585 | FrameRateChange(frameRate, _frames_written_count); |
| 573 | 586 | } |
| 574 | 587 | |
| 575 | | return hasKeyFrame || (_payload_buffer.size() >= (188*50)); |
| | 588 | return _first_keyframe >= 0; |
| 576 | 589 | } |
| 577 | 590 | |
| 578 | 591 | void DTVRecorder::HandleTimestamps(int stream_id, int64_t pts, int64_t dts) |
| … |
… |
bool DTVRecorder::FindAudioKeyframes(const TSPacket*)
|
| 680 | 693 | if (1 == (_frames_seen_count & 0x7)) |
| 681 | 694 | { |
| 682 | 695 | _last_keyframe_seen = _frames_seen_count; |
| 683 | | HandleKeyframe(_frames_written_count); |
| | 696 | HandleKeyframe(_payload_buffer.size()); |
| 684 | 697 | hasKeyFrame = true; |
| 685 | 698 | } |
| 686 | 699 | |
| … |
… |
bool DTVRecorder::FindOtherKeyframes(const TSPacket *tspacket)
|
| 708 | 721 | UpdateFramesWritten(); |
| 709 | 722 | _last_keyframe_seen = _frames_seen_count; |
| 710 | 723 | |
| 711 | | HandleKeyframe(_frames_written_count); |
| | 724 | HandleKeyframe(_payload_buffer.size()); |
| 712 | 725 | |
| 713 | 726 | _has_written_other_keyframe = true; |
| 714 | 727 | |
| … |
… |
bool DTVRecorder::FindOtherKeyframes(const TSPacket *tspacket)
|
| 719 | 732 | * \brief This save the current frame to the position maps |
| 720 | 733 | * and handles ringbuffer switching. |
| 721 | 734 | */ |
| 722 | | void DTVRecorder::HandleKeyframe(uint64_t frameNum, int64_t extra) |
| | 735 | void DTVRecorder::HandleKeyframe(int64_t extra) |
| 723 | 736 | { |
| 724 | 737 | if (!ringBuffer) |
| 725 | 738 | return; |
| 726 | 739 | |
| 727 | | #if 0 |
| 728 | | unsigned long long frameNum = _frames_written_count; |
| 729 | | #endif |
| | 740 | // Perform ringbuffer switch if needed. |
| | 741 | CheckForRingBufferSwitch(); |
| 730 | 742 | |
| | 743 | uint64_t frameNum = _frames_written_count; |
| 731 | 744 | _first_keyframe = (_first_keyframe < 0) ? frameNum : _first_keyframe; |
| 732 | 745 | |
| 733 | 746 | // Add key frame to position map |
| 734 | 747 | positionMapLock.lock(); |
| 735 | 748 | if (!positionMap.contains(frameNum)) |
| 736 | 749 | { |
| 737 | | long long startpos = ringBuffer->GetWritePosition(); |
| 738 | | // FIXME: handle keyframes with start code spanning over two ts packets |
| 739 | | startpos += _payload_buffer.size() - extra; |
| | 750 | int64_t startpos = ringBuffer->GetWritePosition() + extra; |
| 740 | 751 | |
| 741 | 752 | // Don't put negative offsets into the database, they get munged into |
| 742 | 753 | // MAX_INT64 - offset, which is an exceedingly large number, and |
| … |
… |
void DTVRecorder::HandleKeyframe(uint64_t frameNum, int64_t extra)
|
| 750 | 761 | } |
| 751 | 762 | } |
| 752 | 763 | positionMapLock.unlock(); |
| 753 | | |
| 754 | | // Perform ringbuffer switch if needed. |
| 755 | | CheckForRingBufferSwitch(); |
| 756 | 764 | } |
| 757 | 765 | |
| 758 | 766 | /** \fn DTVRecorder::FindH264Keyframes(const TSPacket*) |
| … |
… |
void DTVRecorder::HandleKeyframe(uint64_t frameNum, int64_t extra)
|
| 762 | 770 | */ |
| 763 | 771 | bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket) |
| 764 | 772 | { |
| | 773 | if (!tspacket->HasPayload()) // no payload to scan |
| | 774 | return _first_keyframe >= 0; |
| | 775 | |
| 765 | 776 | if (!ringBuffer) |
| 766 | 777 | { |
| 767 | 778 | LOG(VB_GENERAL, LOG_ERR, LOC + "FindH264Keyframes: No ringbuffer"); |
| 768 | | return false; |
| | 779 | return _first_keyframe >= 0; |
| 769 | 780 | } |
| 770 | 781 | |
| 771 | | bool haveBufferedData = !_payload_buffer.empty(); |
| 772 | | if (!tspacket->HasPayload()) // no payload to scan |
| 773 | | return !haveBufferedData; |
| 774 | | |
| 775 | 782 | const bool payloadStart = tspacket->PayloadStart(); |
| 776 | 783 | if (payloadStart) |
| 777 | 784 | { |
| … |
… |
bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
|
| 790 | 797 | |
| 791 | 798 | // scan for PES packets and H.264 NAL units |
| 792 | 799 | uint i = tspacket->AFCOffset(); |
| 793 | | for (; i < TSPacket::kSize; i++) |
| | 800 | for (; i < TSPacket::kSize; ++i) |
| 794 | 801 | { |
| 795 | 802 | // special handling required when a new PES packet begins |
| 796 | 803 | if (payloadStart && !_pes_synced) |
| … |
… |
bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
|
| 858 | 865 | |
| 859 | 866 | // scan for a NAL unit start code |
| 860 | 867 | |
| 861 | | uint32_t bytes_used = m_h264_parser.addBytes( |
| 862 | | tspacket->data() + i, TSPacket::kSize - i, |
| 863 | | ringBuffer->GetWritePosition() + _payload_buffer.size() |
| 864 | | ); |
| | 868 | uint32_t bytes_used = m_h264_parser.addBytes |
| | 869 | (tspacket->data() + i, TSPacket::kSize - i, |
| | 870 | ringBuffer->GetWritePosition()); |
| 865 | 871 | i += (bytes_used - 1); |
| 866 | 872 | |
| 867 | 873 | if (m_h264_parser.stateChanged()) |
| … |
… |
bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
|
| 879 | 885 | frameRate = m_h264_parser.frameRate(); |
| 880 | 886 | } |
| 881 | 887 | } |
| 882 | | } // for (; i < TSPacket::kSize; i++) |
| | 888 | } // for (; i < TSPacket::kSize; ++i) |
| 883 | 889 | |
| 884 | 890 | if (hasKeyFrame) |
| 885 | 891 | { |
| | 892 | #if 0 |
| | 893 | LOG(VB_RECORD, LOG_ERR, LOC + QString |
| | 894 | ("Keyframe @ %1 + %2 = %3 AU %4") |
| | 895 | .arg(ringBuffer->GetWritePosition()) |
| | 896 | .arg(_payload_buffer.size()) |
| | 897 | .arg(ringBuffer->GetWritePosition() + _payload_buffer.size()) |
| | 898 | .arg(m_h264_parser.keyframeAUstreamOffset())); |
| | 899 | #endif |
| 886 | 900 | _last_keyframe_seen = _frames_seen_count; |
| 887 | 901 | HandleH264Keyframe(); |
| 888 | 902 | } |
| 889 | 903 | |
| 890 | 904 | if (hasFrame) |
| 891 | 905 | { |
| | 906 | #if 0 |
| | 907 | LOG(VB_RECORD, LOG_ERR, LOC + QString |
| | 908 | ("Frame @ %1 + %2 = %3 AU %4") |
| | 909 | .arg(ringBuffer->GetWritePosition()) |
| | 910 | .arg(_payload_buffer.size()) |
| | 911 | .arg(ringBuffer->GetWritePosition() + _payload_buffer.size()) |
| | 912 | .arg(m_h264_parser.keyframeAUstreamOffset())); |
| | 913 | #endif |
| | 914 | _buffer_packets = false; // We now know if this is a keyframe |
| 892 | 915 | _frames_seen_count++; |
| 893 | 916 | if (!_wait_for_keyframe_option || _first_keyframe >= 0) |
| 894 | 917 | UpdateFramesWritten(); |
| | 918 | else |
| | 919 | { |
| | 920 | /* Found a frame that is not a keyframe, and we want to |
| | 921 | * start on a keyframe */ |
| | 922 | _payload_buffer.clear(); |
| | 923 | } |
| 895 | 924 | } |
| 896 | 925 | |
| 897 | 926 | if ((aspectRatio > 0) && (aspectRatio != m_videoAspect)) |
| … |
… |
bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
|
| 909 | 938 | |
| 910 | 939 | if (frameRate != 0 && frameRate != m_frameRate) |
| 911 | 940 | { |
| 912 | | |
| 913 | 941 | LOG(VB_RECORD, LOG_INFO, LOC + |
| 914 | 942 | QString("FindH264Keyframes: timescale: %1, tick: %2, framerate: %3") |
| 915 | 943 | .arg( m_h264_parser.GetTimeScale() ) |
| … |
… |
bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
|
| 919 | 947 | FrameRateChange(frameRate, _frames_written_count); |
| 920 | 948 | } |
| 921 | 949 | |
| 922 | | return hasKeyFrame || (_payload_buffer.size() >= (188*50)); |
| | 950 | return _seen_sps; |
| 923 | 951 | } |
| 924 | 952 | |
| 925 | 953 | /** \fn DTVRecorder::HandleH264Keyframe(void) |
| … |
… |
bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
|
| 928 | 956 | */ |
| 929 | 957 | void DTVRecorder::HandleH264Keyframe(void) |
| 930 | 958 | { |
| 931 | | unsigned long long frameNum = _frames_written_count; |
| | 959 | // Perform ringbuffer switch if needed. |
| | 960 | CheckForRingBufferSwitch(); |
| 932 | 961 | |
| 933 | | _first_keyframe = (_first_keyframe < 0) ? frameNum : _first_keyframe; |
| | 962 | uint64_t startpos; |
| | 963 | uint64_t frameNum = _frames_written_count; |
| | 964 | |
| | 965 | if (_first_keyframe < 0) |
| | 966 | { |
| | 967 | _first_keyframe = frameNum; |
| | 968 | startpos = 0; |
| | 969 | } |
| | 970 | else |
| | 971 | startpos = m_h264_parser.keyframeAUstreamOffset(); |
| 934 | 972 | |
| 935 | 973 | // Add key frame to position map |
| 936 | 974 | positionMapLock.lock(); |
| 937 | 975 | if (!positionMap.contains(frameNum)) |
| 938 | 976 | { |
| 939 | | positionMapDelta[frameNum] = m_h264_parser.keyframeAUstreamOffset(); |
| 940 | | positionMap[frameNum] = m_h264_parser.keyframeAUstreamOffset(); |
| | 977 | positionMapDelta[frameNum] = startpos; |
| | 978 | positionMap[frameNum] = startpos; |
| 941 | 979 | durationMap[frameNum] = _total_duration / 1000; |
| 942 | 980 | durationMapDelta[frameNum] = _total_duration / 1000; |
| 943 | 981 | } |
| 944 | 982 | positionMapLock.unlock(); |
| 945 | | |
| 946 | | // Perform ringbuffer switch if needed. |
| 947 | | CheckForRingBufferSwitch(); |
| 948 | 983 | } |
| 949 | 984 | |
| 950 | 985 | void DTVRecorder::FindPSKeyFrames(const uint8_t *buffer, uint len) |
| … |
… |
void DTVRecorder::FindPSKeyFrames(const uint8_t *buffer, uint len)
|
| 1065 | 1100 | if (hasKeyFrame) |
| 1066 | 1101 | { |
| 1067 | 1102 | _last_keyframe_seen = _frames_seen_count; |
| 1068 | | HandleKeyframe(_frames_written_count, bufptr - bufstart); |
| | 1103 | HandleKeyframe(_payload_buffer.size() - (bufptr - bufstart)); |
| 1069 | 1104 | } |
| 1070 | 1105 | |
| 1071 | 1106 | if ((aspectRatio > 0) && (aspectRatio != m_videoAspect)) |
| … |
… |
void DTVRecorder::HandlePAT(const ProgramAssociationTable *_pat)
|
| 1149 | 1184 | |
| 1150 | 1185 | if (!pmtpid) |
| 1151 | 1186 | { |
| 1152 | | LOG(VB_RECORD, LOG_ERR, LOC + "SetPAT(): " |
| 1153 | | "Ignoring PAT not containing our desired program..."); |
| | 1187 | LOG(VB_RECORD, LOG_ERR, LOC + |
| | 1188 | QString("SetPAT(): Ignoring PAT not containing our desired " |
| | 1189 | "program (%1)...").arg(progNum)); |
| 1154 | 1190 | return; |
| 1155 | 1191 | } |
| 1156 | 1192 | |
| … |
… |
void DTVRecorder::HandlePAT(const ProgramAssociationTable *_pat)
|
| 1162 | 1198 | delete oldpat; |
| 1163 | 1199 | |
| 1164 | 1200 | // Listen for the other PMTs for faster channel switching |
| 1165 | | for (uint i = 0; _input_pat && (i < _input_pat->ProgramCount()); i++) |
| | 1201 | for (uint i = 0; _input_pat && (i < _input_pat->ProgramCount()); ++i) |
| 1166 | 1202 | { |
| 1167 | 1203 | uint pmt_pid = _input_pat->ProgramPID(i); |
| 1168 | 1204 | if (!_stream_data->IsListeningPID(pmt_pid)) |
| … |
… |
void DTVRecorder::HandlePMT(uint progNum, const ProgramMapTable *_pmt)
|
| 1183 | 1219 | QString sistandard = GetSIStandard(); |
| 1184 | 1220 | |
| 1185 | 1221 | bool has_no_av = true; |
| 1186 | | for (uint i = 0; i < _input_pmt->StreamCount() && has_no_av; i++) |
| | 1222 | for (uint i = 0; i < _input_pmt->StreamCount() && has_no_av; ++i) |
| 1187 | 1223 | { |
| 1188 | 1224 | has_no_av &= !_input_pmt->IsVideo(i, sistandard); |
| 1189 | 1225 | has_no_av &= !_input_pmt->IsAudio(i, sistandard); |
| … |
… |
void DTVRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat)
|
| 1210 | 1246 | pat->tsheader()->SetContinuityCounter(next_cc); |
| 1211 | 1247 | pat->GetAsTSPackets(_scratch, next_cc); |
| 1212 | 1248 | |
| 1213 | | for (uint i = 0; i < _scratch.size(); i++) |
| | 1249 | for (uint i = 0; i < _scratch.size(); ++i) |
| 1214 | 1250 | DTVRecorder::BufferedWrite(_scratch[i]); |
| 1215 | 1251 | } |
| 1216 | 1252 | |
| … |
… |
void DTVRecorder::HandleSingleProgramPMT(ProgramMapTable *pmt)
|
| 1223 | 1259 | } |
| 1224 | 1260 | |
| 1225 | 1261 | // collect stream types for H.264 (MPEG-4 AVC) keyframe detection |
| 1226 | | for (uint i = 0; i < pmt->StreamCount(); i++) |
| | 1262 | for (uint i = 0; i < pmt->StreamCount(); ++i) |
| 1227 | 1263 | _stream_id[pmt->StreamPID(i)] = pmt->StreamType(i); |
| 1228 | 1264 | |
| 1229 | 1265 | if (!ringBuffer) |
| … |
… |
void DTVRecorder::HandleSingleProgramPMT(ProgramMapTable *pmt)
|
| 1233 | 1269 | pmt->tsheader()->SetContinuityCounter(next_cc); |
| 1234 | 1270 | pmt->GetAsTSPackets(_scratch, next_cc); |
| 1235 | 1271 | |
| 1236 | | for (uint i = 0; i < _scratch.size(); i++) |
| | 1272 | for (uint i = 0; i < _scratch.size(); ++i) |
| 1237 | 1273 | DTVRecorder::BufferedWrite(_scratch[i]); |
| 1238 | 1274 | } |
| 1239 | 1275 | |
| … |
… |
bool DTVRecorder::ProcessTSPacket(const TSPacket &tspacket)
|
| 1260 | 1296 | // Only create fake keyframe[s] if there are no audio/video streams |
| 1261 | 1297 | if (_input_pmt && _has_no_av) |
| 1262 | 1298 | { |
| 1263 | | _buffer_packets = !FindOtherKeyframes(&tspacket); |
| | 1299 | FindOtherKeyframes(&tspacket); |
| | 1300 | _buffer_packets = false; |
| 1264 | 1301 | } |
| 1265 | 1302 | else |
| 1266 | 1303 | { |
| … |
… |
bool DTVRecorder::ProcessVideoTSPacket(const TSPacket &tspacket)
|
| 1284 | 1321 | |
| 1285 | 1322 | uint streamType = _stream_id[tspacket.PID()]; |
| 1286 | 1323 | |
| 1287 | | // Check for keyframes and count frames |
| 1288 | | if (streamType == StreamID::H264Video) |
| | 1324 | if (tspacket.HasPayload() && tspacket.PayloadStart()) |
| 1289 | 1325 | { |
| 1290 | | _buffer_packets = !FindH264Keyframes(&tspacket); |
| 1291 | | if (_wait_for_keyframe_option && !_seen_sps) |
| 1292 | | return true; |
| | 1326 | // buffer packets until we know if this is a keyframe |
| | 1327 | _buffer_packets = true; |
| | 1328 | #if 0 |
| | 1329 | LOG(VB_RECORD, LOG_ERR, LOC + QString |
| | 1330 | ("ProcessVideoTSPacket PayloadStart @ %1 + %2 = %3") |
| | 1331 | .arg(ringBuffer->GetWritePosition()) |
| | 1332 | .arg(_payload_buffer.size()) |
| | 1333 | .arg(ringBuffer->GetWritePosition() + _payload_buffer.size())); |
| | 1334 | #endif |
| 1293 | 1335 | } |
| | 1336 | |
| | 1337 | // Check for keyframes and count frames |
| | 1338 | if (streamType == StreamID::H264Video) |
| | 1339 | FindH264Keyframes(&tspacket); |
| | 1340 | else if (streamType != 0) |
| | 1341 | FindMPEG2Keyframes(&tspacket); |
| 1294 | 1342 | else |
| 1295 | | { |
| 1296 | | _buffer_packets = !FindMPEG2Keyframes(&tspacket); |
| 1297 | | } |
| | 1343 | LOG(VB_RECORD, LOG_ERR, LOC + |
| | 1344 | "ProcessVideoTSPacket: unknown stream type!"); |
| 1298 | 1345 | |
| 1299 | 1346 | return ProcessAVTSPacket(tspacket); |
| 1300 | 1347 | } |
| … |
… |
bool DTVRecorder::ProcessAudioTSPacket(const TSPacket &tspacket)
|
| 1304 | 1351 | if (!ringBuffer) |
| 1305 | 1352 | return true; |
| 1306 | 1353 | |
| 1307 | | _buffer_packets = !FindAudioKeyframes(&tspacket); |
| | 1354 | if (tspacket.HasPayload() && tspacket.PayloadStart()) |
| | 1355 | { |
| | 1356 | // buffer packets until we know if this is a keyframe |
| | 1357 | _buffer_packets = true; |
| | 1358 | #if 0 |
| | 1359 | LOG(VB_RECORD, LOG_ERR, LOC + QString |
| | 1360 | ("ProcessAudioTSPacket PayloadStart @ %1 + %2 = %3") |
| | 1361 | .arg(ringBuffer->GetWritePosition()) |
| | 1362 | .arg(_payload_buffer.size()) |
| | 1363 | .arg(ringBuffer->GetWritePosition() + _payload_buffer.size())); |
| | 1364 | #endif |
| | 1365 | } |
| | 1366 | |
| | 1367 | FindAudioKeyframes(&tspacket); |
| 1308 | 1368 | return ProcessAVTSPacket(tspacket); |
| 1309 | 1369 | } |
| 1310 | 1370 | |
| 1311 | 1371 | /// Common code for processing either audio or video packets |
| 1312 | 1372 | bool DTVRecorder::ProcessAVTSPacket(const TSPacket &tspacket) |
| 1313 | 1373 | { |
| | 1374 | // Sync recording start to first keyframe |
| | 1375 | if (!_buffer_packets && _wait_for_keyframe_option && _first_keyframe < 0) |
| | 1376 | return true; |
| | 1377 | |
| 1314 | 1378 | const uint pid = tspacket.PID(); |
| 1315 | 1379 | |
| 1316 | 1380 | if (pid != 0x1fff) |
| … |
… |
bool DTVRecorder::ProcessAVTSPacket(const TSPacket &tspacket)
|
| 1328 | 1392 | .arg(erate,5,'f',2)); |
| 1329 | 1393 | } |
| 1330 | 1394 | |
| 1331 | | // Sync recording start to first keyframe |
| 1332 | | if (_wait_for_keyframe_option && _first_keyframe < 0) |
| 1333 | | return true; |
| 1334 | | |
| 1335 | 1395 | // Sync streams to the first Payload Unit Start Indicator |
| 1336 | 1396 | // _after_ first keyframe iff _wait_for_keyframe_option is true |
| 1337 | 1397 | if (!(_pid_status[pid] & kPayloadStartSeen) && tspacket.HasPayload()) |
diff --git a/mythtv/libs/libmythtv/recorders/dtvrecorder.h b/mythtv/libs/libmythtv/recorders/dtvrecorder.h
index 6617366..b12d0ce 100644
|
a
|
b
|
class DTVRecorder :
|
| 93 | 93 | void FinishRecording(void); |
| 94 | 94 | void ResetForNewFile(void); |
| 95 | 95 | |
| 96 | | void HandleKeyframe(uint64_t frameNum, int64_t extra = 0); |
| | 96 | void HandleKeyframe(int64_t extra); |
| 97 | 97 | void HandleTimestamps(int stream_id, int64_t pts, int64_t dts); |
| 98 | 98 | void UpdateFramesWritten(void); |
| 99 | 99 | |