1 | --- /home/mythtv/work2/mythtv-0.19/libs/libmythtv/dtvrecorder.h 2005-12-14 07:54:48.000000000 -0800 |
---|
2 | +++ libs/libmythtv/dtvrecorder.h 2006-02-20 18:22:59.000000000 -0800 |
---|
3 | @@ -59,6 +59,7 @@ |
---|
4 | // used for scanning pes headers for keyframes |
---|
5 | uint _header_pos; |
---|
6 | int _first_keyframe; |
---|
7 | + int _position_within_gop_header; |
---|
8 | unsigned long long _last_gop_seen; |
---|
9 | unsigned long long _last_seq_seen; |
---|
10 | unsigned long long _last_keyframe_seen; |
---|
11 | --- /home/mythtv/work2/mythtv-0.19/libs/libmythtv/dtvrecorder.cpp 2006-02-07 13:56:06.000000000 -0800 |
---|
12 | +++ libs/libmythtv/dtvrecorder.cpp 2006-02-20 18:49:09.000000000 -0800 |
---|
13 | @@ -37,6 +37,7 @@ |
---|
14 | _stream_fd(-1), |
---|
15 | // used for scanning pes headers for keyframes |
---|
16 | _header_pos(0), _first_keyframe(-1), |
---|
17 | + _position_within_gop_header(0), |
---|
18 | _last_gop_seen(0), _last_seq_seen(0), |
---|
19 | _last_keyframe_seen(0), |
---|
20 | // settings |
---|
21 | @@ -126,6 +127,7 @@ |
---|
22 | |
---|
23 | _header_pos = 0; |
---|
24 | _first_keyframe =-1; |
---|
25 | + _position_within_gop_header = 0; |
---|
26 | _last_keyframe_seen = 0; |
---|
27 | _last_gop_seen = 0; |
---|
28 | _last_seq_seen = 0; |
---|
29 | @@ -195,6 +197,101 @@ |
---|
30 | */ |
---|
31 | bool DTVRecorder::FindKeyframes(const TSPacket* tspacket) |
---|
32 | { |
---|
33 | +#define AVG_KEYFRAME_DIFF 16 |
---|
34 | +#define MAX_KEYFRAME_DIFF 32 |
---|
35 | +#define DEBUG_FIND_KEY_FRAMES 0 /* set to 1 to debug */ |
---|
36 | + bool haveBufferedData = !_payload_buffer.empty(); |
---|
37 | + bool hasKeyFrame = false; |
---|
38 | + bool noPayload = !tspacket->HasPayload(); |
---|
39 | + bool payloadStart = tspacket->PayloadStart(); |
---|
40 | + |
---|
41 | + if (noPayload) |
---|
42 | + return !haveBufferedData; // no payload to scan |
---|
43 | + |
---|
44 | + if (payloadStart) |
---|
45 | + { // packet contains start of PES packet |
---|
46 | + _position_within_gop_header = 0; // start looking for first byte of pattern |
---|
47 | + } |
---|
48 | + |
---|
49 | + // Scan for PES header codes; specifically picture_start |
---|
50 | + // and group_start (of_pictures). These should be within |
---|
51 | + // this first TS packet of the PES packet. |
---|
52 | + // 00 00 01 00: picture_start_code |
---|
53 | + // 00 00 01 B8: group_start_code |
---|
54 | + // 00 00 01 B3: seq_start_code |
---|
55 | + // (there are others that we don't care about) |
---|
56 | + long long frameSeenNum = _frames_seen_count; |
---|
57 | + const unsigned char *buffer = tspacket->data(); |
---|
58 | + for (unsigned int i = tspacket->AFCOffset(); i+1<TSPacket::SIZE; i++) |
---|
59 | + { |
---|
60 | + const unsigned char k = buffer[i]; |
---|
61 | + if (0 == _position_within_gop_header) |
---|
62 | + _position_within_gop_header = (k == 0x00) ? 1 : 0; |
---|
63 | + else if (1 == _position_within_gop_header) |
---|
64 | + _position_within_gop_header = (k == 0x00) ? 2 : 0; |
---|
65 | + else |
---|
66 | + { |
---|
67 | + if (0x01 != k) |
---|
68 | + { |
---|
69 | + _position_within_gop_header = (k == 0x00) ? 2 : 0; |
---|
70 | + continue; |
---|
71 | + } |
---|
72 | + const unsigned char k1 = buffer[i+1]; |
---|
73 | + if (0x00 == k1) |
---|
74 | + { // 00 00 01 00: picture_start_code |
---|
75 | + _frames_written_count += (_first_keyframe > 0) ? 1 : 0; |
---|
76 | + _frames_seen_count++; |
---|
77 | + // We've seen 30 frames and no GOP or seq header? let's pretend we have them |
---|
78 | + if ((0==(_frames_seen_count & 0xf)) && |
---|
79 | + (_last_gop_seen+(MAX_KEYFRAME_DIFF+AVG_KEYFRAME_DIFF))<frameSeenNum && |
---|
80 | + (_last_seq_seen+(MAX_KEYFRAME_DIFF+AVG_KEYFRAME_DIFF))<frameSeenNum) { |
---|
81 | +#if DEBUG_FIND_KEY_FRAMES |
---|
82 | + VERBOSE(VB_RECORD, QString("f16 sc(%1) wc(%2) lgop(%3) lseq(%4)"). |
---|
83 | + arg(_frames_seen_count).arg(_frames_written_count). |
---|
84 | + arg(_last_gop_seen).arg(_last_seq_seen)); |
---|
85 | +#endif |
---|
86 | + HandleKeyframe(); |
---|
87 | + hasKeyFrame = true; |
---|
88 | + _last_keyframe_seen = frameSeenNum; |
---|
89 | + } |
---|
90 | + } else if (0xB8 == k1) |
---|
91 | + { // 00 00 01 B8: group_start_code |
---|
92 | +#if DEBUG_FIND_KEY_FRAMES |
---|
93 | + VERBOSE(VB_RECORD, QString("GOP sc(%1) wc(%2) lgop(%3) lseq(%4)"). |
---|
94 | + arg(_frames_seen_count).arg(_frames_written_count). |
---|
95 | + arg(_last_gop_seen).arg(_last_seq_seen)); |
---|
96 | +#endif |
---|
97 | + HandleKeyframe(); |
---|
98 | + hasKeyFrame = true; |
---|
99 | + _last_keyframe_seen = _last_gop_seen = frameSeenNum; |
---|
100 | + } else if (0xB3 == k1) |
---|
101 | + { // 00 00 01 B3: seq_start_code |
---|
102 | + if ((_last_gop_seen+MAX_KEYFRAME_DIFF)<frameSeenNum) |
---|
103 | + { |
---|
104 | +#if DEBUG_FIND_KEY_FRAMES |
---|
105 | + VERBOSE(VB_RECORD, QString("seq sc(%1) wc(%2) lgop(%3) lseq(%4)"). |
---|
106 | + arg(_frames_seen_count).arg(_frames_written_count). |
---|
107 | + arg(_last_gop_seen).arg(_last_seq_seen)); |
---|
108 | +#endif |
---|
109 | + HandleKeyframe(); |
---|
110 | + hasKeyFrame = true; |
---|
111 | + _last_keyframe_seen = frameSeenNum; |
---|
112 | + } |
---|
113 | + _last_seq_seen = frameSeenNum; |
---|
114 | + } |
---|
115 | + _position_within_gop_header = 0; |
---|
116 | + } |
---|
117 | + } |
---|
118 | +#undef AVG_KEYFRAME_DIFF |
---|
119 | +#undef MAX_KEYFRAME_DIFF |
---|
120 | +#undef DEBUG_FIND_KEY_FRAMES |
---|
121 | + |
---|
122 | + return hasKeyFrame || (_payload_buffer.size() >= (188*50)); |
---|
123 | +} |
---|
124 | + |
---|
125 | +/* |
---|
126 | +bool DTVRecorder::FindKeyframes(const TSPacket* tspacket) |
---|
127 | +{ |
---|
128 | bool haveBufferedData = !_payload_buffer.empty(); |
---|
129 | if (!tspacket->HasPayload()) // no payload to scan |
---|
130 | return !haveBufferedData; |
---|
131 | @@ -273,6 +370,7 @@ |
---|
132 | |
---|
133 | return hasKeyFrame || (_payload_buffer.size() >= (188*50)); |
---|
134 | } |
---|
135 | +*/ |
---|
136 | |
---|
137 | // documented in recorderbase.h |
---|
138 | void DTVRecorder::SetNextRecording(const ProgramInfo *progInf, RingBuffer *rb) |
---|