1 | diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp |
---|
2 | index 3eb42c7..41baca6 100644 |
---|
3 | --- a/mythtv/libs/libmythtv/avformatdecoder.cpp |
---|
4 | +++ b/mythtv/libs/libmythtv/avformatdecoder.cpp |
---|
5 | @@ -3108,7 +3108,7 @@ int AvFormatDecoder::H264PreProcessPkt(AVStream *stream, AVPacket *pkt) |
---|
6 | { |
---|
7 | buf += m_h264_parser->addBytes(buf, buf_end - buf, 0); |
---|
8 | |
---|
9 | - if (m_h264_parser->stateChanged()) |
---|
10 | + if (m_h264_parser->stateChanged() && m_h264_parser->seen_SPS()) |
---|
11 | { |
---|
12 | if (m_h264_parser->FieldType() != H264Parser::FIELD_BOTTOM) |
---|
13 | { |
---|
14 | diff --git a/mythtv/libs/libmythtv/mpeg/H264Parser.cpp b/mythtv/libs/libmythtv/mpeg/H264Parser.cpp |
---|
15 | index 3e45c60..35def81 100644 |
---|
16 | --- a/mythtv/libs/libmythtv/mpeg/H264Parser.cpp |
---|
17 | +++ b/mythtv/libs/libmythtv/mpeg/H264Parser.cpp |
---|
18 | @@ -98,7 +98,7 @@ H264Parser::H264Parser(void) |
---|
19 | rbsp_buffer_size = 0; |
---|
20 | |
---|
21 | Reset(); |
---|
22 | - I_is_keyframe = true; |
---|
23 | + I_is_keyframe = false; |
---|
24 | au_contains_keyframe_message = false; |
---|
25 | } |
---|
26 | |
---|
27 | @@ -116,14 +116,14 @@ void H264Parser::Reset(void) |
---|
28 | prev_pic_parameter_set_id = pic_parameter_set_id = -1; |
---|
29 | prev_field_pic_flag = field_pic_flag = -1; |
---|
30 | prev_bottom_field_flag = bottom_field_flag = -1; |
---|
31 | - prev_nal_ref_idc = nal_ref_idc = 0; |
---|
32 | + prev_nal_ref_idc = nal_ref_idc = 111; // != [0|1|2|3] |
---|
33 | prev_pic_order_cnt_type = pic_order_cnt_type = |
---|
34 | prev_pic_order_cnt_lsb = pic_order_cnt_lsb = 0; |
---|
35 | prev_delta_pic_order_cnt_bottom = delta_pic_order_cnt_bottom = 0; |
---|
36 | prev_delta_pic_order_cnt[0] = delta_pic_order_cnt[0] = 0; |
---|
37 | prev_delta_pic_order_cnt[1] = delta_pic_order_cnt[1] = 0; |
---|
38 | prev_nal_unit_type = nal_unit_type = UNKNOWN; |
---|
39 | - prev_idr_pic_id = idr_pic_id = 0; |
---|
40 | + prev_idr_pic_id = idr_pic_id = 111; // != [0|1|2|3] |
---|
41 | |
---|
42 | log2_max_frame_num = log2_max_pic_order_cnt_lsb = 0; |
---|
43 | seq_parameter_set_id = 0; |
---|
44 | @@ -401,6 +401,7 @@ uint32_t H264Parser::addBytes(const uint8_t *bytes, |
---|
45 | const uint8_t *startP = bytes; |
---|
46 | const uint8_t *endP; |
---|
47 | bool found_start_code; |
---|
48 | + bool good_nal_unit; |
---|
49 | |
---|
50 | state_changed = false; |
---|
51 | on_frame = false; |
---|
52 | @@ -474,23 +475,41 @@ uint32_t H264Parser::addBytes(const uint8_t *bytes, |
---|
53 | nal_unit_type = sync_accumulator & 0x1f; |
---|
54 | nal_ref_idc = (sync_accumulator >> 5) & 0x3; |
---|
55 | |
---|
56 | - if (nal_unit_type == SPS || nal_unit_type == PPS || |
---|
57 | - nal_unit_type == SEI || NALisSlice(nal_unit_type)) |
---|
58 | - { |
---|
59 | - /* This is a NAL we need to parse. We may have the body |
---|
60 | - * of it in the part of the stream past to us this call, |
---|
61 | - * or we may get the rest in subsequent calls to addBytes. |
---|
62 | - * Either way, we set have_unfinished_NAL, so that we |
---|
63 | - * start filling the rbsp buffer */ |
---|
64 | - have_unfinished_NAL = true; |
---|
65 | - } |
---|
66 | - else if (nal_unit_type == AU_DELIMITER || |
---|
67 | - (nal_unit_type > SPS_EXT && |
---|
68 | - nal_unit_type < AUXILIARY_SLICE)) |
---|
69 | +/* nal_ref_idc shall be equal to 0 for all NAL units having nal_unit_type equal to 6, 9, 10, 11, or 12. |
---|
70 | + */ |
---|
71 | + good_nal_unit = true; |
---|
72 | + if (nal_ref_idc && (nal_unit_type == SEI || (nal_unit_type >= AU_DELIMITER && |
---|
73 | + nal_unit_type <= FILLER_DATA)) ) |
---|
74 | + good_nal_unit = false; |
---|
75 | + |
---|
76 | +/* nal_ref_idc shall not be equal to 0 for NAL units with nal_unit_type equal to 5 |
---|
77 | + */ |
---|
78 | + if (!nal_ref_idc && (nal_unit_type == SLICE_IDR)) |
---|
79 | + good_nal_unit = false; |
---|
80 | + |
---|
81 | + if (good_nal_unit) |
---|
82 | { |
---|
83 | - set_AU_pending(); |
---|
84 | + if (nal_unit_type == SPS || nal_unit_type == PPS || |
---|
85 | + nal_unit_type == SEI || NALisSlice(nal_unit_type)) |
---|
86 | + { |
---|
87 | + /* This is a NAL we need to parse. We may have the body |
---|
88 | + * of it in the part of the stream past to us this call, |
---|
89 | + * or we may get the rest in subsequent calls to addBytes. |
---|
90 | + * Either way, we set have_unfinished_NAL, so that we |
---|
91 | + * start filling the rbsp buffer */ |
---|
92 | + have_unfinished_NAL = true; |
---|
93 | + } |
---|
94 | + else if (nal_unit_type == AU_DELIMITER || |
---|
95 | + (nal_unit_type > SPS_EXT && |
---|
96 | + nal_unit_type < AUXILIARY_SLICE)) |
---|
97 | + { |
---|
98 | + set_AU_pending(); |
---|
99 | + } |
---|
100 | } |
---|
101 | - } |
---|
102 | + else |
---|
103 | + LOG(VB_GENERAL, LOG_ERR, |
---|
104 | + "H264Parser::addbytes: malformed NAL units"); |
---|
105 | + } //found start code |
---|
106 | } |
---|
107 | |
---|
108 | return startP - bytes; |
---|
109 | @@ -523,6 +542,9 @@ void H264Parser::processRBSP(bool rbsp_complete) |
---|
110 | |
---|
111 | set_AU_pending(); |
---|
112 | |
---|
113 | + if (!seen_sps) |
---|
114 | + SPS_offset = pkt_offset; |
---|
115 | + |
---|
116 | decode_SPS(&gb); |
---|
117 | } |
---|
118 | else if (nal_unit_type == PPS) |
---|
119 | @@ -576,6 +598,8 @@ void H264Parser::processRBSP(bool rbsp_complete) |
---|
120 | */ |
---|
121 | bool H264Parser::decode_Header(GetBitContext *gb) |
---|
122 | { |
---|
123 | + uint first_mb_in_slice; |
---|
124 | + |
---|
125 | is_keyframe = false; |
---|
126 | |
---|
127 | if (log2_max_frame_num == 0 || pic_order_present_flag == -1) |
---|
128 | @@ -601,8 +625,7 @@ bool H264Parser::decode_Header(GetBitContext *gb) |
---|
129 | that precedes the current slice in decoding order and has the |
---|
130 | same value of colour_plane_id. |
---|
131 | */ |
---|
132 | - //uint first_mb_in_slice = get_ue_golomb(gb); |
---|
133 | - get_ue_golomb(gb); // Replaced above line |
---|
134 | + first_mb_in_slice = get_ue_golomb_long(gb); |
---|
135 | |
---|
136 | /* |
---|
137 | slice_type specifies the coding type of the slice according to |
---|
138 | @@ -611,8 +634,10 @@ bool H264Parser::decode_Header(GetBitContext *gb) |
---|
139 | When nal_unit_type is equal to 5 (IDR picture), slice_type shall |
---|
140 | be equal to 2, 4, 7, or 9 (I or SI) |
---|
141 | */ |
---|
142 | - slice_type = get_ue_golomb(gb); |
---|
143 | + slice_type = get_ue_golomb_31(gb); |
---|
144 | |
---|
145 | + /* s->pict_type = golomb_to_pict_type[slice_type % 5]; |
---|
146 | + */ |
---|
147 | /* |
---|
148 | pic_parameter_set_id specifies the picture parameter set in |
---|
149 | use. The value of pic_parameter_set_id shall be in the range of |
---|
150 | @@ -642,6 +667,8 @@ bool H264Parser::decode_Header(GetBitContext *gb) |
---|
151 | bitstream.... |
---|
152 | |
---|
153 | If the current picture is an IDR picture, frame_num shall be equal to 0. |
---|
154 | + |
---|
155 | + When max_num_ref_frames is equal to 0, slice_type shall be equal to 2, 4, 7, or 9. |
---|
156 | */ |
---|
157 | |
---|
158 | frame_num = get_bits(gb, log2_max_frame_num); |
---|
159 | @@ -683,9 +710,10 @@ bool H264Parser::decode_Header(GetBitContext *gb) |
---|
160 | { |
---|
161 | idr_pic_id = get_ue_golomb(gb); |
---|
162 | is_keyframe = true; |
---|
163 | + I_is_keyframe = true; |
---|
164 | } |
---|
165 | else |
---|
166 | - is_keyframe |= I_is_keyframe && isKeySlice(slice_type); |
---|
167 | + is_keyframe |= isKeySlice(slice_type); |
---|
168 | /* |
---|
169 | pic_order_cnt_lsb specifies the picture order count modulo |
---|
170 | MaxPicOrderCntLsb for the top field of a coded frame or for a coded |
---|
171 | @@ -702,7 +730,7 @@ bool H264Parser::decode_Header(GetBitContext *gb) |
---|
172 | { |
---|
173 | pic_order_cnt_lsb = get_bits(gb, log2_max_pic_order_cnt_lsb); |
---|
174 | |
---|
175 | - if (pic_order_present_flag && !field_pic_flag) |
---|
176 | + if ((pic_order_present_flag == 1) && !field_pic_flag) |
---|
177 | delta_pic_order_cnt_bottom = get_se_golomb(gb); |
---|
178 | else |
---|
179 | delta_pic_order_cnt_bottom = 0; |
---|
180 | @@ -731,13 +759,17 @@ bool H264Parser::decode_Header(GetBitContext *gb) |
---|
181 | { |
---|
182 | delta_pic_order_cnt[0] = get_se_golomb(gb); |
---|
183 | |
---|
184 | - if (pic_order_present_flag && !field_pic_flag) |
---|
185 | + if ((pic_order_present_flag == 1) && !field_pic_flag) |
---|
186 | delta_pic_order_cnt[1] = get_se_golomb(gb); |
---|
187 | - else |
---|
188 | + } |
---|
189 | + else |
---|
190 | + { |
---|
191 | + if (pic_order_cnt_type == 1) |
---|
192 | + { |
---|
193 | delta_pic_order_cnt[1] = 0; |
---|
194 | - } |
---|
195 | - else |
---|
196 | - delta_pic_order_cnt[0] = 0; |
---|
197 | + delta_pic_order_cnt[0] = 0; |
---|
198 | + } |
---|
199 | + } |
---|
200 | |
---|
201 | /* |
---|
202 | redundant_pic_cnt shall be equal to 0 for slices and slice data |
---|
203 | @@ -760,6 +792,9 @@ bool H264Parser::decode_Header(GetBitContext *gb) |
---|
204 | void H264Parser::decode_SPS(GetBitContext * gb) |
---|
205 | { |
---|
206 | int profile_idc; |
---|
207 | + int lastScale; |
---|
208 | + int nextScale; |
---|
209 | + int deltaScale; |
---|
210 | |
---|
211 | seen_sps = true; |
---|
212 | |
---|
213 | @@ -772,7 +807,9 @@ void H264Parser::decode_SPS(GetBitContext * gb) |
---|
214 | get_bits(gb, 8); // level_idc |
---|
215 | get_ue_golomb(gb); // sps_id |
---|
216 | |
---|
217 | - if (profile_idc >= 100) |
---|
218 | + if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || |
---|
219 | + profile_idc == 244 || profile_idc == 44 || profile_idc == 83 || |
---|
220 | + profile_idc == 86 || profile_idc == 118 || profile_idc == 128 ) |
---|
221 | { // high profile |
---|
222 | if ((chroma_format_idc = get_ue_golomb(gb)) == 3) // chroma_format_idc |
---|
223 | separate_colour_plane_flag = (get_bits1(gb) == 1); |
---|
224 | @@ -783,14 +820,19 @@ void H264Parser::decode_SPS(GetBitContext * gb) |
---|
225 | |
---|
226 | if (get_bits1(gb)) // seq_scaling_matrix_present_flag |
---|
227 | { |
---|
228 | - for (int idx = 0; idx < ((chroma_format_idc != 3) ? 8 : 12); ++idx) |
---|
229 | + for (int idx = 0; idx < ((chroma_format_idc != 3) ? 8 : 12); idx++) |
---|
230 | { |
---|
231 | - if (get_bits1(gb)) // Scaling list presnent |
---|
232 | + if (get_bits1(gb)) // Scaling list present |
---|
233 | { |
---|
234 | + lastScale = nextScale = 8; |
---|
235 | int sl_n = ((idx < 6) ? 16 : 64); |
---|
236 | for(int sl_i = 0; sl_i < sl_n; sl_i++) |
---|
237 | { |
---|
238 | - get_se_golomb(gb); |
---|
239 | + if (nextScale != 0) |
---|
240 | + { |
---|
241 | + deltaScale = get_se_golomb(gb); |
---|
242 | + nextScale = (lastScale + deltaScale + 256) % 256; |
---|
243 | + } |
---|
244 | } |
---|
245 | } |
---|
246 | } |
---|
247 | @@ -809,6 +851,7 @@ void H264Parser::decode_SPS(GetBitContext * gb) |
---|
248 | int offset_for_non_ref_pic; |
---|
249 | int offset_for_top_to_bottom_field; |
---|
250 | uint tmp; |
---|
251 | + bool gaps_in_frame_num_allowed_flag; |
---|
252 | |
---|
253 | /* |
---|
254 | pic_order_cnt_type specifies the method to decode picture order |
---|
255 | @@ -863,7 +906,7 @@ void H264Parser::decode_SPS(GetBitContext * gb) |
---|
256 | shall be in the range of -231 to 231 - 1, inclusive. |
---|
257 | */ |
---|
258 | tmp = get_ue_golomb(gb); |
---|
259 | - for (uint idx = 0; idx < tmp; ++idx) |
---|
260 | + for (uint idx = 0; idx < tmp; idx++) |
---|
261 | get_se_golomb(gb); // offset_for_ref_frame[i] |
---|
262 | } |
---|
263 | (void) offset_for_non_ref_pic; // suppress unused var warning |
---|
264 | @@ -886,8 +929,7 @@ void H264Parser::decode_SPS(GetBitContext * gb) |
---|
265 | decoding process in case of an inferred gap between values of |
---|
266 | frame_num as specified in subclause 8.2.5.2. |
---|
267 | */ |
---|
268 | - //bool gaps_in_frame_num_allowed_flag = get_bits1(gb); |
---|
269 | - get_bits1(gb); // Replaced above line |
---|
270 | + gaps_in_frame_num_allowed_flag = get_bits1(gb); |
---|
271 | |
---|
272 | /* |
---|
273 | pic_width_in_mbs_minus1 plus 1 specifies the width of each |
---|
274 | @@ -1040,20 +1082,28 @@ void H264Parser::decode_SEI(GetBitContext *gb) |
---|
275 | bool broken_link_flag = false; |
---|
276 | int changing_group_slice_idc = -1; |
---|
277 | |
---|
278 | - int type = 0, size = 0; |
---|
279 | + int type = 0, size = 0, tmp_byte = 0; |
---|
280 | |
---|
281 | /* A message requires at least 2 bytes, and then |
---|
282 | * there's the stop bit plus alignment, so there |
---|
283 | * can be no message in less than 24 bits */ |
---|
284 | while (get_bits_left(gb) >= 24) |
---|
285 | { |
---|
286 | - do { |
---|
287 | - type += show_bits(gb, 8); |
---|
288 | - } while (get_bits(gb, 8) == 255); |
---|
289 | + tmp_byte = get_bits(gb, 8); |
---|
290 | + while (tmp_byte == 255) |
---|
291 | + { |
---|
292 | + type += 255; |
---|
293 | + tmp_byte = get_bits(gb, 8); |
---|
294 | + } |
---|
295 | + type += get_bits(gb, 8); //last_payload_type_byte |
---|
296 | |
---|
297 | - do { |
---|
298 | - size += show_bits(gb, 8); |
---|
299 | - } while (get_bits(gb, 8) == 255); |
---|
300 | + tmp_byte = get_bits(gb, 8); |
---|
301 | + while (tmp_byte == 255) |
---|
302 | + { |
---|
303 | + size += 255; |
---|
304 | + tmp_byte = get_bits(gb, 8); |
---|
305 | + } |
---|
306 | + size += get_bits(gb, 8); //last_payload_size_byte |
---|
307 | |
---|
308 | switch (type) |
---|
309 | { |
---|
310 | @@ -1063,6 +1113,8 @@ void H264Parser::decode_SEI(GetBitContext *gb) |
---|
311 | broken_link_flag = get_bits1(gb); |
---|
312 | changing_group_slice_idc = get_bits(gb, 2); |
---|
313 | au_contains_keyframe_message = (recovery_frame_cnt == 0); |
---|
314 | + if ((size - 12) > 0) |
---|
315 | + skip_bits(gb, (size - 12) * 8); |
---|
316 | return; |
---|
317 | |
---|
318 | default: |
---|
319 | diff --git a/mythtv/libs/libmythtv/mpeg/H264Parser.h b/mythtv/libs/libmythtv/mpeg/H264Parser.h |
---|
320 | index 9c984e0..7b750f2 100644 |
---|
321 | --- a/mythtv/libs/libmythtv/mpeg/H264Parser.h |
---|
322 | +++ b/mythtv/libs/libmythtv/mpeg/H264Parser.h |
---|
323 | @@ -60,7 +60,7 @@ class H264Parser { |
---|
324 | // ITU-T Rec. H.264 table 7-1 |
---|
325 | enum NAL_unit_type { |
---|
326 | UNKNOWN = 0, |
---|
327 | - SLICE = 1, |
---|
328 | + SLICE = 1, // 1 - 5 are VCL NAL units |
---|
329 | SLICE_DPA = 2, |
---|
330 | SLICE_DPB = 3, |
---|
331 | SLICE_DPC = 4, |
---|
332 | @@ -73,11 +73,15 @@ class H264Parser { |
---|
333 | END_STREAM = 11, |
---|
334 | FILLER_DATA = 12, |
---|
335 | SPS_EXT = 13, |
---|
336 | - AUXILIARY_SLICE = 19 |
---|
337 | + NALU_prefix = 14, |
---|
338 | + SPS_subset = 15, |
---|
339 | + AUXILIARY_SLICE = 19, |
---|
340 | + SLICE_EXTENSION = 20 |
---|
341 | }; |
---|
342 | |
---|
343 | enum SEI_type { |
---|
344 | SEI_TYPE_PIC_TIMING = 1, |
---|
345 | + SEI_FILLER_PAYLOAD = 3, |
---|
346 | SEI_TYPE_USER_DATA_UNREGISTERED = 5, |
---|
347 | SEI_TYPE_RECOVERY_POINT = 6 |
---|
348 | }; |
---|
349 | @@ -147,7 +151,9 @@ class H264Parser { |
---|
350 | |
---|
351 | uint64_t frameAUstreamOffset(void) const {return frame_start_offset;} |
---|
352 | uint64_t keyframeAUstreamOffset(void) const {return keyframe_start_offset;} |
---|
353 | + uint64_t SPSstreamOffset(void) const {return SPS_offset;} |
---|
354 | |
---|
355 | +// == NAL_type AU_delimiter: primary_pic_type = 5 |
---|
356 | static int isKeySlice(uint slice_type) |
---|
357 | { |
---|
358 | return (slice_type == SLICE_I || |
---|
359 | @@ -164,6 +170,7 @@ class H264Parser { |
---|
360 | } |
---|
361 | |
---|
362 | void use_I_forKeyframes(bool val) { I_is_keyframe = val; } |
---|
363 | + bool using_I_forKeyframes(void) const { return I_is_keyframe; } |
---|
364 | |
---|
365 | uint32_t GetTimeScale(void) const { return timeScale; } |
---|
366 | |
---|
367 | @@ -172,6 +179,10 @@ class H264Parser { |
---|
368 | void parse_SPS(uint8_t *sps, uint32_t sps_size, |
---|
369 | bool& interlaced, int32_t& max_ref_frames); |
---|
370 | |
---|
371 | + bool seen_SPS(void) const { return seen_sps; } |
---|
372 | + |
---|
373 | + bool found_AU(void) const { return AU_pending; } |
---|
374 | + |
---|
375 | private: |
---|
376 | enum constants {EXTENDED_SAR = 255}; |
---|
377 | |
---|
378 | @@ -247,6 +258,7 @@ class H264Parser { |
---|
379 | bool fixedRate; |
---|
380 | |
---|
381 | uint64_t pkt_offset, AU_offset, frame_start_offset, keyframe_start_offset; |
---|
382 | + uint64_t SPS_offset; |
---|
383 | bool on_frame, on_key_frame; |
---|
384 | }; |
---|
385 | |
---|
386 | diff --git a/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp b/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp |
---|
387 | index e25774d..b51b3a3 100644 |
---|
388 | --- a/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp |
---|
389 | +++ b/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp |
---|
390 | @@ -64,7 +64,7 @@ DTVRecorder::DTVRecorder(TVRec *rec) : |
---|
391 | _pes_synced(false), |
---|
392 | _seen_sps(false), |
---|
393 | // settings |
---|
394 | - _wait_for_keyframe_option(true), |
---|
395 | + _wait_for_keyframe_option(true), // is wait_for_SPS for H264 |
---|
396 | _has_written_other_keyframe(false), |
---|
397 | // state |
---|
398 | _error(), |
---|
399 | @@ -276,9 +276,8 @@ void DTVRecorder::BufferedWrite(const TSPacket &tspacket, bool insert) |
---|
400 | { |
---|
401 | if (!insert) // PAT/PMT may need inserted in front of any buffered data |
---|
402 | { |
---|
403 | - // delay until first GOP to avoid decoder crash on res change |
---|
404 | - if (!_buffer_packets && _wait_for_keyframe_option && |
---|
405 | - _first_keyframe < 0) |
---|
406 | + // delay until first SPS/GOP to avoid decoder crash on res change |
---|
407 | + if (!_buffer_packets && _wait_for_keyframe_option && !_seen_sps) |
---|
408 | return; |
---|
409 | |
---|
410 | if (curRecording && timeOfFirstDataIsSet.testAndSetRelaxed(0,1)) |
---|
411 | @@ -552,6 +551,7 @@ bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket) |
---|
412 | .arg(_payload_buffer.size()) |
---|
413 | .arg(ringBuffer->GetWritePosition() + _payload_buffer.size())); |
---|
414 | |
---|
415 | + _seen_sps = true; // used by H264 to signal start rec to file |
---|
416 | _last_keyframe_seen = _frames_seen_count; |
---|
417 | HandleKeyframe(0); |
---|
418 | } |
---|
419 | @@ -718,6 +718,7 @@ bool DTVRecorder::FindAudioKeyframes(const TSPacket*) |
---|
420 | _audio_timer.start(); |
---|
421 | |
---|
422 | _buffer_packets = false; |
---|
423 | + _seen_sps = true; // unblock BufferedWrite() |
---|
424 | _frames_seen_count++; |
---|
425 | |
---|
426 | if (1 == (_frames_seen_count & 0x7)) |
---|
427 | @@ -898,30 +899,38 @@ bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket) |
---|
428 | uint32_t bytes_used = m_h264_parser.addBytes |
---|
429 | (tspacket->data() + i, TSPacket::kSize - i, |
---|
430 | ringBuffer->GetWritePosition()); |
---|
431 | - i += (bytes_used - 1); |
---|
432 | |
---|
433 | - if (m_h264_parser.stateChanged()) |
---|
434 | + if (!_seen_sps && m_h264_parser.seen_SPS()) |
---|
435 | + _seen_sps = true; |
---|
436 | + |
---|
437 | + if (m_h264_parser.stateChanged() && _seen_sps) |
---|
438 | { |
---|
439 | if (m_h264_parser.onFrameStart() && |
---|
440 | m_h264_parser.FieldType() != H264Parser::FIELD_BOTTOM) |
---|
441 | { |
---|
442 | hasKeyFrame = m_h264_parser.onKeyFrameStart(); |
---|
443 | hasFrame = true; |
---|
444 | - _seen_sps |= hasKeyFrame; |
---|
445 | - |
---|
446 | + |
---|
447 | width = m_h264_parser.pictureWidth(); |
---|
448 | height = m_h264_parser.pictureHeight(); |
---|
449 | aspectRatio = m_h264_parser.aspectRatio(); |
---|
450 | m_h264_parser.getFrameRate(frameRate); |
---|
451 | } |
---|
452 | } |
---|
453 | + |
---|
454 | + i += (bytes_used - 1); |
---|
455 | } // for (; i < TSPacket::kSize; ++i) |
---|
456 | |
---|
457 | // _buffer_packets will only be true if a payload start has been seen |
---|
458 | - if (hasKeyFrame && (_buffer_packets || _first_keyframe >= 0)) |
---|
459 | + if (_seen_sps) |
---|
460 | + _buffer_packets = false; |
---|
461 | + else |
---|
462 | + _payload_buffer.clear(); |
---|
463 | + |
---|
464 | + if (hasKeyFrame) |
---|
465 | { |
---|
466 | LOG(VB_RECORD, LOG_DEBUG, LOC + QString |
---|
467 | - ("Keyframe @ %1 + %2 = %3 AU %4") |
---|
468 | + ("H264Keyframe @ %1 + %2 = %3 AU %4") |
---|
469 | .arg(ringBuffer->GetWritePosition()) |
---|
470 | .arg(_payload_buffer.size()) |
---|
471 | .arg(ringBuffer->GetWritePosition() + _payload_buffer.size()) |
---|
472 | @@ -934,22 +943,15 @@ bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket) |
---|
473 | if (hasFrame) |
---|
474 | { |
---|
475 | LOG(VB_RECORD, LOG_DEBUG, LOC + QString |
---|
476 | - ("Frame @ %1 + %2 = %3 AU %4") |
---|
477 | + ("H264Frame @ %1 + %2 = %3 AU %4") |
---|
478 | .arg(ringBuffer->GetWritePosition()) |
---|
479 | .arg(_payload_buffer.size()) |
---|
480 | .arg(ringBuffer->GetWritePosition() + _payload_buffer.size()) |
---|
481 | - .arg(m_h264_parser.keyframeAUstreamOffset())); |
---|
482 | + .arg(m_h264_parser.frameAUstreamOffset())); |
---|
483 | |
---|
484 | - _buffer_packets = false; // We now know if this is a keyframe |
---|
485 | _frames_seen_count++; |
---|
486 | if (!_wait_for_keyframe_option || _first_keyframe >= 0) |
---|
487 | UpdateFramesWritten(); |
---|
488 | - else |
---|
489 | - { |
---|
490 | - /* Found a frame that is not a keyframe, and we want to |
---|
491 | - * start on a keyframe */ |
---|
492 | - _payload_buffer.clear(); |
---|
493 | - } |
---|
494 | } |
---|
495 | |
---|
496 | if ((aspectRatio > 0) && (aspectRatio != m_videoAspect)) |
---|
497 | @@ -971,12 +973,12 @@ bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket) |
---|
498 | QString("FindH264Keyframes: timescale: %1, tick: %2, framerate: %3") |
---|
499 | .arg( m_h264_parser.GetTimeScale() ) |
---|
500 | .arg( m_h264_parser.GetUnitsInTick() ) |
---|
501 | - .arg( frameRate.toDouble() * 1000 ) ); |
---|
502 | + .arg( frameRate.toDouble() ) ); |
---|
503 | m_frameRate = frameRate; |
---|
504 | FrameRateChange(frameRate.toDouble() * 1000, _frames_written_count); |
---|
505 | } |
---|
506 | |
---|
507 | - return _seen_sps; |
---|
508 | + return hasKeyFrame; |
---|
509 | } |
---|
510 | |
---|
511 | /** \fn DTVRecorder::HandleH264Keyframe(void) |
---|
512 | @@ -991,15 +993,9 @@ void DTVRecorder::HandleH264Keyframe(void) |
---|
513 | uint64_t startpos; |
---|
514 | uint64_t frameNum = _frames_written_count; |
---|
515 | |
---|
516 | - if (_first_keyframe < 0) |
---|
517 | - { |
---|
518 | - _first_keyframe = frameNum; |
---|
519 | - startpos = 0; |
---|
520 | - } |
---|
521 | - else |
---|
522 | - startpos = m_h264_parser.keyframeAUstreamOffset(); |
---|
523 | + startpos = m_h264_parser.keyframeAUstreamOffset(); |
---|
524 | |
---|
525 | - // Add key frame to position map |
---|
526 | + // Add keyframe to position map |
---|
527 | positionMapLock.lock(); |
---|
528 | if (!positionMap.contains(frameNum)) |
---|
529 | { |
---|
530 | @@ -1008,7 +1004,19 @@ void DTVRecorder::HandleH264Keyframe(void) |
---|
531 | durationMap[frameNum] = _total_duration + 0.5; |
---|
532 | durationMapDelta[frameNum] = _total_duration + 0.5; |
---|
533 | } |
---|
534 | + if ((_first_keyframe < 0) && !positionMap.contains(0)) |
---|
535 | + { |
---|
536 | + positionMapDelta[0] = 0; |
---|
537 | + positionMap[0] = 0; |
---|
538 | + durationMap[0] = 0.5; |
---|
539 | + durationMapDelta[0] = 0.5; |
---|
540 | + } |
---|
541 | positionMapLock.unlock(); |
---|
542 | + |
---|
543 | + if (_first_keyframe < 0) |
---|
544 | + { |
---|
545 | + _first_keyframe = frameNum; |
---|
546 | + } |
---|
547 | } |
---|
548 | |
---|
549 | void DTVRecorder::FindPSKeyFrames(const uint8_t *buffer, uint len) |
---|
550 | @@ -1328,6 +1336,7 @@ bool DTVRecorder::ProcessTSPacket(const TSPacket &tspacket) |
---|
551 | if (_input_pmt && _has_no_av) |
---|
552 | { |
---|
553 | FindOtherKeyframes(&tspacket); |
---|
554 | + _seen_sps = true; // unblock BufferedWrite() |
---|
555 | _buffer_packets = false; |
---|
556 | } |
---|
557 | else |
---|
558 | @@ -1383,11 +1392,11 @@ bool DTVRecorder::ProcessAudioTSPacket(const TSPacket &tspacket) |
---|
559 | return ProcessAVTSPacket(tspacket); |
---|
560 | } |
---|
561 | |
---|
562 | -/// Common code for processing either audio or video packets |
---|
563 | +/// Common code for processing either audio or video packets (mpeg2 or h264) |
---|
564 | bool DTVRecorder::ProcessAVTSPacket(const TSPacket &tspacket) |
---|
565 | { |
---|
566 | - // Sync recording start to first keyframe |
---|
567 | - if (_wait_for_keyframe_option && _first_keyframe < 0) |
---|
568 | + // Sync recording start to first SPS / keyframe |
---|
569 | + if (_wait_for_keyframe_option && !_seen_sps && _first_keyframe < 0) |
---|
570 | { |
---|
571 | if (_buffer_packets) |
---|
572 | BufferedWrite(tspacket); |
---|