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()) |