Ticket #1356: dtvrecorder_patch.2

File dtvrecorder_patch.2, 6.5 KB (added by mark.goodman+mythtv@…, 18 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+}