diff --git a/mythtv/libs/libmythtv/mpeg/mpegstreamdata.cpp b/mythtv/libs/libmythtv/mpeg/mpegstreamdata.cpp
index 489c547..fc50feb 100644
|
a
|
b
|
const unsigned char MPEGStreamData::bit_sel[8] =
|
| 65 | 65 | MPEGStreamData::MPEGStreamData(int desiredProgram, bool cacheTables) |
| 66 | 66 | : _sistandard("mpeg"), |
| 67 | 67 | _have_CRC_bug(false), |
| | 68 | _found_payload_start(false), |
| 68 | 69 | _si_time_offset_cnt(0), |
| 69 | 70 | _si_time_offset_indx(0), |
| 70 | 71 | _eit_helper(NULL), _eit_rate(0.0f), |
| … |
… |
bool MPEGStreamData::ProcessTSPacket(const TSPacket& tspacket)
|
| 1054 | 1055 | if (tspacket.Scrambled()) |
| 1055 | 1056 | return true; |
| 1056 | 1057 | |
| | 1058 | _found_payload_start |= (tspacket.HasPayload() && tspacket.PayloadStart()); |
| | 1059 | |
| 1057 | 1060 | if (IsVideoPID(tspacket.PID())) |
| 1058 | 1061 | { |
| 1059 | 1062 | for (uint j = 0; j < _ts_av_listeners.size(); j++) |
diff --git a/mythtv/libs/libmythtv/mpeg/mpegstreamdata.h b/mythtv/libs/libmythtv/mpeg/mpegstreamdata.h
index 94ad37d..3730426 100644
|
a
|
b
|
class MTV_PUBLIC MPEGStreamData : public EITSource
|
| 307 | 307 | // Single program stuff, gets |
| 308 | 308 | int DesiredProgram(void) const { return _desired_program; } |
| 309 | 309 | uint VideoPIDSingleProgram(void) const { return _pid_video_single_program; } |
| | 310 | bool FoundPayloadStart(void) const { return _found_payload_start; } |
| | 311 | void ResetPayloadStart(void) { _found_payload_start = false; } |
| | 312 | |
| 310 | 313 | QString GetRecordingType(void) const; |
| 311 | 314 | |
| 312 | 315 | const ProgramAssociationTable* PATSingleProgram(void) const |
| … |
… |
class MTV_PUBLIC MPEGStreamData : public EITSource
|
| 356 | 359 | QString _sistandard; |
| 357 | 360 | |
| 358 | 361 | bool _have_CRC_bug; |
| | 362 | bool _found_payload_start; |
| 359 | 363 | |
| 360 | 364 | mutable QMutex _si_time_lock; |
| 361 | 365 | uint _si_time_offset_cnt; |
diff --git a/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp b/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp
index 0c30b10..0dcebaf 100644
|
a
|
b
|
void DTVRecorder::InitStreamData(void)
|
| 277 | 277 | void DTVRecorder::BufferedWrite(const TSPacket &tspacket) |
| 278 | 278 | { |
| 279 | 279 | // delay until first GOP to avoid decoder crash on res change |
| 280 | | if (_wait_for_keyframe_option && _first_keyframe<0) |
| | 280 | if (!_buffer_packets && _wait_for_keyframe_option && _first_keyframe<0) |
| 281 | 281 | return; |
| 282 | 282 | |
| 283 | 283 | if (curRecording && timeOfFirstDataIsSet.testAndSetRelaxed(0,1)) |
| … |
… |
static const uint frameRateMap[16] = {
|
| 403 | 403 | */ |
| 404 | 404 | bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket) |
| 405 | 405 | { |
| 406 | | bool haveBufferedData = !_payload_buffer.empty(); |
| 407 | 406 | if (!tspacket->HasPayload()) // no payload to scan |
| 408 | | return !haveBufferedData; |
| | 407 | return _first_keyframe >= 0; |
| 409 | 408 | |
| 410 | 409 | if (!ringBuffer) |
| 411 | | return !haveBufferedData; |
| | 410 | return _first_keyframe >= 0; |
| 412 | 411 | |
| 413 | 412 | // if packet contains start of PES packet, start |
| 414 | 413 | // looking for first byte of MPEG start code (3 bytes 0 0 1) |
| … |
… |
bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket)
|
| 549 | 548 | _frames_seen_count++; |
| 550 | 549 | if (!_wait_for_keyframe_option || _first_keyframe>=0) |
| 551 | 550 | UpdateFramesWritten(); |
| | 551 | else |
| | 552 | { |
| | 553 | /* Found a frame that is not a keyframe, and we want to |
| | 554 | * start on a keyframe */ |
| | 555 | _payload_buffer.clear(); |
| | 556 | _stream_data->ResetPayloadStart(); |
| | 557 | } |
| 552 | 558 | } |
| 553 | 559 | |
| 554 | 560 | if ((aspectRatio > 0) && (aspectRatio != m_videoAspect)) |
| … |
… |
bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket)
|
| 572 | 578 | FrameRateChange(frameRate, _frames_written_count); |
| 573 | 579 | } |
| 574 | 580 | |
| 575 | | return hasKeyFrame || (_payload_buffer.size() >= (188*50)); |
| | 581 | return _first_keyframe >= 0; |
| 576 | 582 | } |
| 577 | 583 | |
| 578 | 584 | void DTVRecorder::HandleTimestamps(int stream_id, int64_t pts, int64_t dts) |
| … |
… |
void DTVRecorder::HandleKeyframe(uint64_t frameNum, int64_t extra)
|
| 762 | 768 | */ |
| 763 | 769 | bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket) |
| 764 | 770 | { |
| | 771 | if (!tspacket->HasPayload()) // no payload to scan |
| | 772 | return _first_keyframe >= 0; |
| | 773 | |
| 765 | 774 | if (!ringBuffer) |
| 766 | 775 | { |
| 767 | 776 | LOG(VB_GENERAL, LOG_ERR, LOC + "FindH264Keyframes: No ringbuffer"); |
| 768 | | return false; |
| | 777 | return _first_keyframe >= 0; |
| 769 | 778 | } |
| 770 | 779 | |
| 771 | | bool haveBufferedData = !_payload_buffer.empty(); |
| 772 | | if (!tspacket->HasPayload()) // no payload to scan |
| 773 | | return !haveBufferedData; |
| 774 | | |
| 775 | 780 | const bool payloadStart = tspacket->PayloadStart(); |
| 776 | 781 | if (payloadStart) |
| 777 | 782 | { |
| … |
… |
bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
|
| 790 | 795 | |
| 791 | 796 | // scan for PES packets and H.264 NAL units |
| 792 | 797 | uint i = tspacket->AFCOffset(); |
| 793 | | for (; i < TSPacket::kSize; i++) |
| | 798 | for (; i < TSPacket::kSize; ++i) |
| 794 | 799 | { |
| 795 | 800 | // special handling required when a new PES packet begins |
| 796 | 801 | if (payloadStart && !_pes_synced) |
| … |
… |
bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
|
| 879 | 884 | frameRate = m_h264_parser.frameRate(); |
| 880 | 885 | } |
| 881 | 886 | } |
| 882 | | } // for (; i < TSPacket::kSize; i++) |
| | 887 | } // for (; i < TSPacket::kSize; ++i) |
| 883 | 888 | |
| 884 | 889 | if (hasKeyFrame) |
| 885 | 890 | { |
| … |
… |
bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
|
| 892 | 897 | _frames_seen_count++; |
| 893 | 898 | if (!_wait_for_keyframe_option || _first_keyframe >= 0) |
| 894 | 899 | UpdateFramesWritten(); |
| | 900 | else |
| | 901 | { |
| | 902 | /* Found a frame that is not a keyframe, and we want to |
| | 903 | * start on a keyframe */ |
| | 904 | _payload_buffer.clear(); |
| | 905 | _stream_data->ResetPayloadStart(); |
| | 906 | } |
| 895 | 907 | } |
| 896 | 908 | |
| 897 | 909 | if ((aspectRatio > 0) && (aspectRatio != m_videoAspect)) |
| … |
… |
bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
|
| 909 | 921 | |
| 910 | 922 | if (frameRate != 0 && frameRate != m_frameRate) |
| 911 | 923 | { |
| 912 | | |
| 913 | 924 | LOG(VB_RECORD, LOG_INFO, LOC + |
| 914 | 925 | QString("FindH264Keyframes: timescale: %1, tick: %2, framerate: %3") |
| 915 | 926 | .arg( m_h264_parser.GetTimeScale() ) |
| … |
… |
bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
|
| 919 | 930 | FrameRateChange(frameRate, _frames_written_count); |
| 920 | 931 | } |
| 921 | 932 | |
| 922 | | return hasKeyFrame || (_payload_buffer.size() >= (188*50)); |
| | 933 | return _seen_sps; |
| 923 | 934 | } |
| 924 | 935 | |
| 925 | 936 | /** \fn DTVRecorder::HandleH264Keyframe(void) |
| … |
… |
void DTVRecorder::HandlePAT(const ProgramAssociationTable *_pat)
|
| 1149 | 1160 | |
| 1150 | 1161 | if (!pmtpid) |
| 1151 | 1162 | { |
| 1152 | | LOG(VB_RECORD, LOG_ERR, LOC + "SetPAT(): " |
| 1153 | | "Ignoring PAT not containing our desired program..."); |
| | 1163 | LOG(VB_RECORD, LOG_ERR, LOC + |
| | 1164 | QString("SetPAT(): Ignoring PAT not containing our desired " |
| | 1165 | "program (%1)...").arg(progNum)); |
| 1154 | 1166 | return; |
| 1155 | 1167 | } |
| 1156 | 1168 | |
| … |
… |
bool DTVRecorder::ProcessVideoTSPacket(const TSPacket &tspacket)
|
| 1287 | 1299 | // Check for keyframes and count frames |
| 1288 | 1300 | if (streamType == StreamID::H264Video) |
| 1289 | 1301 | { |
| 1290 | | _buffer_packets = !FindH264Keyframes(&tspacket); |
| 1291 | | if (_wait_for_keyframe_option && !_seen_sps) |
| 1292 | | return true; |
| | 1302 | _buffer_packets = !FindH264Keyframes(&tspacket) && |
| | 1303 | _stream_data->FoundPayloadStart(); |
| 1293 | 1304 | } |
| 1294 | 1305 | else |
| 1295 | 1306 | { |
| 1296 | | _buffer_packets = !FindMPEG2Keyframes(&tspacket); |
| | 1307 | _buffer_packets = !FindMPEG2Keyframes(&tspacket) && |
| | 1308 | _stream_data->FoundPayloadStart(); |
| 1297 | 1309 | } |
| 1298 | 1310 | |
| 1299 | 1311 | return ProcessAVTSPacket(tspacket); |
| … |
… |
bool DTVRecorder::ProcessAudioTSPacket(const TSPacket &tspacket)
|
| 1311 | 1323 | /// Common code for processing either audio or video packets |
| 1312 | 1324 | bool DTVRecorder::ProcessAVTSPacket(const TSPacket &tspacket) |
| 1313 | 1325 | { |
| | 1326 | // Sync recording start to first keyframe |
| | 1327 | if (!_buffer_packets && _wait_for_keyframe_option && _first_keyframe < 0) |
| | 1328 | return true; |
| | 1329 | |
| 1314 | 1330 | const uint pid = tspacket.PID(); |
| 1315 | 1331 | |
| 1316 | 1332 | if (pid != 0x1fff) |
| … |
… |
bool DTVRecorder::ProcessAVTSPacket(const TSPacket &tspacket)
|
| 1328 | 1344 | .arg(erate,5,'f',2)); |
| 1329 | 1345 | } |
| 1330 | 1346 | |
| 1331 | | // Sync recording start to first keyframe |
| 1332 | | if (_wait_for_keyframe_option && _first_keyframe < 0) |
| 1333 | | return true; |
| 1334 | | |
| 1335 | 1347 | // Sync streams to the first Payload Unit Start Indicator |
| 1336 | 1348 | // _after_ first keyframe iff _wait_for_keyframe_option is true |
| 1337 | 1349 | if (!(_pid_status[pid] & kPayloadStartSeen) && tspacket.HasPayload()) |