Ticket #1356: dtvrecorder_patch.2

File dtvrecorder_patch.2, 6.5 KB (added by mark.goodman+mythtv@…, 20 years ago)

Patch to restore FindKeyframes and HandleKeyframe from 0.18.1

Line 
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+}