Ticket #7067: mythtv.patch
File mythtv.patch, 13.9 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; … … 221 200 return ret_val; 222 201 } 223 202 224 /** \fn VideoSync::KeepPhase()225 * \brief Keep our nexttrigger from drifting too close to the exact retrace.226 *227 * If delay is near zero, some frames will be delay < 0 and others228 * delay > 0 which would cause continous rapid fire stuttering.229 * This method is only useful for those sync methods where WaitForFrame230 * targets hardware retrace rather than targeting nexttrigger.231 */232 void VideoSync::KeepPhase()233 {234 // cerr << m_delay << endl;235 if (m_delay < -(m_refresh_interval/2))236 OffsetTimeval(m_nexttrigger, 200);237 else if (m_delay > -500)238 OffsetTimeval(m_nexttrigger, -2000);239 }240 241 203 #ifndef _WIN32 242 204 #define DRM_VBLANK_RELATIVE 0x1; 243 205 … … 359 321 //cerr << " Delay " << m_delay << endl; 360 322 } 361 323 } 362 363 void DRMVideoSync::AdvanceTrigger(void)364 {365 KeepPhase();366 UpdateNexttrigger();367 }368 324 #endif /* !_WIN32 */ 369 325 370 326 #ifndef _WIN32 … … 529 485 530 486 #endif /* USING_OPENGL_VSYNC */ 531 487 } 532 533 void OpenGLVideoSync::AdvanceTrigger(void)534 {535 #ifdef USING_OPENGL_VSYNC536 537 KeepPhase();538 UpdateNexttrigger();539 #endif /* USING_OPENGL_VSYNC */540 }541 488 #endif /* !_WIN32 */ 542 489 543 490 #ifdef __linux__ … … 598 545 usleep(m_delay); 599 546 } 600 547 } 601 602 void RTCVideoSync::AdvanceTrigger(void)603 {604 UpdateNexttrigger();605 }606 548 #endif /* __linux__ */ 607 549 608 550 #ifdef USING_VDPAU … … 638 580 vo->SetNextFrameDisplayTimeOffset(m_delay); 639 581 } 640 582 641 void VDPAUVideoSync::AdvanceTrigger(void)642 {643 UpdateNexttrigger();644 }645 646 583 #endif 647 584 648 585 BusyWaitVideoSync::BusyWaitVideoSync(VideoOutput *vo, … … 692 629 } 693 630 } 694 631 695 void BusyWaitVideoSync::AdvanceTrigger(void)696 {697 UpdateNexttrigger();698 }699 700 632 USleepVideoSync::USleepVideoSync(VideoOutput *vo, 701 633 int fr, int ri, bool intl) : 702 634 VideoSync(vo, fr, ri, intl) … … 721 653 if (m_delay > 0) 722 654 usleep(m_delay); 723 655 } 724 725 void USleepVideoSync::AdvanceTrigger(void)726 {727 UpdateNexttrigger();728 } -
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" … … 966 964 m_double_framerate = false; 967 965 m_double_process = false; 968 966 969 if (videosync)970 videosync->SetFrameInterval(frame_interval, false);971 972 967 if (osd) 973 968 osd->SetFrameInterval(frame_interval); 974 969 … … 1045 1040 if (interlaced && !m_deint_possible) 1046 1041 { 1047 1042 m_scan = scan; 1048 videosync->SetFrameInterval(frame_interval, false);1049 1043 return; 1050 1044 } 1051 1045 … … 1061 1055 if (videoOutput->NeedsDoubleFramerate()) 1062 1056 { 1063 1057 m_double_framerate = true; 1064 videosync->SetFrameInterval(frame_interval, true); 1065 // Make sure video sync can double frame rate 1066 m_can_double = videosync->UsesFieldInterval(); 1067 if (!m_can_double) 1068 { 1058 m_can_double = (frame_interval / 2 > videosync->getRefreshInterval() * 1.005); 1059 if (! m_can_double) { 1069 1060 VERBOSE(VB_IMPORTANT, "Video sync method can't support double " 1070 1061 "framerate (refresh rate too low for bob deint)"); 1071 1062 FallbackDeint(); … … 1080 1071 { 1081 1072 m_double_process = false; 1082 1073 m_double_framerate = false; 1083 videosync->SetFrameInterval(frame_interval, false);1084 1074 videoOutput->SetDeinterlacingEnabled(false); 1085 1075 VERBOSE(VB_PLAYBACK, "Disabled deinterlacing"); 1086 1076 } … … 2368 2358 void NuppelVideoPlayer::AVSync(void) 2369 2359 { 2370 2360 float diverge = 0.0f; 2361 int frameDelay = m_double_framerate ? frame_interval / 2 : frame_interval; 2371 2362 // attempt to reduce fps for standalone PIP 2372 2363 if (player_ctx->IsPIP() && framesPlayed % 2) 2373 2364 { 2374 videosync->WaitForFrame(avsync_adjustment); 2375 videosync->AdvanceTrigger(); 2365 videosync->WaitForFrame(frameDelay + avsync_adjustment); 2376 2366 if (!using_null_videoout) 2377 2367 videoOutput->SetFramesPlayed(framesPlayed + 1); 2378 2368 return; … … 2384 2374 VERBOSE(VB_IMPORTANT, LOC_ERR + "AVSync: No video buffer"); 2385 2375 return; 2386 2376 } 2377 2387 2378 if (videoOutput->IsErrored()) 2388 2379 { 2389 2380 VERBOSE(VB_IMPORTANT, LOC_ERR + "AVSync: " … … 2441 2432 2442 2433 VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, QString("AVSync waitforframe %1 %2") 2443 2434 .arg(avsync_adjustment).arg(m_double_framerate)); 2444 videosync->WaitForFrame( avsync_adjustment);2435 videosync->WaitForFrame(frameDelay + avsync_adjustment); 2445 2436 VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, "AVSync show"); 2446 2437 if (!resetvideo) 2447 2438 videoOutput->Show(ps); … … 2482 2473 videoOutput->PrepareFrame(buffer, ps); 2483 2474 2484 2475 // Display the second field 2485 videosync->AdvanceTrigger(); 2486 #ifdef NEW_AVSYNC 2487 videosync->WaitForFrame(avsync_adjustment); 2488 #else 2489 videosync->WaitForFrame(0); 2490 #endif 2476 videosync->WaitForFrame(frameDelay + avsync_adjustment); 2491 2477 if (!resetvideo) 2492 2478 { 2493 2479 videoOutput->Show(ps); … … 2496 2482 } 2497 2483 else 2498 2484 { 2499 videosync->WaitForFrame( 0);2485 videosync->WaitForFrame(frameDelay); 2500 2486 } 2501 2487 2502 2488 if (output_jmeter && output_jmeter->RecordCycleTime()) … … 2507 2493 .arg(warpfactor).arg(warpfactor_avg)); 2508 2494 } 2509 2495 2510 videosync->AdvanceTrigger();2511 2496 avsync_adjustment = 0; 2512 2497 2513 2498 if (diverge > MAXDIVERGE) … … 2515 2500 // If audio is way behind of video, adjust for it... 2516 2501 // by cutting the frame rate in half for the length of this frame 2517 2502 2518 #ifdef NEW_AVSYNC2519 2503 avsync_adjustment = refreshrate; 2520 #else2521 avsync_adjustment = frame_interval;2522 #endif2523 2504 lastsync = true; 2524 2505 VERBOSE(VB_PLAYBACK, LOC + 2525 2506 QString("Video is %1 frames ahead of audio,\n" … … 2551 2532 prevtc = buffer->timecode; 2552 2533 //cerr << delta << " "; 2553 2534 2554 // If the timecode is off by a frame (dropped frame) wait to sync2555 if (delta > (int) frame_interval / 1200 &&2556 delta < (int) frame_interval / 1000 * 3)2557 {2558 //cerr << "+ ";2559 videosync->AdvanceTrigger();2560 if (m_double_framerate)2561 videosync->AdvanceTrigger();2562 }2563 2564 2535 avsync_delay = (buffer->timecode - currentaudiotime) * 1000;//usec 2565 2536 // prevents major jitter when pts resets during dvd title 2566 2537 if (avsync_delay > 2000000 && player_ctx->buffer->isDVD()) 2567 2538 avsync_delay = 90000; 2568 2539 avsync_avg = (avsync_delay + (avsync_avg * 3)) / 4; 2569 if (!usevideotimebase) 2540 2541 // If the timecode is off by a frame (dropped frame) wait to sync 2542 if (delta > (int) frame_interval / 1200 && 2543 delta < (int) frame_interval / 1000 * 3) 2570 2544 { 2571 /* If the audio time codes and video diverge, shift 2572 the video by one interlaced field (1/2 frame) */ 2545 // wait an extra frame interval 2546 avsync_adjustment = frame_interval; 2547 } 2548 else if (!usevideotimebase) 2549 { 2550 /* Adjust by the smoothed divergence amount; 2551 * dividy by two to soften the effect. */ 2573 2552 2574 if (!lastsync) 2575 { 2576 if (avsync_avg > frame_interval * 3 / 2) 2577 { 2578 avsync_adjustment = refreshrate; 2579 lastsync = true; 2580 } 2581 else if (avsync_avg < 0 - frame_interval * 3 / 2) 2582 { 2583 avsync_adjustment = -refreshrate; 2584 lastsync = true; 2585 } 2553 if (!lastsync) { 2554 avsync_adjustment = avsync_avg / 2; 2555 if (avsync_adjustment > frame_interval * 4) 2556 avsync_adjustment = frame_interval * 4; 2586 2557 } 2587 2558 else 2588 2559 lastsync = false; … … 2957 2928 // Make sure video sync can do it 2958 2929 if (videosync != NULL && m_double_framerate) 2959 2930 { 2960 videosync->SetFrameInterval(frame_interval, m_double_framerate); 2961 m_can_double = videosync->UsesFieldInterval(); 2962 if (!m_can_double) 2963 { 2931 m_can_double = (frame_interval / 2 > videosync->getRefreshInterval() * 1.005); 2932 if (! m_can_double) { 2964 2933 VERBOSE(VB_IMPORTANT, "Video sync method can't support double " 2965 2934 "framerate (refresh rate too low for bob deint)"); 2966 2935 FallbackDeint(); … … 4333 4302 (frame_interval>>1) : frame_interval); 4334 4303 } 4335 4304 4336 if (videosync != NULL)4337 videosync->SetFrameInterval(frame_interval, m_double_framerate);4338 4339 4305 VERBOSE(VB_PLAYBACK, LOC + "DoPause() -- setting paused"); 4340 4306 paused = actuallypaused = true; 4341 4307 decoderThreadPaused.wakeAll(); … … 4412 4378 4413 4379 m_double_framerate = videoOutput->NeedsDoubleFramerate(); 4414 4380 m_double_process = videoOutput->IsExtraProcessingRequired(); 4415 videosync->SetFrameInterval(frame_interval, m_double_framerate);4416 4381 } 4417 4382 4418 4383 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 */