Ticket #11435: diff-dtvrecorder.cpp.txt

File diff-dtvrecorder.cpp.txt, 7.4 KB (added by blm-ubunet@…, 11 years ago)

diff patch against git master (1 week ago) dtvrecorder.cpp

Line 
1--- /media/FreeAgent GoFlex Drive/src/mythtv/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp    2013-03-26 10:41:46.000000000 +1300
2+++ mythtv/mythtv/libs/libmythtv/dtvrecorder.cpp        2013-03-30 18:27:08.377633504 +1300
3@@ -62,11 +62,11 @@
4     _repeat_pict(0),
5     // H.264 support
6     _pes_synced(false),
7     _seen_sps(false),
8     // settings
9-    _wait_for_keyframe_option(true),
10+    _wait_for_keyframe_option(true),   // is wait_for_SPS for H264
11     _has_written_other_keyframe(false),
12     // state
13     _error(),
14     _stream_data(NULL),
15     // TS packet buffer
16@@ -274,13 +274,12 @@
17 
18 void DTVRecorder::BufferedWrite(const TSPacket &tspacket, bool insert)
19 {
20     if (!insert) // PAT/PMT may need inserted in front of any buffered data
21     {
22-        // delay until first GOP to avoid decoder crash on res change
23-        if (!_buffer_packets && _wait_for_keyframe_option &&
24-            _first_keyframe < 0)
25+        // delay until first SPS/GOP to avoid decoder crash on res change
26+        if (!_buffer_packets && _wait_for_keyframe_option && !_seen_sps)
27             return;
28 
29         if (curRecording && timeOfFirstDataIsSet.testAndSetRelaxed(0,1))
30         {
31             QMutexLocker locker(&statisticsLock);
32@@ -542,18 +541,19 @@
33         hasKeyFrame &= (_last_gop_seen + maxKFD) < _frames_seen_count;
34         hasKeyFrame &= (_last_seq_seen + maxKFD) < _frames_seen_count;
35     }
36 
37     // _buffer_packets will only be true if a payload start has been seen
38-    if (hasKeyFrame && _buffer_packets)
39+    if (hasKeyFrame && (_buffer_packets || _first_keyframe >= 0))
40     {
41         LOG(VB_RECORD, LOG_DEBUG, LOC + QString
42             ("Keyframe @ %1 + %2 = %3")
43             .arg(ringBuffer->GetWritePosition())
44             .arg(_payload_buffer.size())
45             .arg(ringBuffer->GetWritePosition() + _payload_buffer.size()));
46 
47+        _seen_sps = true; // used by H264 to signal start rec to file
48         _last_keyframe_seen = _frames_seen_count;
49         HandleKeyframe(0);
50     }
51 
52     if (hasFrame)
53@@ -896,34 +896,42 @@
54         // scan for a NAL unit start code
55 
56         uint32_t bytes_used = m_h264_parser.addBytes
57                               (tspacket->data() + i, TSPacket::kSize - i,
58                                ringBuffer->GetWritePosition());
59-        i += (bytes_used - 1);
60+       
61+        if (!_seen_sps && m_h264_parser.seen_SPS())
62+            _seen_sps = true;
63 
64-        if (m_h264_parser.stateChanged())
65+        if (m_h264_parser.stateChanged() && _seen_sps)
66         {
67             if (m_h264_parser.onFrameStart() &&
68                 m_h264_parser.FieldType() != H264Parser::FIELD_BOTTOM)
69             {
70                 hasKeyFrame = m_h264_parser.onKeyFrameStart();
71                 hasFrame = true;
72-                _seen_sps |= hasKeyFrame;
73-
74+               
75                 width = m_h264_parser.pictureWidth();
76                 height = m_h264_parser.pictureHeight();
77                 aspectRatio = m_h264_parser.aspectRatio();
78                 m_h264_parser.getFrameRate(frameRate);
79             }
80         }
81+
82+        i += (bytes_used - 1);
83     } // for (; i < TSPacket::kSize; ++i)
84 
85     // _buffer_packets will only be true if a payload start has been seen
86-    if (hasKeyFrame && _buffer_packets)
87+    if (_seen_sps)
88+        _buffer_packets = false;
89+    else
90+        _payload_buffer.clear();
91+
92+    if (hasKeyFrame)
93     {
94         LOG(VB_RECORD, LOG_DEBUG, LOC + QString
95-            ("Keyframe @ %1 + %2 = %3 AU %4")
96+            ("H264Keyframe @ %1 + %2 = %3 AU %4")
97             .arg(ringBuffer->GetWritePosition())
98             .arg(_payload_buffer.size())
99             .arg(ringBuffer->GetWritePosition() + _payload_buffer.size())
100             .arg(m_h264_parser.keyframeAUstreamOffset()));
101 
102@@ -932,26 +940,19 @@
103     }
104 
105     if (hasFrame)
106     {
107         LOG(VB_RECORD, LOG_DEBUG, LOC + QString
108-            ("Frame @ %1 + %2 = %3 AU %4")
109+            ("H264Frame @ %1 + %2 = %3 AU %4")
110             .arg(ringBuffer->GetWritePosition())
111             .arg(_payload_buffer.size())
112             .arg(ringBuffer->GetWritePosition() + _payload_buffer.size())
113-            .arg(m_h264_parser.keyframeAUstreamOffset()));
114+            .arg(m_h264_parser.frameAUstreamOffset()));
115 
116-        _buffer_packets = false;  // We now know if this is a keyframe
117         _frames_seen_count++;
118         if (!_wait_for_keyframe_option || _first_keyframe >= 0)
119             UpdateFramesWritten();
120-        else
121-        {
122-            /* Found a frame that is not a keyframe, and we want to
123-             * start on a keyframe */
124-            _payload_buffer.clear();
125-        }
126     }
127 
128     if ((aspectRatio > 0) && (aspectRatio != m_videoAspect))
129     {
130         m_videoAspect = aspectRatio;
131@@ -969,16 +970,16 @@
132     {
133         LOG(VB_RECORD, LOG_INFO, LOC +
134             QString("FindH264Keyframes: timescale: %1, tick: %2, framerate: %3")
135                       .arg( m_h264_parser.GetTimeScale() )
136                       .arg( m_h264_parser.GetUnitsInTick() )
137-                      .arg( frameRate.toDouble() * 1000 ) );
138+                      .arg( frameRate.toDouble() ) );
139         m_frameRate = frameRate;
140         FrameRateChange(frameRate.toDouble() * 1000, _frames_written_count);
141     }
142 
143-    return _seen_sps;
144+    return hasKeyFrame;
145 }
146 
147 /** \fn DTVRecorder::HandleH264Keyframe(void)
148  *  \brief This save the current frame to the position maps
149  *         and handles ringbuffer switching.
150@@ -989,28 +990,40 @@
151     CheckForRingBufferSwitch();
152 
153     uint64_t startpos;
154     uint64_t frameNum = _frames_written_count;
155 
156-    if (_first_keyframe < 0)
157-    {
158-        _first_keyframe = frameNum;
159-        startpos = 0;
160-    }
161-    else
162-        startpos = m_h264_parser.keyframeAUstreamOffset();
163+    startpos = m_h264_parser.keyframeAUstreamOffset();
164 
165-    // Add key frame to position map
166+    // Add keyframe to position map
167     positionMapLock.lock();
168     if (!positionMap.contains(frameNum))
169     {
170+//        LOG(VB_RECORD, LOG_DEBUG, LOC + QString
171+//            ("H264KeyFrame @ %1 tot_dur %2 AU %3")
172+//            .arg(frameNum)
173+//            .arg(_total_duration)
174+//            .arg(startpos) );
175+
176         positionMapDelta[frameNum] = startpos;
177         positionMap[frameNum]      = startpos;
178         durationMap[frameNum]      = _total_duration + 0.5;
179         durationMapDelta[frameNum] = _total_duration + 0.5;
180     }
181+    if ((_first_keyframe < 0) && !positionMap.contains(0))
182+    {
183+        positionMapDelta[0] = 0;
184+        positionMap[0]      = 0;
185+        durationMap[0]      = 0.5;
186+        durationMapDelta[0] = 0.5;
187+    }
188     positionMapLock.unlock();
189+
190+    if (_first_keyframe < 0)
191+    {
192+        _first_keyframe = frameNum;
193+    }
194 }
195 
196 void DTVRecorder::FindPSKeyFrames(const uint8_t *buffer, uint len)
197 {
198     const uint maxKFD = kMaxKeyFrameDistance;
199@@ -1381,15 +1394,15 @@
200 
201     FindAudioKeyframes(&tspacket);
202     return ProcessAVTSPacket(tspacket);
203 }
204 
205-/// Common code for processing either audio or video packets
206+/// Common code for processing either audio or video packets (mpeg2 or h264)
207 bool DTVRecorder::ProcessAVTSPacket(const TSPacket &tspacket)
208 {
209-    // Sync recording start to first keyframe
210-    if (_wait_for_keyframe_option && _first_keyframe < 0)
211+    // Sync recording start to first SPS/ keyframe
212+    if (_wait_for_keyframe_option && !_seen_sps && _first_keyframe < 0)
213     {
214         if (_buffer_packets)
215             BufferedWrite(tspacket);
216         return true;
217     }