1 | Index: libs/libmythtv/NuppelVideoPlayer.cpp |
---|
2 | =================================================================== |
---|
3 | --- libs/libmythtv/NuppelVideoPlayer.cpp (revision 23844) |
---|
4 | +++ libs/libmythtv/NuppelVideoPlayer.cpp (working copy) |
---|
5 | @@ -26,8 +26,6 @@ |
---|
6 | #include <QKeyEvent> |
---|
7 | #include <QDir> |
---|
8 | |
---|
9 | -#define NEW_AVSYNC |
---|
10 | - |
---|
11 | // MythTV headers |
---|
12 | #include "mythconfig.h" |
---|
13 | #include "mythdbcon.h" |
---|
14 | @@ -957,9 +955,6 @@ |
---|
15 | m_double_framerate = false; |
---|
16 | m_double_process = false; |
---|
17 | |
---|
18 | - if (videosync) |
---|
19 | - videosync->SetFrameInterval(frame_interval, false); |
---|
20 | - |
---|
21 | if (osd) |
---|
22 | osd->SetFrameInterval(frame_interval); |
---|
23 | |
---|
24 | @@ -1036,7 +1031,6 @@ |
---|
25 | if (interlaced && !m_deint_possible) |
---|
26 | { |
---|
27 | m_scan = scan; |
---|
28 | - videosync->SetFrameInterval(frame_interval, false); |
---|
29 | return; |
---|
30 | } |
---|
31 | |
---|
32 | @@ -1052,9 +1046,7 @@ |
---|
33 | if (videoOutput->NeedsDoubleFramerate()) |
---|
34 | { |
---|
35 | m_double_framerate = true; |
---|
36 | - videosync->SetFrameInterval(frame_interval, true); |
---|
37 | - // Make sure video sync can double frame rate |
---|
38 | - m_can_double = videosync->UsesFieldInterval(); |
---|
39 | + m_can_double = (frame_interval / 2 > videosync->getRefreshInterval() * 0.995); |
---|
40 | if (!m_can_double) |
---|
41 | { |
---|
42 | VERBOSE(VB_IMPORTANT, "Video sync method can't support double " |
---|
43 | @@ -1071,7 +1063,6 @@ |
---|
44 | { |
---|
45 | m_double_process = false; |
---|
46 | m_double_framerate = false; |
---|
47 | - videosync->SetFrameInterval(frame_interval, false); |
---|
48 | videoOutput->SetDeinterlacingEnabled(false); |
---|
49 | VERBOSE(VB_PLAYBACK, "Disabled deinterlacing"); |
---|
50 | } |
---|
51 | @@ -2338,11 +2329,11 @@ |
---|
52 | void NuppelVideoPlayer::AVSync(void) |
---|
53 | { |
---|
54 | float diverge = 0.0f; |
---|
55 | + int frameDelay = m_double_framerate ? frame_interval / 2 : frame_interval; |
---|
56 | // attempt to reduce fps for standalone PIP |
---|
57 | if (player_ctx->IsPIP() && framesPlayed % 2) |
---|
58 | { |
---|
59 | - videosync->WaitForFrame(avsync_adjustment); |
---|
60 | - videosync->AdvanceTrigger(); |
---|
61 | + videosync->WaitForFrame(frameDelay + avsync_adjustment); |
---|
62 | if (!using_null_videoout) |
---|
63 | videoOutput->SetFramesPlayed(framesPlayed + 1); |
---|
64 | return; |
---|
65 | @@ -2354,6 +2345,7 @@ |
---|
66 | VERBOSE(VB_IMPORTANT, LOC_ERR + "AVSync: No video buffer"); |
---|
67 | return; |
---|
68 | } |
---|
69 | + |
---|
70 | if (videoOutput->IsErrored()) |
---|
71 | { |
---|
72 | VERBOSE(VB_IMPORTANT, LOC_ERR + "AVSync: " |
---|
73 | @@ -2376,10 +2368,8 @@ |
---|
74 | if (kScan_Detect == m_scan || kScan_Ignore == m_scan) |
---|
75 | ps = kScan_Progressive; |
---|
76 | |
---|
77 | - bool dropframe = false; |
---|
78 | if (diverge < -MAXDIVERGE) |
---|
79 | { |
---|
80 | - dropframe = true; |
---|
81 | // If video is way behind of audio, adjust for it... |
---|
82 | QString dbg = QString("Video is %1 frames behind audio (too slow), ") |
---|
83 | .arg(-diverge); |
---|
84 | @@ -2413,7 +2403,7 @@ |
---|
85 | |
---|
86 | VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, QString("AVSync waitforframe %1 %2") |
---|
87 | .arg(avsync_adjustment).arg(m_double_framerate)); |
---|
88 | - videosync->WaitForFrame(avsync_adjustment + repeat_delay); |
---|
89 | + videosync->WaitForFrame(frameDelay + avsync_adjustment + repeat_delay); |
---|
90 | VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, "AVSync show"); |
---|
91 | if (!resetvideo) |
---|
92 | videoOutput->Show(ps); |
---|
93 | @@ -2454,12 +2444,7 @@ |
---|
94 | videoOutput->PrepareFrame(buffer, ps); |
---|
95 | |
---|
96 | // Display the second field |
---|
97 | - videosync->AdvanceTrigger(); |
---|
98 | -#ifdef NEW_AVSYNC |
---|
99 | - videosync->WaitForFrame(avsync_adjustment); |
---|
100 | -#else |
---|
101 | - videosync->WaitForFrame(0); |
---|
102 | -#endif |
---|
103 | + videosync->WaitForFrame(frameDelay + avsync_adjustment); |
---|
104 | if (!resetvideo) |
---|
105 | { |
---|
106 | videoOutput->Show(ps); |
---|
107 | @@ -2474,7 +2459,7 @@ |
---|
108 | } |
---|
109 | else |
---|
110 | { |
---|
111 | - videosync->WaitForFrame(0); |
---|
112 | + videosync->WaitForFrame(frameDelay); |
---|
113 | } |
---|
114 | |
---|
115 | if (output_jmeter && output_jmeter->RecordCycleTime()) |
---|
116 | @@ -2485,8 +2470,6 @@ |
---|
117 | .arg(warpfactor).arg(warpfactor_avg)); |
---|
118 | } |
---|
119 | |
---|
120 | - if (!dropframe) |
---|
121 | - videosync->AdvanceTrigger(); |
---|
122 | avsync_adjustment = 0; |
---|
123 | |
---|
124 | if (diverge > MAXDIVERGE) |
---|
125 | @@ -2494,11 +2477,7 @@ |
---|
126 | // If audio is way behind of video, adjust for it... |
---|
127 | // by cutting the frame rate in half for the length of this frame |
---|
128 | |
---|
129 | -#ifdef NEW_AVSYNC |
---|
130 | avsync_adjustment = refreshrate; |
---|
131 | -#else |
---|
132 | - avsync_adjustment = frame_interval; |
---|
133 | -#endif |
---|
134 | lastsync = true; |
---|
135 | VERBOSE(VB_PLAYBACK, LOC + |
---|
136 | QString("Video is %1 frames ahead of audio,\n" |
---|
137 | @@ -2530,24 +2509,21 @@ |
---|
138 | prevtc = buffer->timecode; |
---|
139 | //cerr << delta << " "; |
---|
140 | |
---|
141 | + avsync_delay = (buffer->timecode - currentaudiotime) * 1000;//usec |
---|
142 | + // prevents major jitter when pts resets during dvd title |
---|
143 | + if (avsync_delay > 2000000 && player_ctx->buffer->isDVD()) |
---|
144 | + avsync_delay = 90000; |
---|
145 | + avsync_avg = (avsync_delay + (avsync_avg * 3)) / 4; |
---|
146 | + |
---|
147 | // If the timecode is off by a frame (dropped frame) wait to sync |
---|
148 | if (delta > (int) frame_interval / 1200 && |
---|
149 | delta < (int) frame_interval / 1000 * 3 && |
---|
150 | prevrp == 0) |
---|
151 | { |
---|
152 | - //cerr << "+ "; |
---|
153 | - videosync->AdvanceTrigger(); |
---|
154 | - if (m_double_framerate) |
---|
155 | - videosync->AdvanceTrigger(); |
---|
156 | + // wait an extra frame interval |
---|
157 | + avsync_adjustment = frame_interval; |
---|
158 | } |
---|
159 | - prevrp = buffer->repeat_pict; |
---|
160 | |
---|
161 | - avsync_delay = (buffer->timecode - currentaudiotime) * 1000;//usec |
---|
162 | - // prevents major jitter when pts resets during dvd title |
---|
163 | - if (avsync_delay > 2000000 && player_ctx->buffer->isDVD()) |
---|
164 | - avsync_delay = 90000; |
---|
165 | - avsync_avg = (avsync_delay + (avsync_avg * 3)) / 4; |
---|
166 | - |
---|
167 | /* If the audio time codes and video diverge, shift |
---|
168 | the video by one interlaced field (1/2 frame) */ |
---|
169 | if (!lastsync) |
---|
170 | @@ -2911,10 +2887,8 @@ |
---|
171 | // Make sure video sync can do it |
---|
172 | if (videosync != NULL && m_double_framerate) |
---|
173 | { |
---|
174 | - videosync->SetFrameInterval(frame_interval, m_double_framerate); |
---|
175 | - m_can_double = videosync->UsesFieldInterval(); |
---|
176 | - if (!m_can_double) |
---|
177 | - { |
---|
178 | + m_can_double = (frame_interval / 2 > videosync->getRefreshInterval() * 0.995); |
---|
179 | + if (! m_can_double) { |
---|
180 | VERBOSE(VB_IMPORTANT, "Video sync method can't support double " |
---|
181 | "framerate (refresh rate too low for bob deint)"); |
---|
182 | FallbackDeint(); |
---|
183 | @@ -4216,9 +4190,6 @@ |
---|
184 | (frame_interval>>1) : frame_interval); |
---|
185 | } |
---|
186 | |
---|
187 | - if (videosync != NULL) |
---|
188 | - videosync->SetFrameInterval(frame_interval, m_double_framerate); |
---|
189 | - |
---|
190 | VERBOSE(VB_PLAYBACK, LOC + "DoPause() -- setting paused"); |
---|
191 | paused = actuallypaused = true; |
---|
192 | decoderThreadPaused.wakeAll(); |
---|
193 | @@ -4295,7 +4266,6 @@ |
---|
194 | |
---|
195 | m_double_framerate = videoOutput->NeedsDoubleFramerate(); |
---|
196 | m_double_process = videoOutput->IsExtraProcessingRequired(); |
---|
197 | - videosync->SetFrameInterval(frame_interval, m_double_framerate); |
---|
198 | } |
---|
199 | |
---|
200 | if (osd) |
---|
201 | Index: libs/libmythtv/vsync.cpp |
---|
202 | =================================================================== |
---|
203 | --- libs/libmythtv/vsync.cpp (revision 23844) |
---|
204 | +++ libs/libmythtv/vsync.cpp (working copy) |
---|
205 | @@ -126,12 +126,6 @@ |
---|
206 | m_delay(-1) |
---|
207 | { |
---|
208 | bzero(&m_nexttrigger, sizeof(m_nexttrigger)); |
---|
209 | - |
---|
210 | - int tolerance = m_refresh_interval / 200; |
---|
211 | - if (m_interlaced && m_refresh_interval > ((m_frame_interval/2) + tolerance)) |
---|
212 | - m_interlaced = false; // can't display both fields at 2x rate |
---|
213 | - |
---|
214 | - //cout << "Frame interval: " << m_frame_interval << endl; |
---|
215 | } |
---|
216 | |
---|
217 | void VideoSync::Start(void) |
---|
218 | @@ -139,21 +133,6 @@ |
---|
219 | gettimeofday(&m_nexttrigger, NULL); // now |
---|
220 | } |
---|
221 | |
---|
222 | -/** \fn VideoSync::SetFrameInterval(int fr, bool intr) |
---|
223 | - * \brief Change frame interval and interlacing attributes |
---|
224 | - */ |
---|
225 | -void VideoSync::SetFrameInterval(int fr, bool intr) |
---|
226 | -{ |
---|
227 | - m_frame_interval = fr; |
---|
228 | - m_interlaced = intr; |
---|
229 | - int tolerance = m_refresh_interval / 200; |
---|
230 | - if (m_interlaced && m_refresh_interval > ((m_frame_interval/2) + tolerance)) |
---|
231 | - m_interlaced = false; // can't display both fields at 2x rate |
---|
232 | - |
---|
233 | - VERBOSE(VB_PLAYBACK, QString("Set video sync frame interval to %1") |
---|
234 | - .arg(m_frame_interval)); |
---|
235 | -} |
---|
236 | - |
---|
237 | void VideoSync::OffsetTimeval(struct timeval& tv, int offset) |
---|
238 | { |
---|
239 | tv.tv_usec += offset; |
---|
240 | @@ -169,21 +148,6 @@ |
---|
241 | } |
---|
242 | } |
---|
243 | |
---|
244 | -/** \fn VideoSync::UpdateNexttrigger() |
---|
245 | - * \brief Internal method to tells video synchronization method to use |
---|
246 | - * the next frame (or field, if interlaced) for CalcDelay() |
---|
247 | - * and WaitForFrame(). |
---|
248 | - */ |
---|
249 | -void VideoSync::UpdateNexttrigger() |
---|
250 | -{ |
---|
251 | - // Offset by frame interval -- if interlaced, only delay by half |
---|
252 | - // frame interval |
---|
253 | - if (m_interlaced) |
---|
254 | - OffsetTimeval(m_nexttrigger, m_frame_interval/2); |
---|
255 | - else |
---|
256 | - OffsetTimeval(m_nexttrigger, m_frame_interval); |
---|
257 | -} |
---|
258 | - |
---|
259 | /** \fn VideoSync::CalcDelay() |
---|
260 | * \brief Calculates the delay to the next frame. |
---|
261 | * |
---|
262 | @@ -370,12 +334,8 @@ |
---|
263 | //cerr << "Wait " << n << " intervals. Count " << blank.request.sequence; |
---|
264 | //cerr << " Delay " << m_delay << endl; |
---|
265 | } |
---|
266 | -} |
---|
267 | |
---|
268 | -void DRMVideoSync::AdvanceTrigger(void) |
---|
269 | -{ |
---|
270 | KeepPhase(); |
---|
271 | - UpdateNexttrigger(); |
---|
272 | } |
---|
273 | #endif /* !_WIN32 */ |
---|
274 | |
---|
275 | @@ -539,15 +499,7 @@ |
---|
276 | m_delay = CalcDelay(); |
---|
277 | } |
---|
278 | |
---|
279 | -#endif /* USING_OPENGL_VSYNC */ |
---|
280 | -} |
---|
281 | - |
---|
282 | -void OpenGLVideoSync::AdvanceTrigger(void) |
---|
283 | -{ |
---|
284 | -#ifdef USING_OPENGL_VSYNC |
---|
285 | - |
---|
286 | KeepPhase(); |
---|
287 | - UpdateNexttrigger(); |
---|
288 | #endif /* USING_OPENGL_VSYNC */ |
---|
289 | } |
---|
290 | #endif /* !_WIN32 */ |
---|
291 | @@ -610,11 +562,6 @@ |
---|
292 | usleep(m_delay); |
---|
293 | } |
---|
294 | } |
---|
295 | - |
---|
296 | -void RTCVideoSync::AdvanceTrigger(void) |
---|
297 | -{ |
---|
298 | - UpdateNexttrigger(); |
---|
299 | -} |
---|
300 | #endif /* __linux__ */ |
---|
301 | |
---|
302 | #ifdef USING_VDPAU |
---|
303 | @@ -650,11 +597,6 @@ |
---|
304 | vo->SetNextFrameDisplayTimeOffset(m_delay); |
---|
305 | } |
---|
306 | |
---|
307 | -void VDPAUVideoSync::AdvanceTrigger(void) |
---|
308 | -{ |
---|
309 | - UpdateNexttrigger(); |
---|
310 | -} |
---|
311 | - |
---|
312 | #endif |
---|
313 | |
---|
314 | BusyWaitVideoSync::BusyWaitVideoSync(VideoOutput *vo, |
---|
315 | @@ -705,11 +647,6 @@ |
---|
316 | } |
---|
317 | } |
---|
318 | |
---|
319 | -void BusyWaitVideoSync::AdvanceTrigger(void) |
---|
320 | -{ |
---|
321 | - UpdateNexttrigger(); |
---|
322 | -} |
---|
323 | - |
---|
324 | USleepVideoSync::USleepVideoSync(VideoOutput *vo, |
---|
325 | int fr, int ri, bool intl) : |
---|
326 | VideoSync(vo, fr, ri, intl) |
---|
327 | @@ -734,8 +671,3 @@ |
---|
328 | if (m_delay > 0) |
---|
329 | usleep(m_delay); |
---|
330 | } |
---|
331 | - |
---|
332 | -void USleepVideoSync::AdvanceTrigger(void) |
---|
333 | -{ |
---|
334 | - UpdateNexttrigger(); |
---|
335 | -} |
---|
336 | Index: libs/libmythtv/vsync.h |
---|
337 | =================================================================== |
---|
338 | --- libs/libmythtv/vsync.h (revision 23844) |
---|
339 | +++ libs/libmythtv/vsync.h (working copy) |
---|
340 | @@ -39,15 +39,9 @@ |
---|
341 | * The factory method BestMethod tries subclasses in roughly quality |
---|
342 | * order until one succeeds. |
---|
343 | * |
---|
344 | - * A/V sync methods may supply an additonal delay per frame. Other |
---|
345 | + * A/V sync methods may supply the nominal delay per frame. Other |
---|
346 | * than that, video timing is entirely up to these classes. When |
---|
347 | * WaitForFrame returns, it is time to show the frame. |
---|
348 | - * |
---|
349 | - * There is some basic support for interlaced video timing where the |
---|
350 | - * fields need to be displayed sequentially. Passing true for the |
---|
351 | - * interlaced flags for the constructors, BestMethod, and |
---|
352 | - * SetFrameInterval will cause us to wait for half the specified frame |
---|
353 | - * interval, if the refresh rate is sufficient to do so. |
---|
354 | */ |
---|
355 | class VideoSync |
---|
356 | // virtual base class |
---|
357 | @@ -80,17 +74,9 @@ |
---|
358 | */ |
---|
359 | virtual void WaitForFrame(int sync_delay) = 0; |
---|
360 | |
---|
361 | - /// \brief Use the next frame or field for CalcDelay(void) |
---|
362 | - /// and WaitForFrame(int). |
---|
363 | - virtual void AdvanceTrigger(void) = 0; |
---|
364 | + /// \brief Returns the (minimum) refresh interval of the output device. |
---|
365 | + int getRefreshInterval(void) const { return m_refresh_interval; } |
---|
366 | |
---|
367 | - void SetFrameInterval(int fi, bool interlaced); |
---|
368 | - |
---|
369 | - /// \brief Returns true AdvanceTrigger(void) advances a field at a time. |
---|
370 | - bool UsesFieldInterval(void) const { return m_interlaced; } |
---|
371 | - /// \brief Returns true AdvanceTrigger(void) advances a frame at a time. |
---|
372 | - bool UsesFrameInterval(void) const { return !m_interlaced; } |
---|
373 | - |
---|
374 | /** \brief Stops VSync; must be called from main thread. |
---|
375 | * |
---|
376 | * Start(void), WaitForFrame(void), and Stop(void) should |
---|
377 | @@ -105,7 +91,6 @@ |
---|
378 | bool interlaced); |
---|
379 | protected: |
---|
380 | static void OffsetTimeval(struct timeval& tv, int offset); |
---|
381 | - void UpdateNexttrigger(void); |
---|
382 | int CalcDelay(void); |
---|
383 | void KeepPhase(void); |
---|
384 | |
---|
385 | @@ -137,7 +122,6 @@ |
---|
386 | bool TryInit(void); |
---|
387 | void Start(void); |
---|
388 | void WaitForFrame(int sync_delay); |
---|
389 | - void AdvanceTrigger(void); |
---|
390 | |
---|
391 | private: |
---|
392 | int m_dri_fd; |
---|
393 | @@ -179,7 +163,6 @@ |
---|
394 | bool TryInit(void); |
---|
395 | void Start(void); |
---|
396 | void WaitForFrame(int sync_delay); |
---|
397 | - void AdvanceTrigger(void); |
---|
398 | |
---|
399 | private: |
---|
400 | OpenGLContext *m_context; |
---|
401 | @@ -208,7 +191,6 @@ |
---|
402 | QString getName(void) const { return QString("RTC"); } |
---|
403 | bool TryInit(void); |
---|
404 | void WaitForFrame(int sync_delay); |
---|
405 | - void AdvanceTrigger(void); |
---|
406 | |
---|
407 | private: |
---|
408 | int m_rtcfd; |
---|
409 | @@ -229,7 +211,6 @@ |
---|
410 | QString getName(void) const { return QString("VDPAU"); } |
---|
411 | bool TryInit(void); |
---|
412 | void WaitForFrame(int sync_delay); |
---|
413 | - void AdvanceTrigger(void); |
---|
414 | |
---|
415 | private: |
---|
416 | }; |
---|
417 | @@ -257,7 +238,6 @@ |
---|
418 | QString getName(void) const { return QString("USleep with busy wait"); } |
---|
419 | bool TryInit(void); |
---|
420 | void WaitForFrame(int sync_delay); |
---|
421 | - void AdvanceTrigger(void); |
---|
422 | |
---|
423 | private: |
---|
424 | int m_cheat; |
---|
425 | @@ -285,6 +265,5 @@ |
---|
426 | QString getName(void) const { return QString("USleep"); } |
---|
427 | bool TryInit(void); |
---|
428 | void WaitForFrame(int sync_delay); |
---|
429 | - void AdvanceTrigger(void); |
---|
430 | }; |
---|
431 | #endif /* VSYNC_H_INCLUDED */ |
---|