Ticket #7067: mythtv.2.patch
File mythtv.2.patch, 14.4 KB (added by , 14 years ago) |
---|
-
libs/libmythtv/vsync.cpp
126 126 m_delay(-1) 127 127 { 128 128 bzero(&m_nexttrigger, sizeof(m_nexttrigger)); 129 130 int tolerance = m_refresh_interval / 200;131 if (m_interlaced && m_refresh_interval > ((m_frame_interval/2) + tolerance))132 m_interlaced = false; // can't display both fields at 2x rate133 134 //cout << "Frame interval: " << m_frame_interval << endl;135 129 } 136 130 137 131 void VideoSync::Start(void) … … 139 133 gettimeofday(&m_nexttrigger, NULL); // now 140 134 } 141 135 142 /** \fn VideoSync::SetFrameInterval(int fr, bool intr)143 * \brief Change frame interval and interlacing attributes144 */145 void VideoSync::SetFrameInterval(int fr, bool intr)146 {147 m_frame_interval = fr;148 m_interlaced = intr;149 int tolerance = m_refresh_interval / 200;150 if (m_interlaced && m_refresh_interval > ((m_frame_interval/2) + tolerance))151 m_interlaced = false; // can't display both fields at 2x rate152 153 VERBOSE(VB_PLAYBACK, QString("Set video sync frame interval to %1")154 .arg(m_frame_interval));155 }156 157 136 void VideoSync::OffsetTimeval(struct timeval& tv, int offset) 158 137 { 159 138 tv.tv_usec += offset; … … 233 212 return ret_val; 234 213 } 235 214 236 /** \fn VideoSync::KeepPhase()237 * \brief Keep our nexttrigger from drifting too close to the exact retrace.238 *239 * If delay is near zero, some frames will be delay < 0 and others240 * delay > 0 which would cause continous rapid fire stuttering.241 * This method is only useful for those sync methods where WaitForFrame242 * targets hardware retrace rather than targeting nexttrigger.243 */244 void VideoSync::KeepPhase()245 {246 // cerr << m_delay << endl;247 if (m_delay < -(m_refresh_interval/2))248 OffsetTimeval(m_nexttrigger, 200);249 else if (m_delay > -500)250 OffsetTimeval(m_nexttrigger, -2000);251 }252 253 215 #ifndef _WIN32 254 216 #define DRM_VBLANK_RELATIVE 0x1; 255 217 … … 371 333 //cerr << " Delay " << m_delay << endl; 372 334 } 373 335 } 374 375 void DRMVideoSync::AdvanceTrigger(void)376 {377 KeepPhase();378 UpdateNexttrigger();379 }380 336 #endif /* !_WIN32 */ 381 337 382 338 #ifndef _WIN32 … … 541 497 542 498 #endif /* USING_OPENGL_VSYNC */ 543 499 } 544 545 void OpenGLVideoSync::AdvanceTrigger(void)546 {547 #ifdef USING_OPENGL_VSYNC548 549 KeepPhase();550 UpdateNexttrigger();551 #endif /* USING_OPENGL_VSYNC */552 }553 500 #endif /* !_WIN32 */ 554 501 555 502 #ifdef __linux__ … … 610 557 usleep(m_delay); 611 558 } 612 559 } 613 614 void RTCVideoSync::AdvanceTrigger(void)615 {616 UpdateNexttrigger();617 }618 560 #endif /* __linux__ */ 619 561 620 562 #ifdef USING_VDPAU … … 650 592 vo->SetNextFrameDisplayTimeOffset(m_delay); 651 593 } 652 594 653 void VDPAUVideoSync::AdvanceTrigger(void)654 {655 UpdateNexttrigger();656 }657 658 595 #endif 659 596 660 597 BusyWaitVideoSync::BusyWaitVideoSync(VideoOutput *vo, … … 705 642 } 706 643 } 707 644 708 void BusyWaitVideoSync::AdvanceTrigger(void)709 {710 UpdateNexttrigger();711 }712 713 645 USleepVideoSync::USleepVideoSync(VideoOutput *vo, 714 646 int fr, int ri, bool intl) : 715 647 VideoSync(vo, fr, ri, intl) … … 734 666 if (m_delay > 0) 735 667 usleep(m_delay); 736 668 } 737 738 void USleepVideoSync::AdvanceTrigger(void)739 {740 UpdateNexttrigger();741 } -
libs/libmythtv/NuppelVideoPlayer.cpp
26 26 #include <QKeyEvent> 27 27 #include <QDir> 28 28 29 #define NEW_AVSYNC30 31 29 // MythTV headers 32 30 #include "mythconfig.h" 33 31 #include "mythdbcon.h" … … 967 965 m_double_framerate = false; 968 966 m_double_process = false; 969 967 970 if (videosync)971 videosync->SetFrameInterval(frame_interval, false);972 973 968 if (osd) 974 969 osd->SetFrameInterval(frame_interval); 975 970 … … 1046 1041 if (interlaced && !m_deint_possible) 1047 1042 { 1048 1043 m_scan = scan; 1049 videosync->SetFrameInterval(frame_interval, false);1050 1044 return; 1051 1045 } 1052 1046 … … 1062 1056 if (videoOutput->NeedsDoubleFramerate()) 1063 1057 { 1064 1058 m_double_framerate = true; 1065 videosync->SetFrameInterval(frame_interval, true); 1066 // Make sure video sync can double frame rate 1067 m_can_double = videosync->UsesFieldInterval(); 1059 m_can_double = (frame_interval / 2 > videosync->getRefreshInterval() * 1.005); 1068 1060 if (!m_can_double) 1069 1061 { 1070 1062 VERBOSE(VB_IMPORTANT, "Video sync method can't support double " … … 1081 1073 { 1082 1074 m_double_process = false; 1083 1075 m_double_framerate = false; 1084 videosync->SetFrameInterval(frame_interval, false);1085 1076 videoOutput->SetDeinterlacingEnabled(false); 1086 1077 VERBOSE(VB_PLAYBACK, "Disabled deinterlacing"); 1087 1078 } … … 2371 2362 void NuppelVideoPlayer::AVSync(void) 2372 2363 { 2373 2364 float diverge = 0.0f; 2365 int frameDelay = m_double_framerate ? frame_interval / 2 : frame_interval; 2374 2366 // attempt to reduce fps for standalone PIP 2375 2367 if (player_ctx->IsPIP() && framesPlayed % 2) 2376 2368 { 2377 videosync->WaitForFrame(avsync_adjustment); 2378 videosync->AdvanceTrigger(); 2369 videosync->WaitForFrame(frameDelay + avsync_adjustment); 2379 2370 if (!using_null_videoout) 2380 2371 videoOutput->SetFramesPlayed(framesPlayed + 1); 2381 2372 return; … … 2387 2378 VERBOSE(VB_IMPORTANT, LOC_ERR + "AVSync: No video buffer"); 2388 2379 return; 2389 2380 } 2381 2390 2382 if (videoOutput->IsErrored()) 2391 2383 { 2392 2384 VERBOSE(VB_IMPORTANT, LOC_ERR + "AVSync: " … … 2409 2401 if (kScan_Detect == m_scan || kScan_Ignore == m_scan) 2410 2402 ps = kScan_Progressive; 2411 2403 2412 bool dropframe = false;2413 2404 if (diverge < -MAXDIVERGE) 2414 2405 { 2415 dropframe = true;2416 2406 // If video is way behind of audio, adjust for it... 2417 2407 QString dbg = QString("Video is %1 frames behind audio (too slow), ") 2418 2408 .arg(-diverge); … … 2446 2436 2447 2437 VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, QString("AVSync waitforframe %1 %2") 2448 2438 .arg(avsync_adjustment).arg(m_double_framerate)); 2449 videosync->WaitForFrame( avsync_adjustment + repeat_delay);2439 videosync->WaitForFrame(frameDelay + avsync_adjustment + repeat_delay); 2450 2440 VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, "AVSync show"); 2451 2441 if (!resetvideo) 2452 2442 videoOutput->Show(ps); … … 2487 2477 videoOutput->PrepareFrame(buffer, ps); 2488 2478 2489 2479 // Display the second field 2490 videosync->AdvanceTrigger(); 2491 #ifdef NEW_AVSYNC 2492 videosync->WaitForFrame(avsync_adjustment); 2493 #else 2494 videosync->WaitForFrame(0); 2495 #endif 2480 videosync->WaitForFrame(frameDelay + avsync_adjustment); 2496 2481 if (!resetvideo) 2497 2482 { 2498 2483 videoOutput->Show(ps); … … 2507 2492 } 2508 2493 else 2509 2494 { 2510 videosync->WaitForFrame( 0);2495 videosync->WaitForFrame(frameDelay); 2511 2496 } 2512 2497 2513 2498 if (output_jmeter && output_jmeter->RecordCycleTime()) … … 2518 2503 .arg(warpfactor).arg(warpfactor_avg)); 2519 2504 } 2520 2505 2521 if (!dropframe)2522 videosync->AdvanceTrigger();2523 2506 avsync_adjustment = 0; 2524 2507 2525 2508 if (diverge > MAXDIVERGE) … … 2527 2510 // If audio is way behind of video, adjust for it... 2528 2511 // by cutting the frame rate in half for the length of this frame 2529 2512 2530 #ifdef NEW_AVSYNC2531 2513 avsync_adjustment = refreshrate; 2532 #else2533 avsync_adjustment = frame_interval;2534 #endif2535 2514 lastsync = true; 2536 2515 VERBOSE(VB_PLAYBACK, LOC + 2537 2516 QString("Video is %1 frames ahead of audio,\n" … … 2563 2542 prevtc = buffer->timecode; 2564 2543 //cerr << delta << " "; 2565 2544 2545 avsync_delay = (buffer->timecode - currentaudiotime) * 1000;//usec 2546 // prevents major jitter when pts resets during dvd title 2547 if (avsync_delay > 2000000 && player_ctx->buffer->isDVD()) 2548 avsync_delay = 90000; 2549 avsync_avg = (avsync_delay + (avsync_avg * 3)) / 4; 2550 2566 2551 // If the timecode is off by a frame (dropped frame) wait to sync 2567 2552 if (delta > (int) frame_interval / 1200 && 2568 2553 delta < (int) frame_interval / 1000 * 3 && 2569 2554 prevrp == 0) 2570 2555 { 2571 //cerr << "+ "; 2572 videosync->AdvanceTrigger(); 2573 if (m_double_framerate) 2574 videosync->AdvanceTrigger(); 2556 // wait an extra frame interval 2557 avsync_adjustment = frame_interval; 2575 2558 } 2576 prevrp = buffer->repeat_pict; 2577 2578 avsync_delay = (buffer->timecode - currentaudiotime) * 1000;//usec 2579 // prevents major jitter when pts resets during dvd title 2580 if (avsync_delay > 2000000 && player_ctx->buffer->isDVD()) 2581 avsync_delay = 90000; 2582 avsync_avg = (avsync_delay + (avsync_avg * 3)) / 4; 2583 if (!usevideotimebase) 2559 else if (!usevideotimebase) 2584 2560 { 2585 /* If the audio time codes and video diverge, shift2586 the video by one interlaced field (1/2 frame)*/2561 /* Adjust by the smoothed divergence amount; 2562 * divide by two to soften the effect. */ 2587 2563 2588 if (!lastsync) 2589 { 2590 if (avsync_avg > frame_interval * 3 / 2) 2591 { 2592 avsync_adjustment = refreshrate; 2593 lastsync = true; 2594 } 2595 else if (avsync_avg < 0 - frame_interval * 3 / 2) 2596 { 2597 avsync_adjustment = -refreshrate; 2598 lastsync = true; 2599 } 2564 if (!lastsync) { 2565 avsync_adjustment = avsync_avg / 2; 2566 if (avsync_adjustment > frame_interval * 4) 2567 avsync_adjustment = frame_interval * 4; 2600 2568 } 2601 2569 else 2602 2570 lastsync = false; 2603 2571 } 2572 prevrp = buffer->repeat_pict; 2604 2573 } 2605 2574 else 2606 2575 { … … 2971 2940 // Make sure video sync can do it 2972 2941 if (videosync != NULL && m_double_framerate) 2973 2942 { 2974 videosync->SetFrameInterval(frame_interval, m_double_framerate); 2975 m_can_double = videosync->UsesFieldInterval(); 2976 if (!m_can_double) 2977 { 2943 m_can_double = (frame_interval / 2 > videosync->getRefreshInterval() * 1.005); 2944 if (! m_can_double) { 2978 2945 VERBOSE(VB_IMPORTANT, "Video sync method can't support double " 2979 2946 "framerate (refresh rate too low for bob deint)"); 2980 2947 FallbackDeint(); … … 4350 4317 (frame_interval>>1) : frame_interval); 4351 4318 } 4352 4319 4353 if (videosync != NULL)4354 videosync->SetFrameInterval(frame_interval, m_double_framerate);4355 4356 4320 VERBOSE(VB_PLAYBACK, LOC + "DoPause() -- setting paused"); 4357 4321 paused = actuallypaused = true; 4358 4322 decoderThreadPaused.wakeAll(); … … 4429 4393 4430 4394 m_double_framerate = videoOutput->NeedsDoubleFramerate(); 4431 4395 m_double_process = videoOutput->IsExtraProcessingRequired(); 4432 videosync->SetFrameInterval(frame_interval, m_double_framerate);4433 4396 } 4434 4397 4435 4398 if (osd) -
libs/libmythtv/vsync.h
39 39 * The factory method BestMethod tries subclasses in roughly quality 40 40 * order until one succeeds. 41 41 * 42 * A/V sync methods may supply an additonal delay per frame. Other42 * A/V sync methods may supply the nominal delay per frame. Other 43 43 * than that, video timing is entirely up to these classes. When 44 44 * WaitForFrame returns, it is time to show the frame. 45 *46 * There is some basic support for interlaced video timing where the47 * fields need to be displayed sequentially. Passing true for the48 * interlaced flags for the constructors, BestMethod, and49 * SetFrameInterval will cause us to wait for half the specified frame50 * interval, if the refresh rate is sufficient to do so.51 45 */ 52 46 class VideoSync 53 47 // virtual base class … … 80 74 */ 81 75 virtual void WaitForFrame(int sync_delay) = 0; 82 76 83 /// \brief Use the next frame or field for CalcDelay(void) 84 /// and WaitForFrame(int). 85 virtual void AdvanceTrigger(void) = 0; 86 87 void SetFrameInterval(int fi, bool interlaced); 88 89 /// \brief Returns true AdvanceTrigger(void) advances a field at a time. 90 bool UsesFieldInterval(void) const { return m_interlaced; } 91 /// \brief Returns true AdvanceTrigger(void) advances a frame at a time. 92 bool UsesFrameInterval(void) const { return !m_interlaced; } 77 /// \brief Returns the (minimum) refresh interval of the output device. 78 int getRefreshInterval(void) const { return m_refresh_interval; } 93 79 94 80 /** \brief Stops VSync; must be called from main thread. 95 81 * … … 107 93 static void OffsetTimeval(struct timeval& tv, int offset); 108 94 void UpdateNexttrigger(void); 109 95 int CalcDelay(void); 110 void KeepPhase(void);111 96 112 97 VideoOutput *m_video_output; 113 98 int m_frame_interval; // of video … … 137 122 bool TryInit(void); 138 123 void Start(void); 139 124 void WaitForFrame(int sync_delay); 140 void AdvanceTrigger(void);141 125 142 126 private: 143 127 int m_dri_fd; … … 179 163 bool TryInit(void); 180 164 void Start(void); 181 165 void WaitForFrame(int sync_delay); 182 void AdvanceTrigger(void);183 166 184 167 private: 185 168 OpenGLContext *m_context; … … 208 191 QString getName(void) const { return QString("RTC"); } 209 192 bool TryInit(void); 210 193 void WaitForFrame(int sync_delay); 211 void AdvanceTrigger(void);212 194 213 195 private: 214 196 int m_rtcfd; … … 229 211 QString getName(void) const { return QString("VDPAU"); } 230 212 bool TryInit(void); 231 213 void WaitForFrame(int sync_delay); 232 void AdvanceTrigger(void);233 214 234 215 private: 235 216 }; … … 257 238 QString getName(void) const { return QString("USleep with busy wait"); } 258 239 bool TryInit(void); 259 240 void WaitForFrame(int sync_delay); 260 void AdvanceTrigger(void);261 241 262 242 private: 263 243 int m_cheat; … … 285 265 QString getName(void) const { return QString("USleep"); } 286 266 bool TryInit(void); 287 267 void WaitForFrame(int sync_delay); 288 void AdvanceTrigger(void);289 268 }; 290 269 #endif /* VSYNC_H_INCLUDED */