Ticket #11435: git_diff3.txt

File git_diff3.txt, 23.8 KB (added by blm-ubunet@…, 11 years ago)

git diff to master ; added some mpeg2 video changes etc

Line 
1diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp
2index 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             {
14diff --git a/mythtv/libs/libmythtv/mpeg/H264Parser.cpp b/mythtv/libs/libmythtv/mpeg/H264Parser.cpp
15index 3e45c60..e761138 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,10 +792,13 @@ 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-    profile_idc = get_bits(gb, 8); // profile_idc
214+    profile_idc = get_bits(gb, 8);
215     get_bits1(gb);      // constraint_set0_flag
216     get_bits1(gb);      // constraint_set1_flag
217     get_bits1(gb);      // constraint_set2_flag
218@@ -772,9 +807,11 @@ void H264Parser::decode_SPS(GetBitContext * gb)
219     get_bits(gb, 8);    // level_idc
220     get_ue_golomb(gb);  // sps_id
221 
222-    if (profile_idc >= 100)
223+    if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 ||
224+        profile_idc == 244 || profile_idc == 44  || profile_idc == 83  ||
225+        profile_idc == 86  || profile_idc == 118 || profile_idc == 128 )
226     { // high profile
227-        if ((chroma_format_idc = get_ue_golomb(gb)) == 3) // chroma_format_idc
228+        if ((chroma_format_idc = get_ue_golomb(gb)) == 3)
229             separate_colour_plane_flag = (get_bits1(gb) == 1);
230 
231         get_ue_golomb(gb);     // bit_depth_luma_minus8
232@@ -785,12 +822,18 @@ void H264Parser::decode_SPS(GetBitContext * gb)
233         {
234             for (int idx = 0; idx < ((chroma_format_idc != 3) ? 8 : 12); ++idx)
235             {
236-                if (get_bits1(gb)) // Scaling list presnent
237+                if (get_bits1(gb)) // Scaling list present
238                 {
239+                    lastScale = nextScale = 8;
240                     int sl_n = ((idx < 6) ? 16 : 64);
241-                    for(int sl_i = 0; sl_i < sl_n; sl_i++)
242+                    for(int sl_i = 0; sl_i < sl_n; ++sl_i)
243                     {
244-                        get_se_golomb(gb);
245+                        if (nextScale != 0)
246+                        {
247+                            deltaScale = get_se_golomb(gb);
248+                            nextScale = (lastScale + deltaScale + 256) % 256;
249+                        }
250+                        lastScale = (nextScale == 0) ? lastScale : nextScale;
251                     }
252                 }
253             }
254@@ -809,6 +852,7 @@ void H264Parser::decode_SPS(GetBitContext * gb)
255     int  offset_for_non_ref_pic;
256     int  offset_for_top_to_bottom_field;
257     uint tmp;
258+    bool gaps_in_frame_num_allowed_flag;
259 
260     /*
261       pic_order_cnt_type specifies the method to decode picture order
262@@ -886,8 +930,7 @@ void H264Parser::decode_SPS(GetBitContext * gb)
263       decoding process in case of an inferred gap between values of
264       frame_num as specified in subclause 8.2.5.2.
265      */
266-    //bool gaps_in_frame_num_allowed_flag = get_bits1(gb);
267-    get_bits1(gb); // Replaced above line
268+    gaps_in_frame_num_allowed_flag = get_bits1(gb);
269 
270     /*
271       pic_width_in_mbs_minus1 plus 1 specifies the width of each
272@@ -1040,20 +1083,28 @@ void H264Parser::decode_SEI(GetBitContext *gb)
273     bool  broken_link_flag = false;
274     int   changing_group_slice_idc = -1;
275 
276-    int type = 0, size = 0;
277+    int type = 0, size = 0, tmp_byte = 0;
278 
279     /* A message requires at least 2 bytes, and then
280      * there's the stop bit plus alignment, so there
281      * can be no message in less than 24 bits */
282     while (get_bits_left(gb) >= 24)
283     {
284-        do {
285-            type += show_bits(gb, 8);
286-        } while (get_bits(gb, 8) == 255);
287+        tmp_byte = get_bits(gb, 8);
288+        while (tmp_byte == 255)
289+        {
290+            type += 255;
291+            tmp_byte = get_bits(gb, 8);
292+        }
293+        type += get_bits(gb, 8);   //last_payload_type_byte
294 
295-        do {
296-            size += show_bits(gb, 8);
297-        } while (get_bits(gb, 8) == 255);
298+        tmp_byte = get_bits(gb, 8);
299+        while (tmp_byte == 255)
300+        {
301+            size += 255;
302+            tmp_byte = get_bits(gb, 8);
303+        }
304+        size += get_bits(gb, 8);   //last_payload_size_byte
305 
306         switch (type)
307         {
308@@ -1063,6 +1114,8 @@ void H264Parser::decode_SEI(GetBitContext *gb)
309                 broken_link_flag = get_bits1(gb);
310                 changing_group_slice_idc = get_bits(gb, 2);
311                 au_contains_keyframe_message = (recovery_frame_cnt == 0);
312+                if ((size - 12) > 0)
313+                    skip_bits(gb, (size - 12) * 8);
314                 return;
315 
316             default:
317diff --git a/mythtv/libs/libmythtv/mpeg/H264Parser.h b/mythtv/libs/libmythtv/mpeg/H264Parser.h
318index 9c984e0..7b750f2 100644
319--- a/mythtv/libs/libmythtv/mpeg/H264Parser.h
320+++ b/mythtv/libs/libmythtv/mpeg/H264Parser.h
321@@ -60,7 +60,7 @@ class H264Parser {
322     // ITU-T Rec. H.264 table 7-1
323     enum NAL_unit_type {
324         UNKNOWN         = 0,
325-        SLICE           = 1,
326+        SLICE           = 1,   // 1 - 5 are VCL NAL units
327         SLICE_DPA       = 2,
328         SLICE_DPB       = 3,
329         SLICE_DPC       = 4,
330@@ -73,11 +73,15 @@ class H264Parser {
331         END_STREAM      = 11,
332         FILLER_DATA     = 12,
333         SPS_EXT         = 13,
334-        AUXILIARY_SLICE = 19
335+        NALU_prefix     = 14,
336+        SPS_subset      = 15,
337+        AUXILIARY_SLICE = 19,
338+        SLICE_EXTENSION = 20
339     };
340 
341     enum SEI_type {
342         SEI_TYPE_PIC_TIMING             = 1,
343+        SEI_FILLER_PAYLOAD              = 3,
344         SEI_TYPE_USER_DATA_UNREGISTERED = 5,
345         SEI_TYPE_RECOVERY_POINT         = 6
346     };
347@@ -147,7 +151,9 @@ class H264Parser {
348 
349     uint64_t frameAUstreamOffset(void) const {return frame_start_offset;}
350     uint64_t keyframeAUstreamOffset(void) const {return keyframe_start_offset;}
351+    uint64_t SPSstreamOffset(void) const {return SPS_offset;}
352 
353+// == NAL_type AU_delimiter: primary_pic_type = 5
354     static int isKeySlice(uint slice_type)
355         {
356             return (slice_type == SLICE_I   ||
357@@ -164,6 +170,7 @@ class H264Parser {
358         }
359 
360     void use_I_forKeyframes(bool val) { I_is_keyframe = val; }
361+    bool using_I_forKeyframes(void) const { return I_is_keyframe; }
362 
363     uint32_t GetTimeScale(void) const { return timeScale; }
364 
365@@ -172,6 +179,10 @@ class H264Parser {
366     void parse_SPS(uint8_t *sps, uint32_t sps_size,
367                    bool& interlaced, int32_t& max_ref_frames);
368 
369+    bool seen_SPS(void) const { return seen_sps; }
370+
371+    bool found_AU(void) const { return AU_pending; }
372+
373   private:
374     enum constants {EXTENDED_SAR = 255};
375 
376@@ -247,6 +258,7 @@ class H264Parser {
377     bool       fixedRate;
378 
379     uint64_t   pkt_offset, AU_offset, frame_start_offset, keyframe_start_offset;
380+    uint64_t   SPS_offset;
381     bool       on_frame, on_key_frame;
382 };
383 
384diff --git a/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp b/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp
385index e25774d..21707ce 100644
386--- a/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp
387+++ b/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp
388@@ -64,7 +64,7 @@ DTVRecorder::DTVRecorder(TVRec *rec) :
389     _pes_synced(false),
390     _seen_sps(false),
391     // settings
392-    _wait_for_keyframe_option(true),
393+    _wait_for_keyframe_option(true),   // is wait_for_SPS for H264
394     _has_written_other_keyframe(false),
395     // state
396     _error(),
397@@ -195,7 +195,7 @@ void DTVRecorder::ResetForNewFile(void)
398     _repeat_pict                = 0;
399 
400     //_pes_synced
401-    //_seen_sps
402+    _seen_sps                   = false;
403     positionMap.clear();
404     positionMapDelta.clear();
405     durationMap.clear();
406@@ -276,9 +276,8 @@ void DTVRecorder::BufferedWrite(const TSPacket &tspacket, bool insert)
407 {
408     if (!insert) // PAT/PMT may need inserted in front of any buffered data
409     {
410-        // delay until first GOP to avoid decoder crash on res change
411-        if (!_buffer_packets && _wait_for_keyframe_option &&
412-            _first_keyframe < 0)
413+        // delay until first SPS/GOP to avoid decoder crash on res change
414+        if (!_buffer_packets && _wait_for_keyframe_option && !_seen_sps)
415             return;
416 
417         if (curRecording && timeOfFirstDataIsSet.testAndSetRelaxed(0,1))
418@@ -461,6 +460,7 @@ bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket)
419             }
420             else if (PESStreamID::SequenceStartCode == stream_id)
421             {
422+                _seen_sps = true; // for mpeg2vid ==SeqStartHeader
423                 _last_seq_seen  = _frames_seen_count;
424                 hasKeyFrame    |= (_last_gop_seen + maxKFD)<_frames_seen_count;
425 
426@@ -532,6 +532,12 @@ bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket)
427         }
428     }
429 
430+    // _buffer_packets will only be true if a payload start has been seen
431+    if (_seen_sps || !_wait_for_keyframe_option)
432+        _buffer_packets = false;
433+    else
434+        _payload_buffer.clear();
435+
436     if (hasFrame && !hasKeyFrame)
437     {
438         // If we have seen kMaxKeyFrameDistance frames since the
439@@ -543,8 +549,7 @@ bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket)
440         hasKeyFrame &= (_last_seq_seen + maxKFD) < _frames_seen_count;
441     }
442 
443-    // _buffer_packets will only be true if a payload start has been seen
444-    if (hasKeyFrame && (_buffer_packets || _first_keyframe >= 0))
445+    if (hasKeyFrame)
446     {
447         LOG(VB_RECORD, LOG_DEBUG, LOC + QString
448             ("Keyframe @ %1 + %2 = %3")
449@@ -553,7 +558,7 @@ bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket)
450             .arg(ringBuffer->GetWritePosition() + _payload_buffer.size()));
451 
452         _last_keyframe_seen = _frames_seen_count;
453-        HandleKeyframe(0);
454+        HandleKeyframe(_payload_buffer.size());
455     }
456 
457     if (hasFrame)
458@@ -564,16 +569,9 @@ bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket)
459             .arg(_payload_buffer.size())
460             .arg(ringBuffer->GetWritePosition() + _payload_buffer.size()));
461 
462-        _buffer_packets = false;  // We now know if it is a keyframe, or not
463         _frames_seen_count++;
464-        if (!_wait_for_keyframe_option || _first_keyframe >= 0)
465+        if (_first_keyframe >= 0)
466             UpdateFramesWritten();
467-        else
468-        {
469-            /* Found a frame that is not a keyframe, and we want to
470-             * start on a keyframe */
471-            _payload_buffer.clear();
472-        }
473     }
474 
475     if ((aspectRatio > 0) && (aspectRatio != m_videoAspect))
476@@ -718,6 +716,7 @@ bool DTVRecorder::FindAudioKeyframes(const TSPacket*)
477             _audio_timer.start();
478 
479         _buffer_packets = false;
480+        _seen_sps = true;   // unblock BufferedWrite()
481         _frames_seen_count++;
482 
483         if (1 == (_frames_seen_count & 0x7))
484@@ -898,30 +897,38 @@ bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
485         uint32_t bytes_used = m_h264_parser.addBytes
486                               (tspacket->data() + i, TSPacket::kSize - i,
487                                ringBuffer->GetWritePosition());
488-        i += (bytes_used - 1);
489 
490-        if (m_h264_parser.stateChanged())
491+        if (!_seen_sps && m_h264_parser.seen_SPS())
492+            _seen_sps = true;
493+
494+        if (m_h264_parser.stateChanged() && _seen_sps)
495         {
496             if (m_h264_parser.onFrameStart() &&
497                 m_h264_parser.FieldType() != H264Parser::FIELD_BOTTOM)
498             {
499                 hasKeyFrame = m_h264_parser.onKeyFrameStart();
500                 hasFrame = true;
501-                _seen_sps |= hasKeyFrame;
502-
503+               
504                 width = m_h264_parser.pictureWidth();
505                 height = m_h264_parser.pictureHeight();
506                 aspectRatio = m_h264_parser.aspectRatio();
507                 m_h264_parser.getFrameRate(frameRate);
508             }
509         }
510+
511+        i += (bytes_used - 1);
512     } // for (; i < TSPacket::kSize; ++i)
513 
514     // _buffer_packets will only be true if a payload start has been seen
515-    if (hasKeyFrame && (_buffer_packets || _first_keyframe >= 0))
516+    if (_seen_sps || !_wait_for_keyframe_option)
517+        _buffer_packets = false;
518+    else
519+        _payload_buffer.clear();
520+
521+    if (hasKeyFrame)
522     {
523         LOG(VB_RECORD, LOG_DEBUG, LOC + QString
524-            ("Keyframe @ %1 + %2 = %3 AU %4")
525+            ("H264Keyframe @ %1 + %2 = %3 AU %4")
526             .arg(ringBuffer->GetWritePosition())
527             .arg(_payload_buffer.size())
528             .arg(ringBuffer->GetWritePosition() + _payload_buffer.size())
529@@ -934,22 +941,15 @@ bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
530     if (hasFrame)
531     {
532         LOG(VB_RECORD, LOG_DEBUG, LOC + QString
533-            ("Frame @ %1 + %2 = %3 AU %4")
534+            ("H264Frame @ %1 + %2 = %3 AU %4")
535             .arg(ringBuffer->GetWritePosition())
536             .arg(_payload_buffer.size())
537             .arg(ringBuffer->GetWritePosition() + _payload_buffer.size())
538-            .arg(m_h264_parser.keyframeAUstreamOffset()));
539+            .arg(m_h264_parser.frameAUstreamOffset()));
540 
541-        _buffer_packets = false;  // We now know if this is a keyframe
542         _frames_seen_count++;
543-        if (!_wait_for_keyframe_option || _first_keyframe >= 0)
544+        if (_first_keyframe >= 0)
545             UpdateFramesWritten();
546-        else
547-        {
548-            /* Found a frame that is not a keyframe, and we want to
549-             * start on a keyframe */
550-            _payload_buffer.clear();
551-        }
552     }
553 
554     if ((aspectRatio > 0) && (aspectRatio != m_videoAspect))
555@@ -971,12 +971,12 @@ bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
556             QString("FindH264Keyframes: timescale: %1, tick: %2, framerate: %3")
557                       .arg( m_h264_parser.GetTimeScale() )
558                       .arg( m_h264_parser.GetUnitsInTick() )
559-                      .arg( frameRate.toDouble() * 1000 ) );
560+                      .arg( frameRate.toDouble() ) );
561         m_frameRate = frameRate;
562         FrameRateChange(frameRate.toDouble() * 1000, _frames_written_count);
563     }
564 
565-    return _seen_sps;
566+    return hasKeyFrame;
567 }
568 
569 /** \fn DTVRecorder::HandleH264Keyframe(void)
570@@ -991,15 +991,9 @@ void DTVRecorder::HandleH264Keyframe(void)
571     uint64_t startpos;
572     uint64_t frameNum = _frames_written_count;
573 
574-    if (_first_keyframe < 0)
575-    {
576-        _first_keyframe = frameNum;
577-        startpos = 0;
578-    }
579-    else
580-        startpos = m_h264_parser.keyframeAUstreamOffset();
581+    startpos = m_h264_parser.keyframeAUstreamOffset();
582 
583-    // Add key frame to position map
584+    // Add keyframe to position map
585     positionMapLock.lock();
586     if (!positionMap.contains(frameNum))
587     {
588@@ -1008,7 +1002,19 @@ void DTVRecorder::HandleH264Keyframe(void)
589         durationMap[frameNum]      = _total_duration + 0.5;
590         durationMapDelta[frameNum] = _total_duration + 0.5;
591     }
592+    if ((_first_keyframe < 0) && !positionMap.contains(0))
593+    {
594+        positionMapDelta[0] = 0;
595+        positionMap[0]      = 0;
596+        durationMap[0]      = 0.5;
597+        durationMapDelta[0] = 0.5;
598+    }
599     positionMapLock.unlock();
600+
601+    if (_first_keyframe < 0)
602+    {
603+        _first_keyframe = frameNum;
604+    }
605 }
606 
607 void DTVRecorder::FindPSKeyFrames(const uint8_t *buffer, uint len)
608@@ -1074,6 +1080,7 @@ void DTVRecorder::FindPSKeyFrames(const uint8_t *buffer, uint len)
609             else if (PESStreamID::SequenceStartCode == stream_id)
610             { // pes_packet_length is meaningless
611                 pes_packet_length = -1;
612+                _seen_sps = true; // for mpeg2vid ==SeqStartHeader
613                 _last_seq_seen  = _frames_seen_count;
614                 hasKeyFrame    |= (_last_gop_seen + maxKFD)<_frames_seen_count;
615 
616@@ -1328,6 +1335,7 @@ bool DTVRecorder::ProcessTSPacket(const TSPacket &tspacket)
617     if (_input_pmt && _has_no_av)
618     {
619         FindOtherKeyframes(&tspacket);
620+        _seen_sps = true;   // unblock BufferedWrite()
621         _buffer_packets = false;
622     }
623     else
624@@ -1383,11 +1391,11 @@ bool DTVRecorder::ProcessAudioTSPacket(const TSPacket &tspacket)
625     return ProcessAVTSPacket(tspacket);
626 }
627 
628-/// Common code for processing either audio or video packets
629+/// Common code for processing either audio or video packets (mpeg2 or h264)
630 bool DTVRecorder::ProcessAVTSPacket(const TSPacket &tspacket)
631 {
632-    // Sync recording start to first keyframe
633-    if (_wait_for_keyframe_option && _first_keyframe < 0)
634+    // Sync recording start to first SPS / keyframe
635+    if (_wait_for_keyframe_option && !_seen_sps && _first_keyframe < 0)
636     {
637         if (_buffer_packets)
638             BufferedWrite(tspacket);