Ticket #11435: gitdiff-cleaned5.txt

File gitdiff-cleaned5.txt, 25.0 KB (added by blm-ubunet@…, 13 years ago)

allow for H264 stream without SPS but still use it if possible.

Line 
1diff --git a/mythtv/libs/libmythtv/mpeg/H264Parser.cpp b/mythtv/libs/libmythtv/mpeg/H264Parser.cpp
2index 3e45c60..5e337de 100644
3--- a/mythtv/libs/libmythtv/mpeg/H264Parser.cpp
4+++ b/mythtv/libs/libmythtv/mpeg/H264Parser.cpp
5@@ -98,7 +98,7 @@ H264Parser::H264Parser(void)
6 rbsp_buffer_size = 0;
7
8 Reset();
9- I_is_keyframe = true;
10+ I_is_keyframe = false;
11 au_contains_keyframe_message = false;
12 }
13
14@@ -116,14 +116,14 @@ void H264Parser::Reset(void)
15 prev_pic_parameter_set_id = pic_parameter_set_id = -1;
16 prev_field_pic_flag = field_pic_flag = -1;
17 prev_bottom_field_flag = bottom_field_flag = -1;
18- prev_nal_ref_idc = nal_ref_idc = 0;
19+ prev_nal_ref_idc = nal_ref_idc = 111; // != [0|1|2|3]
20 prev_pic_order_cnt_type = pic_order_cnt_type =
21 prev_pic_order_cnt_lsb = pic_order_cnt_lsb = 0;
22 prev_delta_pic_order_cnt_bottom = delta_pic_order_cnt_bottom = 0;
23 prev_delta_pic_order_cnt[0] = delta_pic_order_cnt[0] = 0;
24 prev_delta_pic_order_cnt[1] = delta_pic_order_cnt[1] = 0;
25 prev_nal_unit_type = nal_unit_type = UNKNOWN;
26- prev_idr_pic_id = idr_pic_id = 0;
27+ prev_idr_pic_id = idr_pic_id = 111; // != [0|1|2|3]
28
29 log2_max_frame_num = log2_max_pic_order_cnt_lsb = 0;
30 seq_parameter_set_id = 0;
31@@ -401,6 +401,7 @@ uint32_t H264Parser::addBytes(const uint8_t *bytes,
32 const uint8_t *startP = bytes;
33 const uint8_t *endP;
34 bool found_start_code;
35+ bool good_nal_unit;
36
37 state_changed = false;
38 on_frame = false;
39@@ -474,23 +475,41 @@ uint32_t H264Parser::addBytes(const uint8_t *bytes,
40 nal_unit_type = sync_accumulator & 0x1f;
41 nal_ref_idc = (sync_accumulator >> 5) & 0x3;
42
43- if (nal_unit_type == SPS || nal_unit_type == PPS ||
44- nal_unit_type == SEI || NALisSlice(nal_unit_type))
45- {
46- /* This is a NAL we need to parse. We may have the body
47- * of it in the part of the stream past to us this call,
48- * or we may get the rest in subsequent calls to addBytes.
49- * Either way, we set have_unfinished_NAL, so that we
50- * start filling the rbsp buffer */
51- have_unfinished_NAL = true;
52- }
53- else if (nal_unit_type == AU_DELIMITER ||
54- (nal_unit_type > SPS_EXT &&
55- nal_unit_type < AUXILIARY_SLICE))
56+/* nal_ref_idc shall be equal to 0 for all NAL units having nal_unit_type equal to 6, 9, 10, 11, or 12.
57+ */
58+ good_nal_unit = true;
59+ if (nal_ref_idc && (nal_unit_type == SEI || (nal_unit_type >= AU_DELIMITER &&
60+ nal_unit_type <= FILLER_DATA)) )
61+ good_nal_unit = false;
62+
63+/* nal_ref_idc shall not be equal to 0 for NAL units with nal_unit_type equal to 5
64+ */
65+ if (!nal_ref_idc && (nal_unit_type == SLICE_IDR))
66+ good_nal_unit = false;
67+
68+ if (good_nal_unit)
69 {
70- set_AU_pending();
71+ if (nal_unit_type == SPS || nal_unit_type == PPS ||
72+ nal_unit_type == SEI || NALisSlice(nal_unit_type))
73+ {
74+ /* This is a NAL we need to parse. We may have the body
75+ * of it in the part of the stream past to us this call,
76+ * or we may get the rest in subsequent calls to addBytes.
77+ * Either way, we set have_unfinished_NAL, so that we
78+ * start filling the rbsp buffer */
79+ have_unfinished_NAL = true;
80+ }
81+ else if (nal_unit_type == AU_DELIMITER ||
82+ (nal_unit_type > SPS_EXT &&
83+ nal_unit_type < AUXILIARY_SLICE))
84+ {
85+ set_AU_pending();
86+ }
87 }
88- }
89+ else
90+ LOG(VB_GENERAL, LOG_ERR,
91+ "H264Parser::addbytes: malformed NAL units");
92+ } //found start code
93 }
94
95 return startP - bytes;
96@@ -523,6 +542,9 @@ void H264Parser::processRBSP(bool rbsp_complete)
97
98 set_AU_pending();
99
100+ if (!seen_sps)
101+ SPS_offset = pkt_offset;
102+
103 decode_SPS(&gb);
104 }
105 else if (nal_unit_type == PPS)
106@@ -576,6 +598,8 @@ void H264Parser::processRBSP(bool rbsp_complete)
107 */
108 bool H264Parser::decode_Header(GetBitContext *gb)
109 {
110+ uint first_mb_in_slice;
111+
112 is_keyframe = false;
113
114 if (log2_max_frame_num == 0 || pic_order_present_flag == -1)
115@@ -601,8 +625,7 @@ bool H264Parser::decode_Header(GetBitContext *gb)
116 that precedes the current slice in decoding order and has the
117 same value of colour_plane_id.
118 */
119- //uint first_mb_in_slice = get_ue_golomb(gb);
120- get_ue_golomb(gb); // Replaced above line
121+ first_mb_in_slice = get_ue_golomb_long(gb);
122
123 /*
124 slice_type specifies the coding type of the slice according to
125@@ -611,8 +634,10 @@ bool H264Parser::decode_Header(GetBitContext *gb)
126 When nal_unit_type is equal to 5 (IDR picture), slice_type shall
127 be equal to 2, 4, 7, or 9 (I or SI)
128 */
129- slice_type = get_ue_golomb(gb);
130+ slice_type = get_ue_golomb_31(gb);
131
132+ /* s->pict_type = golomb_to_pict_type[slice_type % 5];
133+ */
134 /*
135 pic_parameter_set_id specifies the picture parameter set in
136 use. The value of pic_parameter_set_id shall be in the range of
137@@ -642,6 +667,8 @@ bool H264Parser::decode_Header(GetBitContext *gb)
138 bitstream....
139
140 If the current picture is an IDR picture, frame_num shall be equal to 0.
141+
142+ When max_num_ref_frames is equal to 0, slice_type shall be equal to 2, 4, 7, or 9.
143 */
144
145 frame_num = get_bits(gb, log2_max_frame_num);
146@@ -683,9 +710,10 @@ bool H264Parser::decode_Header(GetBitContext *gb)
147 {
148 idr_pic_id = get_ue_golomb(gb);
149 is_keyframe = true;
150+ I_is_keyframe = true;
151 }
152 else
153- is_keyframe |= I_is_keyframe && isKeySlice(slice_type);
154+ is_keyframe = isKeySlice(slice_type);
155 /*
156 pic_order_cnt_lsb specifies the picture order count modulo
157 MaxPicOrderCntLsb for the top field of a coded frame or for a coded
158@@ -702,7 +730,7 @@ bool H264Parser::decode_Header(GetBitContext *gb)
159 {
160 pic_order_cnt_lsb = get_bits(gb, log2_max_pic_order_cnt_lsb);
161
162- if (pic_order_present_flag && !field_pic_flag)
163+ if ((pic_order_present_flag == 1) && !field_pic_flag)
164 delta_pic_order_cnt_bottom = get_se_golomb(gb);
165 else
166 delta_pic_order_cnt_bottom = 0;
167@@ -731,13 +759,17 @@ bool H264Parser::decode_Header(GetBitContext *gb)
168 {
169 delta_pic_order_cnt[0] = get_se_golomb(gb);
170
171- if (pic_order_present_flag && !field_pic_flag)
172+ if ((pic_order_present_flag == 1) && !field_pic_flag)
173 delta_pic_order_cnt[1] = get_se_golomb(gb);
174- else
175+ }
176+ else
177+ {
178+ if (pic_order_cnt_type == 1)
179+ {
180 delta_pic_order_cnt[1] = 0;
181- }
182- else
183- delta_pic_order_cnt[0] = 0;
184+ delta_pic_order_cnt[0] = 0;
185+ }
186+ }
187
188 /*
189 redundant_pic_cnt shall be equal to 0 for slices and slice data
190@@ -760,10 +792,13 @@ bool H264Parser::decode_Header(GetBitContext *gb)
191 void H264Parser::decode_SPS(GetBitContext * gb)
192 {
193 int profile_idc;
194+ int lastScale;
195+ int nextScale;
196+ int deltaScale;
197
198 seen_sps = true;
199
200- profile_idc = get_bits(gb, 8); // profile_idc
201+ profile_idc = get_bits(gb, 8);
202 get_bits1(gb); // constraint_set0_flag
203 get_bits1(gb); // constraint_set1_flag
204 get_bits1(gb); // constraint_set2_flag
205@@ -772,9 +807,11 @@ void H264Parser::decode_SPS(GetBitContext * gb)
206 get_bits(gb, 8); // level_idc
207 get_ue_golomb(gb); // sps_id
208
209- if (profile_idc >= 100)
210+ if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 ||
211+ profile_idc == 244 || profile_idc == 44 || profile_idc == 83 ||
212+ profile_idc == 86 || profile_idc == 118 || profile_idc == 128 )
213 { // high profile
214- if ((chroma_format_idc = get_ue_golomb(gb)) == 3) // chroma_format_idc
215+ if ((chroma_format_idc = get_ue_golomb(gb)) == 3)
216 separate_colour_plane_flag = (get_bits1(gb) == 1);
217
218 get_ue_golomb(gb); // bit_depth_luma_minus8
219@@ -785,12 +822,18 @@ void H264Parser::decode_SPS(GetBitContext * gb)
220 {
221 for (int idx = 0; idx < ((chroma_format_idc != 3) ? 8 : 12); ++idx)
222 {
223- if (get_bits1(gb)) // Scaling list presnent
224+ if (get_bits1(gb)) // Scaling list present
225 {
226+ lastScale = nextScale = 8;
227 int sl_n = ((idx < 6) ? 16 : 64);
228- for(int sl_i = 0; sl_i < sl_n; sl_i++)
229+ for(int sl_i = 0; sl_i < sl_n; ++sl_i)
230 {
231- get_se_golomb(gb);
232+ if (nextScale != 0)
233+ {
234+ deltaScale = get_se_golomb(gb);
235+ nextScale = (lastScale + deltaScale + 256) % 256;
236+ }
237+ lastScale = (nextScale == 0) ? lastScale : nextScale;
238 }
239 }
240 }
241@@ -809,6 +852,7 @@ void H264Parser::decode_SPS(GetBitContext * gb)
242 int offset_for_non_ref_pic;
243 int offset_for_top_to_bottom_field;
244 uint tmp;
245+ bool gaps_in_frame_num_allowed_flag;
246
247 /*
248 pic_order_cnt_type specifies the method to decode picture order
249@@ -886,8 +930,7 @@ void H264Parser::decode_SPS(GetBitContext * gb)
250 decoding process in case of an inferred gap between values of
251 frame_num as specified in subclause 8.2.5.2.
252 */
253- //bool gaps_in_frame_num_allowed_flag = get_bits1(gb);
254- get_bits1(gb); // Replaced above line
255+ gaps_in_frame_num_allowed_flag = get_bits1(gb);
256
257 /*
258 pic_width_in_mbs_minus1 plus 1 specifies the width of each
259@@ -1040,20 +1083,28 @@ void H264Parser::decode_SEI(GetBitContext *gb)
260 bool broken_link_flag = false;
261 int changing_group_slice_idc = -1;
262
263- int type = 0, size = 0;
264+ int type = 0, size = 0, tmp_byte = 0;
265
266 /* A message requires at least 2 bytes, and then
267 * there's the stop bit plus alignment, so there
268 * can be no message in less than 24 bits */
269 while (get_bits_left(gb) >= 24)
270 {
271- do {
272- type += show_bits(gb, 8);
273- } while (get_bits(gb, 8) == 255);
274+ tmp_byte = get_bits(gb, 8);
275+ while (tmp_byte == 255)
276+ {
277+ type += 255;
278+ tmp_byte = get_bits(gb, 8);
279+ }
280+ type += get_bits(gb, 8); //last_payload_type_byte
281
282- do {
283- size += show_bits(gb, 8);
284- } while (get_bits(gb, 8) == 255);
285+ tmp_byte = get_bits(gb, 8);
286+ while (tmp_byte == 255)
287+ {
288+ size += 255;
289+ tmp_byte = get_bits(gb, 8);
290+ }
291+ size += get_bits(gb, 8); //last_payload_size_byte
292
293 switch (type)
294 {
295@@ -1063,6 +1114,8 @@ void H264Parser::decode_SEI(GetBitContext *gb)
296 broken_link_flag = get_bits1(gb);
297 changing_group_slice_idc = get_bits(gb, 2);
298 au_contains_keyframe_message = (recovery_frame_cnt == 0);
299+ if ((size - 12) > 0)
300+ skip_bits(gb, (size - 12) * 8);
301 return;
302
303 default:
304diff --git a/mythtv/libs/libmythtv/mpeg/H264Parser.h b/mythtv/libs/libmythtv/mpeg/H264Parser.h
305index 9c984e0..7b750f2 100644
306--- a/mythtv/libs/libmythtv/mpeg/H264Parser.h
307+++ b/mythtv/libs/libmythtv/mpeg/H264Parser.h
308@@ -60,7 +60,7 @@ class H264Parser {
309 // ITU-T Rec. H.264 table 7-1
310 enum NAL_unit_type {
311 UNKNOWN = 0,
312- SLICE = 1,
313+ SLICE = 1, // 1 - 5 are VCL NAL units
314 SLICE_DPA = 2,
315 SLICE_DPB = 3,
316 SLICE_DPC = 4,
317@@ -73,11 +73,15 @@ class H264Parser {
318 END_STREAM = 11,
319 FILLER_DATA = 12,
320 SPS_EXT = 13,
321- AUXILIARY_SLICE = 19
322+ NALU_prefix = 14,
323+ SPS_subset = 15,
324+ AUXILIARY_SLICE = 19,
325+ SLICE_EXTENSION = 20
326 };
327
328 enum SEI_type {
329 SEI_TYPE_PIC_TIMING = 1,
330+ SEI_FILLER_PAYLOAD = 3,
331 SEI_TYPE_USER_DATA_UNREGISTERED = 5,
332 SEI_TYPE_RECOVERY_POINT = 6
333 };
334@@ -147,7 +151,9 @@ class H264Parser {
335
336 uint64_t frameAUstreamOffset(void) const {return frame_start_offset;}
337 uint64_t keyframeAUstreamOffset(void) const {return keyframe_start_offset;}
338+ uint64_t SPSstreamOffset(void) const {return SPS_offset;}
339
340+// == NAL_type AU_delimiter: primary_pic_type = 5
341 static int isKeySlice(uint slice_type)
342 {
343 return (slice_type == SLICE_I ||
344@@ -164,6 +170,7 @@ class H264Parser {
345 }
346
347 void use_I_forKeyframes(bool val) { I_is_keyframe = val; }
348+ bool using_I_forKeyframes(void) const { return I_is_keyframe; }
349
350 uint32_t GetTimeScale(void) const { return timeScale; }
351
352@@ -172,6 +179,10 @@ class H264Parser {
353 void parse_SPS(uint8_t *sps, uint32_t sps_size,
354 bool& interlaced, int32_t& max_ref_frames);
355
356+ bool seen_SPS(void) const { return seen_sps; }
357+
358+ bool found_AU(void) const { return AU_pending; }
359+
360 private:
361 enum constants {EXTENDED_SAR = 255};
362
363@@ -247,6 +258,7 @@ class H264Parser {
364 bool fixedRate;
365
366 uint64_t pkt_offset, AU_offset, frame_start_offset, keyframe_start_offset;
367+ uint64_t SPS_offset;
368 bool on_frame, on_key_frame;
369 };
370
371diff --git a/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp b/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp
372index e25774d..2cd7efc 100644
373--- a/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp
374+++ b/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp
375@@ -38,6 +38,18 @@ extern "C" {
376
377 const uint DTVRecorder::kMaxKeyFrameDistance = 80;
378
379+const uint seen_kf_limit = 4; // hdpvr kf at 2sec/120frames
380+
381 /** \class DTVRecorder
382 * \brief This is a specialization of RecorderBase used to
383 * handle MPEG-2, MPEG-4, MPEG-4 AVC, DVB and ATSC streams.
384@@ -55,16 +67,17 @@ DTVRecorder::DTVRecorder(TVRec *rec) :
385 _start_code(0xffffffff), _first_keyframe(-1),
386 _last_gop_seen(0), _last_seq_seen(0),
387 _last_keyframe_seen(0),
388 _audio_bytes_remaining(0), _video_bytes_remaining(0),
389 _other_bytes_remaining(0),
390+ _skip_bytes_remaining(0),
391 // MPEG2 parser information
392 _progressive_sequence(0),
393 _repeat_pict(0),
394 // H.264 support
395 _pes_synced(false),
396 _seen_sps(false),
397+ _seen_kf_count(0),
398 // settings
399- _wait_for_keyframe_option(true),
400+ _wait_for_keyframe_option(true), // is wait_for_SPS for H264
401 _has_written_other_keyframe(false),
402 // state
403 _error(),
404@@ -171,7 +184,7 @@ void DTVRecorder::ResetForNewFile(void)
405 LOG(VB_RECORD, LOG_INFO, LOC + "ResetForNewFile(void)");
406 QMutexLocker locker(&positionMapLock);
407
408- // _seen_psp and m_h264_parser should
409+ // _seen_sps and m_h264_parser should
410 // not be reset here. This will only be called just as
411 // we're seeing the first packet of a new keyframe for
412 // writing to the new file and anything that makes the
413@@ -179,15 +192,12 @@ void DTVRecorder::ResetForNewFile(void)
414 // send significant amounts of good data to /dev/null.
415 // -- Daniel Kristjansson 2011-02-26
416
417- _start_code = 0xffffffff;
418 _first_keyframe = -1;
419 _has_written_other_keyframe = false;
420 _last_keyframe_seen = 0;
421 _last_gop_seen = 0;
422 _last_seq_seen = 0;
423 _audio_bytes_remaining = 0;
424 _video_bytes_remaining = 0;
425 _other_bytes_remaining = 0;
426+ _skip_bytes_remaining = 0;
427 //_recording
428 _error = QString();
429
430@@ -195,7 +205,9 @@ void DTVRecorder::ResetForNewFile(void)
431 _repeat_pict = 0;
432
433 //_pes_synced
434- //_seen_sps
435+ _seen_sps = false;
436+ _seen_seq = false;
437+
438 positionMap.clear();
439 positionMapDelta.clear();
440 durationMap.clear();
441@@ -231,8 +243,6 @@ void DTVRecorder::Reset(void)
442 LOG(VB_RECORD, LOG_INFO, LOC + "Reset(void)");
443 ResetForNewFile();
444
445- _start_code = 0xffffffff;
446-
447 if (curRecording)
448 {
449 curRecording->ClearPositionMap(MARK_GOP_BYFRAME);
450@@ -276,9 +286,8 @@ void DTVRecorder::BufferedWrite(const TSPacket &tspacket, bool insert)
451 {
452 if (!insert) // PAT/PMT may need inserted in front of any buffered data
453 {
454- // delay until first GOP to avoid decoder crash on res change
455- if (!_buffer_packets && _wait_for_keyframe_option &&
456- _first_keyframe < 0)
457+ // delay until first SPS/GOP to avoid decoder crash on res change
458+ if (!_buffer_packets && !_seen_sps)
459 return;
460
461 if (curRecording && timeOfFirstDataIsSet.testAndSetRelaxed(0,1))
462@@ -419,16 +428,20 @@ bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket)
463 // looking for first byte of MPEG start code (3 bytes 0 0 1)
464 // otherwise, pick up search where we left off.
465 const bool payloadStart = tspacket->PayloadStart();
466- _start_code = (payloadStart) ? 0xffffffff : _start_code;
467+ if (payloadStart)
468+ {
469+ _seen_sps = false;
470+ if (!_wait_for_keyframe_option)
471+ _seen_sps = true;
472+ }
473
474 // Just make these local for efficiency reasons (gcc not so smart..)
475 const uint maxKFD = kMaxKeyFrameDistance;
476
477 void DTVRecorder::HandleTimestamps(int stream_id, int64_t pts, int64_t dts)
478@@ -718,6 +788,7 @@ bool DTVRecorder::FindAudioKeyframes(const TSPacket*)
479 _audio_timer.start();
480
481 _buffer_packets = false;
482+ _seen_sps = true; // unblock BufferedWrite()
483 _frames_seen_count++;
484
485 if (1 == (_frames_seen_count & 0x7))
486@@ -815,6 +886,7 @@ bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
487 // reset PES sync state
488 _pes_synced = false;
489 _start_code = 0xffffffff;
490+ _seen_sps = false;
491 }
492
493 uint aspectRatio = 0;
494@@ -898,30 +970,49 @@ bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
495 uint32_t bytes_used = m_h264_parser.addBytes
496 (tspacket->data() + i, TSPacket::kSize - i,
497 ringBuffer->GetWritePosition());
498- i += (bytes_used - 1);
499
500- if (m_h264_parser.stateChanged())
501+ // 3 states:
502+ // no SPS & no keyframes seen -> clear buffer
503+ // no SPS & keyframes seen -> count keyframes, don't clear buffer
504+ // if (keyframe count >= limit) then set seen_SPS
505+ // SPS seen -> don't clear buffer, buffer_pkts false (write to file)
506+ if (!_seen_sps)
507+ {
508+ if(!_wait_for_keyframe_option || m_h264_parser.seen_SPS())
509+ _seen_sps = true;
510+ if (m_h264_parser.onKeyFrameStart())
511+ ++_seen_kf_count;
512+ if (_seen_kf_count >= seen_kf_limit)
513+ _seen_sps = true;
514+ }
515+ if (m_h264_parser.stateChanged() && _seen_sps)
516 {
517 if (m_h264_parser.onFrameStart() &&
518 m_h264_parser.FieldType() != H264Parser::FIELD_BOTTOM)
519 {
520 hasKeyFrame = m_h264_parser.onKeyFrameStart();
521 hasFrame = true;
522- _seen_sps |= hasKeyFrame;
523-
524 width = m_h264_parser.pictureWidth();
525 height = m_h264_parser.pictureHeight();
526 aspectRatio = m_h264_parser.aspectRatio();
527 m_h264_parser.getFrameRate(frameRate);
528 }
529 }
530+
531+ i += (bytes_used - 1);
532 } // for (; i < TSPacket::kSize; ++i)
533
534 // _buffer_packets will only be true if a payload start has been seen
535- if (hasKeyFrame && (_buffer_packets || _first_keyframe >= 0))
536+ if (_seen_sps)
537+ _buffer_packets = false;
538+ else
539+ if (_seen_kf_count < seen_kf_limit)
540+ _payload_buffer.clear();
541+
542+ if (hasKeyFrame)
543 {
544 LOG(VB_RECORD, LOG_DEBUG, LOC + QString
545- ("Keyframe @ %1 + %2 = %3 AU %4")
546+ ("H264Keyframe @ %1 + %2 = %3 AU %4")
547 .arg(ringBuffer->GetWritePosition())
548 .arg(_payload_buffer.size())
549 .arg(ringBuffer->GetWritePosition() + _payload_buffer.size())
550@@ -934,22 +1025,15 @@ bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
551 if (hasFrame)
552 {
553 LOG(VB_RECORD, LOG_DEBUG, LOC + QString
554- ("Frame @ %1 + %2 = %3 AU %4")
555+ ("H264Frame @ %1 + %2 = %3 AU %4")
556 .arg(ringBuffer->GetWritePosition())
557 .arg(_payload_buffer.size())
558 .arg(ringBuffer->GetWritePosition() + _payload_buffer.size())
559- .arg(m_h264_parser.keyframeAUstreamOffset()));
560+ .arg(m_h264_parser.frameAUstreamOffset()));
561
562- _buffer_packets = false; // We now know if this is a keyframe
563 _frames_seen_count++;
564- if (!_wait_for_keyframe_option || _first_keyframe >= 0)
565+ if (_first_keyframe >= 0)
566 UpdateFramesWritten();
567- else
568- {
569- /* Found a frame that is not a keyframe, and we want to
570- * start on a keyframe */
571- _payload_buffer.clear();
572- }
573 }
574
575 if ((aspectRatio > 0) && (aspectRatio != m_videoAspect))
576@@ -971,12 +1055,12 @@ bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
577 QString("FindH264Keyframes: timescale: %1, tick: %2, framerate: %3")
578 .arg( m_h264_parser.GetTimeScale() )
579 .arg( m_h264_parser.GetUnitsInTick() )
580- .arg( frameRate.toDouble() * 1000 ) );
581+ .arg( frameRate.toDouble() ) );
582 m_frameRate = frameRate;
583 FrameRateChange(frameRate.toDouble() * 1000, _frames_written_count);
584 }
585
586- return _seen_sps;
587+ return hasKeyFrame;
588 }
589
590 /** \fn DTVRecorder::HandleH264Keyframe(void)
591@@ -991,15 +1075,9 @@ void DTVRecorder::HandleH264Keyframe(void)
592 uint64_t startpos;
593 uint64_t frameNum = _frames_written_count;
594
595- if (_first_keyframe < 0)
596- {
597- _first_keyframe = frameNum;
598- startpos = 0;
599- }
600- else
601- startpos = m_h264_parser.keyframeAUstreamOffset();
602+ startpos = m_h264_parser.keyframeAUstreamOffset();
603
604- // Add key frame to position map
605+ // Add keyframe to position map
606 positionMapLock.lock();
607 if (!positionMap.contains(frameNum))
608 {
609@@ -1008,14 +1086,27 @@ void DTVRecorder::HandleH264Keyframe(void)
610 durationMap[frameNum] = _total_duration + 0.5;
611 durationMapDelta[frameNum] = _total_duration + 0.5;
612 }
613+ if ((_first_keyframe < 0) && !positionMap.contains(0))
614+ {
615+ positionMapDelta[0] = 0;
616+ positionMap[0] = 0;
617+ durationMap[0] = 0.5;
618+ durationMapDelta[0] = 0.5;
619+ }
620 positionMapLock.unlock();
621+
622+ if (_first_keyframe < 0)
623+ {
624+ _first_keyframe = frameNum;
625+ }
626 }
627
628
629 void DTVRecorder::HandlePAT(const ProgramAssociationTable *_pat)
630@@ -1328,6 +1523,7 @@ bool DTVRecorder::ProcessTSPacket(const TSPacket &tspacket)
631 if (_input_pmt && _has_no_av)
632 {
633 FindOtherKeyframes(&tspacket);
634+ _seen_sps = true; // unblock BufferedWrite()
635 _buffer_packets = false;
636 }
637 else
638@@ -1383,11 +1579,11 @@ bool DTVRecorder::ProcessAudioTSPacket(const TSPacket &tspacket)
639 return ProcessAVTSPacket(tspacket);
640 }
641
642-/// Common code for processing either audio or video packets
643+/// Common code for processing either audio or video packets (mpeg2 or h264)
644 bool DTVRecorder::ProcessAVTSPacket(const TSPacket &tspacket)
645 {
646- // Sync recording start to first keyframe
647- if (_wait_for_keyframe_option && _first_keyframe < 0)
648+ // Sync recording start to first SPS / keyframe
649+ if (!_seen_sps && _first_keyframe < 0)
650 {
651 if (_buffer_packets)
652 BufferedWrite(tspacket);
653diff --git a/mythtv/libs/libmythtv/recorders/dtvrecorder.h b/mythtv/libs/libmythtv/recorders/dtvrecorder.h
654index 51cbb0c..42d8735 100644
655--- a/mythtv/libs/libmythtv/recorders/dtvrecorder.h
656+++ b/mythtv/libs/libmythtv/recorders/dtvrecorder.h
657@@ -110,7 +110,7 @@ class DTVRecorder :
658 void HandleH264Keyframe(void);
659
660 // MPEG2 PS support (Hauppauge PVR-x50/PVR-500)
661 void FindPSKeyFrames(const uint8_t *buffer, uint len);
662
663 // For handling other (non audio/video) packets
664 bool FindOtherKeyframes(const TSPacket *tspacket);
665@@ -136,6 +136,11 @@ class DTVRecorder :
666 unsigned int _audio_bytes_remaining;
667 unsigned int _video_bytes_remaining;
668 unsigned int _other_bytes_remaining;
669+ int _skip_bytes_remaining;
670+
671+ // MPEGPS parser information
672+ bool _seen_seq;
673+ bool _next_frame_isKey;
674
675 // MPEG2 parser information
676 int _progressive_sequence;
677@@ -144,6 +149,7 @@ class DTVRecorder :
678 // H.264 support
679 bool _pes_synced;
680 bool _seen_sps;
681+ int _seen_kf_count;
682 H264Parser m_h264_parser;
683
684 /// Wait for the a GOP/SEQ-start before sending data
685