| 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 */ |
|---|