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