| 1 | --- /home/mythtv/work2/mythtv-0.19/libs/libmythtv/dtvrecorder.cpp 2006-02-07 13:56:06.000000000 -0800
|
|---|
| 2 | +++ libs/libmythtv/dtvrecorder.cpp 2006-02-22 03:29:01.000000000 -0800
|
|---|
| 3 | @@ -37,7 +37,9 @@
|
|---|
| 4 | _stream_fd(-1),
|
|---|
| 5 | // used for scanning pes headers for keyframes
|
|---|
| 6 | _header_pos(0), _first_keyframe(-1),
|
|---|
| 7 | + _position_within_gop_header(0),
|
|---|
| 8 | _last_gop_seen(0), _last_seq_seen(0),
|
|---|
| 9 | + _keyframe_seen(false),
|
|---|
| 10 | _last_keyframe_seen(0),
|
|---|
| 11 | // settings
|
|---|
| 12 | _request_recording(false),
|
|---|
| 13 | @@ -126,6 +128,8 @@
|
|---|
| 14 |
|
|---|
| 15 | _header_pos = 0;
|
|---|
| 16 | _first_keyframe =-1;
|
|---|
| 17 | + _position_within_gop_header = 0;
|
|---|
| 18 | + _keyframe_seen = false;
|
|---|
| 19 | _last_keyframe_seen = 0;
|
|---|
| 20 | _last_gop_seen = 0;
|
|---|
| 21 | _last_seq_seen = 0;
|
|---|
| 22 | @@ -195,6 +199,101 @@
|
|---|
| 23 | */
|
|---|
| 24 | bool DTVRecorder::FindKeyframes(const TSPacket* tspacket)
|
|---|
| 25 | {
|
|---|
| 26 | +#define AVG_KEYFRAME_DIFF 16
|
|---|
| 27 | +#define MAX_KEYFRAME_DIFF 32
|
|---|
| 28 | +#define DEBUG_FIND_KEY_FRAMES 0 /* set to 1 to debug */
|
|---|
| 29 | + bool haveBufferedData = !_payload_buffer.empty();
|
|---|
| 30 | + bool hasKeyFrame = false;
|
|---|
| 31 | + bool noPayload = !tspacket->HasPayload();
|
|---|
| 32 | + bool payloadStart = tspacket->PayloadStart();
|
|---|
| 33 | +
|
|---|
| 34 | + if (noPayload)
|
|---|
| 35 | + return !haveBufferedData; // no payload to scan
|
|---|
| 36 | +
|
|---|
| 37 | + if (payloadStart)
|
|---|
| 38 | + { // packet contains start of PES packet
|
|---|
| 39 | + _position_within_gop_header = 0; // start looking for first byte of pattern
|
|---|
| 40 | + }
|
|---|
| 41 | +
|
|---|
| 42 | + // Scan for PES header codes; specifically picture_start
|
|---|
| 43 | + // and group_start (of_pictures). These should be within
|
|---|
| 44 | + // this first TS packet of the PES packet.
|
|---|
| 45 | + // 00 00 01 00: picture_start_code
|
|---|
| 46 | + // 00 00 01 B8: group_start_code
|
|---|
| 47 | + // 00 00 01 B3: seq_start_code
|
|---|
| 48 | + // (there are others that we don't care about)
|
|---|
| 49 | + long long frameSeenNum = _frames_seen_count;
|
|---|
| 50 | + const unsigned char *buffer = tspacket->data();
|
|---|
| 51 | + for (unsigned int i = tspacket->AFCOffset(); i+1<TSPacket::SIZE; i++)
|
|---|
| 52 | + {
|
|---|
| 53 | + const unsigned char k = buffer[i];
|
|---|
| 54 | + if (0 == _position_within_gop_header)
|
|---|
| 55 | + _position_within_gop_header = (k == 0x00) ? 1 : 0;
|
|---|
| 56 | + else if (1 == _position_within_gop_header)
|
|---|
| 57 | + _position_within_gop_header = (k == 0x00) ? 2 : 0;
|
|---|
| 58 | + else
|
|---|
| 59 | + {
|
|---|
| 60 | + if (0x01 != k)
|
|---|
| 61 | + {
|
|---|
| 62 | + _position_within_gop_header = (k == 0x00) ? 2 : 0;
|
|---|
| 63 | + continue;
|
|---|
| 64 | + }
|
|---|
| 65 | + const unsigned char k1 = buffer[i+1];
|
|---|
| 66 | + if (0x00 == k1)
|
|---|
| 67 | + { // 00 00 01 00: picture_start_code
|
|---|
| 68 | + _frames_written_count += (_first_keyframe > 0) ? 1 : 0;
|
|---|
| 69 | + _frames_seen_count++;
|
|---|
| 70 | + // We've seen 30 frames and no GOP or seq header? let's pretend we have them
|
|---|
| 71 | + if ((0==(_frames_seen_count & 0xf)) &&
|
|---|
| 72 | + (_last_gop_seen+(MAX_KEYFRAME_DIFF+AVG_KEYFRAME_DIFF))<frameSeenNum &&
|
|---|
| 73 | + (_last_seq_seen+(MAX_KEYFRAME_DIFF+AVG_KEYFRAME_DIFF))<frameSeenNum) {
|
|---|
| 74 | +#if DEBUG_FIND_KEY_FRAMES
|
|---|
| 75 | + VERBOSE(VB_RECORD, QString("f16 sc(%1) wc(%2) lgop(%3) lseq(%4)").
|
|---|
| 76 | + arg(_frames_seen_count).arg(_frames_written_count).
|
|---|
| 77 | + arg(_last_gop_seen).arg(_last_seq_seen));
|
|---|
| 78 | +#endif
|
|---|
| 79 | + HandleKeyframe();
|
|---|
| 80 | + hasKeyFrame = true;
|
|---|
| 81 | + _last_keyframe_seen = frameSeenNum;
|
|---|
| 82 | + }
|
|---|
| 83 | + } else if (0xB8 == k1)
|
|---|
| 84 | + { // 00 00 01 B8: group_start_code
|
|---|
| 85 | +#if DEBUG_FIND_KEY_FRAMES
|
|---|
| 86 | + VERBOSE(VB_RECORD, QString("GOP sc(%1) wc(%2) lgop(%3) lseq(%4)").
|
|---|
| 87 | + arg(_frames_seen_count).arg(_frames_written_count).
|
|---|
| 88 | + arg(_last_gop_seen).arg(_last_seq_seen));
|
|---|
| 89 | +#endif
|
|---|
| 90 | + HandleKeyframe();
|
|---|
| 91 | + hasKeyFrame = true;
|
|---|
| 92 | + _last_keyframe_seen = _last_gop_seen = frameSeenNum;
|
|---|
| 93 | + } else if (0xB3 == k1)
|
|---|
| 94 | + { // 00 00 01 B3: seq_start_code
|
|---|
| 95 | + if ((_last_gop_seen+MAX_KEYFRAME_DIFF)<frameSeenNum)
|
|---|
| 96 | + {
|
|---|
| 97 | +#if DEBUG_FIND_KEY_FRAMES
|
|---|
| 98 | + VERBOSE(VB_RECORD, QString("seq sc(%1) wc(%2) lgop(%3) lseq(%4)").
|
|---|
| 99 | + arg(_frames_seen_count).arg(_frames_written_count).
|
|---|
| 100 | + arg(_last_gop_seen).arg(_last_seq_seen));
|
|---|
| 101 | +#endif
|
|---|
| 102 | + HandleKeyframe();
|
|---|
| 103 | + hasKeyFrame = true;
|
|---|
| 104 | + _last_keyframe_seen = frameSeenNum;
|
|---|
| 105 | + }
|
|---|
| 106 | + _last_seq_seen = frameSeenNum;
|
|---|
| 107 | + }
|
|---|
| 108 | + _position_within_gop_header = 0;
|
|---|
| 109 | + }
|
|---|
| 110 | + }
|
|---|
| 111 | +#undef AVG_KEYFRAME_DIFF
|
|---|
| 112 | +#undef MAX_KEYFRAME_DIFF
|
|---|
| 113 | +#undef DEBUG_FIND_KEY_FRAMES
|
|---|
| 114 | +
|
|---|
| 115 | + return hasKeyFrame || (_payload_buffer.size() >= (188*50));
|
|---|
| 116 | +}
|
|---|
| 117 | +
|
|---|
| 118 | +/*
|
|---|
| 119 | +bool DTVRecorder::FindKeyframes(const TSPacket* tspacket)
|
|---|
| 120 | +{
|
|---|
| 121 | bool haveBufferedData = !_payload_buffer.empty();
|
|---|
| 122 | if (!tspacket->HasPayload()) // no payload to scan
|
|---|
| 123 | return !haveBufferedData;
|
|---|
| 124 | @@ -273,6 +372,7 @@
|
|---|
| 125 |
|
|---|
| 126 | return hasKeyFrame || (_payload_buffer.size() >= (188*50));
|
|---|
| 127 | }
|
|---|
| 128 | +*/
|
|---|
| 129 |
|
|---|
| 130 | // documented in recorderbase.h
|
|---|
| 131 | void DTVRecorder::SetNextRecording(const ProgramInfo *progInf, RingBuffer *rb)
|
|---|
| 132 | @@ -304,6 +404,7 @@
|
|---|
| 133 | * \brief This save the current frame to the position maps
|
|---|
| 134 | * and handles ringbuffer switching.
|
|---|
| 135 | */
|
|---|
| 136 | +/*
|
|---|
| 137 | void DTVRecorder::HandleKeyframe(void)
|
|---|
| 138 | {
|
|---|
| 139 | unsigned long long frameNum = _frames_written_count;
|
|---|
| 140 | @@ -328,6 +429,7 @@
|
|---|
| 141 | // Perform ringbuffer switch if needed.
|
|---|
| 142 | CheckForRingBufferSwitch();
|
|---|
| 143 | }
|
|---|
| 144 | +*/
|
|---|
| 145 |
|
|---|
| 146 | /** \fn DTVRecorder::SavePositionMap(bool)
|
|---|
| 147 | * \brief This saves the postition map delta to the database if force
|
|---|
| 148 | @@ -355,3 +457,34 @@
|
|---|
| 149 | curRecording->SetFilesize(ringBuffer->GetWritePosition());
|
|---|
| 150 | }
|
|---|
| 151 | }
|
|---|
| 152 | +
|
|---|
| 153 | +void DTVRecorder::HandleKeyframe() {
|
|---|
| 154 | + long long frameNum = _frames_written_count - 1;
|
|---|
| 155 | +
|
|---|
| 156 | + if (!_keyframe_seen && _frames_seen_count > 0)
|
|---|
| 157 | + {
|
|---|
| 158 | + if (_first_keyframe > 0)
|
|---|
| 159 | + _keyframe_seen = true;
|
|---|
| 160 | + else
|
|---|
| 161 | + _first_keyframe = (frameNum > 0) ? frameNum : 1;
|
|---|
| 162 | + }
|
|---|
| 163 | +
|
|---|
| 164 | + long long startpos =
|
|---|
| 165 | + ringBuffer->GetWritePosition();
|
|---|
| 166 | +
|
|---|
| 167 | + if (!_position_map.contains(frameNum))
|
|---|
| 168 | + {
|
|---|
| 169 | + _position_map_delta[frameNum] = startpos;
|
|---|
| 170 | + _position_map[frameNum] = startpos;
|
|---|
| 171 | +
|
|---|
| 172 | + if (curRecording &&
|
|---|
| 173 | + _position_map_delta.size() == 30)
|
|---|
| 174 | + {
|
|---|
| 175 | + curRecording->SetPositionMapDelta(_position_map_delta,
|
|---|
| 176 | + MARK_GOP_BYFRAME);
|
|---|
| 177 | + curRecording->SetFilesize(startpos);
|
|---|
| 178 | + _position_map_delta.clear();
|
|---|
| 179 | + }
|
|---|
| 180 | + }
|
|---|
| 181 | +
|
|---|
| 182 | +}
|
|---|