Ticket #7964: smoother-vsync-vsync-opt.11-24fixes-p0.patch
File smoother-vsync-vsync-opt.11-24fixes-p0.patch, 11.8 KB (added by , 13 years ago) |
---|
-
libs/libmythtv/vsync.cpp
old new VideoSync::VideoSync(VideoOutput *video_ 130 130 bool halve_frame_interval) : 131 131 m_video_output(video_output), m_frame_interval(frameint), 132 132 m_refresh_interval(refreshint), m_interlaced(halve_frame_interval), 133 m_delay(-1) 134 { 135 bzero(&m_nexttrigger, sizeof(m_nexttrigger)); 133 m_nexttrigger(0), 134 m_delay(-1), 135 m_synchronous(false) 136 { 137 int fieldint = frameint; 138 if (halve_frame_interval) 139 fieldint /= 2; 140 double sync_factor = fieldint * 2.0f / refreshint; 141 sync_factor = sync_factor - round(sync_factor); 142 m_synchronous = (sync_factor >= -0.005) && (sync_factor <= 0.005); 143 VERBOSE(VB_PLAYBACK, LOC + QString("Set video sync frame interval to %1 (synced:%2)") 144 .arg(m_frame_interval).arg(m_synchronous)); 145 } 146 147 int64_t GetTime(void) 148 { 149 struct timeval now_tv; 150 gettimeofday(&now_tv, NULL); // now 151 return now_tv.tv_sec * 1000000LL + now_tv.tv_usec; 136 152 } 137 153 138 154 void VideoSync::Start(void) 139 155 { 140 gettimeofday(&m_nexttrigger, NULL); // now 141 } 142 143 void VideoSync::OffsetTimeval(struct timeval& tv, int offset) 144 { 145 tv.tv_usec += offset; 146 while (tv.tv_usec > 999999) 147 { 148 tv.tv_sec++; 149 tv.tv_usec -= 1000000; 150 } 151 while (tv.tv_usec < 0) 152 { 153 tv.tv_sec--; 154 tv.tv_usec += 1000000; 155 } 156 m_nexttrigger = GetTime(); 156 157 } 157 158 158 159 /** \fn VideoSync::CalcDelay() … … void VideoSync::OffsetTimeval(struct tim 168 169 */ 169 170 int VideoSync::CalcDelay() 170 171 { 171 struct timeval now; 172 gettimeofday(&now, NULL); 172 int64_t now = GetTime(); 173 173 //cout << "CalcDelay: next: " << timeval_str(m_nexttrigger) << " now " 174 174 // << timeval_str(now) << endl; 175 175 176 int ret_val = (m_nexttrigger.tv_sec - now.tv_sec) * 1000000 + 177 (m_nexttrigger.tv_usec - now.tv_usec); 176 int ret_val = m_nexttrigger - now; 178 177 179 178 //cout << "delay " << ret_val << endl; 180 179 … … int VideoSync::CalcDelay() 186 185 ret_val = m_frame_interval * 4; 187 186 188 187 // set nexttrigger to our new target time 189 m_nexttrigger.tv_sec = now.tv_sec; 190 m_nexttrigger.tv_usec = now.tv_usec; 191 OffsetTimeval(m_nexttrigger, ret_val); 188 m_nexttrigger = now; 189 m_nexttrigger += ret_val; 192 190 } 193 191 194 if ( ret_val < -m_frame_interval)192 if ((ret_val < -m_frame_interval) && (m_frame_interval >= m_refresh_interval)) 195 193 { 196 194 ret_val = -m_frame_interval; 197 195 198 196 // set nexttrigger to our new target time 199 m_nexttrigger.tv_sec = now.tv_sec; 200 m_nexttrigger.tv_usec = now.tv_usec; 201 OffsetTimeval(m_nexttrigger, ret_val); 197 m_nexttrigger = now; 198 m_nexttrigger += ret_val; 202 199 } 203 200 204 201 return ret_val; … … int VideoSync::CalcDelay() 215 212 void VideoSync::KeepPhase() 216 213 { 217 214 // cerr << m_delay << endl; 218 if (m_delay < -(m_refresh_interval/2)) 219 OffsetTimeval(m_nexttrigger, 200); 220 else if (m_delay > -500) 221 OffsetTimeval(m_nexttrigger, -2000); 215 if (m_synchronous) 216 { 217 if (m_delay < -(m_refresh_interval - 500)) 218 m_nexttrigger += 200; 219 else if (m_delay > -500) 220 m_nexttrigger += -2000; 221 } 222 else 223 { 224 if (m_delay < -(m_refresh_interval + 500)) 225 m_nexttrigger += 200; 226 else if (m_delay >= 0) 227 m_nexttrigger += -2000; 228 } 222 229 } 223 230 224 231 #ifndef _WIN32 … … void DRMVideoSync::Start(void) 308 315 VideoSync::Start(); 309 316 } 310 317 311 voidDRMVideoSync::WaitForFrame(int sync_delay)318 int DRMVideoSync::WaitForFrame(int sync_delay) 312 319 { 313 320 // Offset for externally-provided A/V sync delay 314 OffsetTimeval(m_nexttrigger, sync_delay);321 m_nexttrigger += sync_delay; 315 322 316 323 m_delay = CalcDelay(); 317 324 //cerr << "WaitForFrame at : " << m_delay; … … void DRMVideoSync::WaitForFrame(int sync 331 338 if (m_delay > 0) 332 339 { 333 340 // Wait for any remaining retrace intervals in one pass. 334 int n = m_delay / m_refresh_interval + 1;341 int n = (m_delay + m_refresh_interval - 1) / m_refresh_interval; 335 342 336 343 drm_wait_vblank_t blank; 337 344 blank.request.type = DRM_VBLANK_RELATIVE; … … void DRMVideoSync::WaitForFrame(int sync 341 348 //cerr << "Wait " << n << " intervals. Count " << blank.request.sequence; 342 349 //cerr << " Delay " << m_delay << endl; 343 350 } 351 return m_delay; 344 352 345 353 KeepPhase(); 346 354 } … … void OpenGLVideoSync::Start(void) 412 420 #endif /* USING_OPENGL_VSYNC */ 413 421 } 414 422 415 voidOpenGLVideoSync::WaitForFrame(int sync_delay)423 int OpenGLVideoSync::WaitForFrame(int sync_delay) 416 424 { 417 425 (void) sync_delay; 418 426 #ifdef USING_OPENGL_VSYNC 427 //#define GLVSYNCDEBUG 428 #ifdef GLVSYNCDEBUG 429 int refreshcount = 0; 430 #endif 419 431 const QString msg1("First A/V Sync"), msg2("Second A/V Sync"); 420 OffsetTimeval(m_nexttrigger, sync_delay);432 m_nexttrigger += sync_delay; 421 433 422 434 if (m_video_output && m_video_output->IsEmbedding()) 423 435 { 424 436 m_delay = CalcDelay(); 425 437 if (m_delay > 0) 426 438 usleep(m_delay); 427 return ;439 return 0; 428 440 } 429 441 430 442 if (!m_context) 431 return ;443 return 0; 432 444 433 445 unsigned int frameNum = m_context->GetVideoSyncCount(); 434 446 447 #ifdef GLVSYNCDEBUG 448 int delay1 = m_delay; 449 int delay2; 450 #endif 435 451 // Always sync to the next retrace execpt when we are very late. 436 452 if ((m_delay = CalcDelay()) > -(m_refresh_interval/2)) 437 453 { 454 #ifdef GLVSYNCDEBUG 455 delay2 = m_delay; 456 #endif 438 457 m_context->WaitForVideoSync(2, (frameNum+1)%2 ,&frameNum); 439 458 m_delay = CalcDelay(); 459 #ifdef GLVSYNCDEBUG 460 refreshcount++; 461 #endif 440 462 } 463 #ifdef GLVSYNCDEBUG 464 else 465 delay2 = m_delay; 466 #endif 441 467 468 #ifdef GLVSYNCDEBUG 469 int delay3 = m_delay; 470 #endif 442 471 // Wait for any remaining retrace intervals in one pass. 443 472 if (m_delay > 0) 444 473 { 445 uint n = m_delay / m_refresh_interval + 1; 474 //uint n = m_delay / m_refresh_interval + 1; 475 uint n = (m_delay + m_refresh_interval - 1) / m_refresh_interval; 446 476 m_context->WaitForVideoSync((n+1), (frameNum+n)%(n+1), &frameNum); 477 #ifdef GLVSYNCDEBUG 478 refreshcount += (int)n; 479 #endif 447 480 m_delay = CalcDelay(); 448 481 } 482 #ifdef GLVSYNCDEBUG 483 VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, QString("VS: WFF: ri:%1 fi:%2 delay1:%3 delay2:%4 delay3:%5 skip:%6 finaldelay:%7") 484 .arg(m_refresh_interval) 485 .arg(m_frame_interval) 486 .arg(delay1) 487 .arg(delay2) 488 .arg(delay3) 489 .arg(refreshcount) 490 .arg(m_delay) 491 ); 492 #endif 493 494 return m_delay; 449 495 450 496 KeepPhase(); 497 #ifdef GLVSYNCDEBUG 498 VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, "VS: AdvanceTrigger"); 499 #endif 451 500 #endif /* USING_OPENGL_VSYNC */ 452 501 } 453 502 #endif /* !_WIN32 */ … … bool RTCVideoSync::TryInit(void) 494 543 return true; 495 544 } 496 545 497 voidRTCVideoSync::WaitForFrame(int sync_delay)546 int RTCVideoSync::WaitForFrame(int sync_delay) 498 547 { 499 OffsetTimeval(m_nexttrigger, sync_delay);548 m_nexttrigger += sync_delay; 500 549 501 550 m_delay = CalcDelay(); 502 551 … … void RTCVideoSync::WaitForFrame(int sync 509 558 if ((val < 0) && (m_delay > 0)) 510 559 usleep(m_delay); 511 560 } 561 return 0; 512 562 } 513 563 #endif /* __linux__ */ 514 564 … … bool VDPAUVideoSync::TryInit(void) 532 582 return true; 533 583 } 534 584 535 voidVDPAUVideoSync::WaitForFrame(int sync_delay)585 int VDPAUVideoSync::WaitForFrame(int sync_delay) 536 586 { 537 587 // Offset for externally-provided A/V sync delay 538 OffsetTimeval(m_nexttrigger, sync_delay);588 m_nexttrigger += sync_delay; 539 589 m_delay = CalcDelay(); 540 590 541 591 if (m_delay < 0) … … void VDPAUVideoSync::WaitForFrame(int sy 543 593 544 594 VideoOutputVDPAU *vo = (VideoOutputVDPAU *)(m_video_output); 545 595 vo->SetNextFrameDisplayTimeOffset(m_delay); 596 return 0; 546 597 } 547 598 #endif 548 599 … … bool BusyWaitVideoSync::TryInit(void) 563 614 return true; 564 615 } 565 616 566 voidBusyWaitVideoSync::WaitForFrame(int sync_delay)617 int BusyWaitVideoSync::WaitForFrame(int sync_delay) 567 618 { 568 619 // Offset for externally-provided A/V sync delay 569 OffsetTimeval(m_nexttrigger, sync_delay);620 m_nexttrigger += sync_delay; 570 621 571 622 m_delay = CalcDelay(); 572 623 … … void BusyWaitVideoSync::WaitForFrame(int 592 643 if (cnt > 1) 593 644 m_cheat -= 200; 594 645 } 646 return 0; 595 647 } 596 648 597 649 USleepVideoSync::USleepVideoSync(VideoOutput *vo, … … bool USleepVideoSync::TryInit(void) 609 661 return true; 610 662 } 611 663 612 voidUSleepVideoSync::WaitForFrame(int sync_delay)664 int USleepVideoSync::WaitForFrame(int sync_delay) 613 665 { 614 666 // Offset for externally-provided A/V sync delay 615 OffsetTimeval(m_nexttrigger, sync_delay);667 m_nexttrigger += sync_delay; 616 668 617 669 m_delay = CalcDelay(); 618 670 if (m_delay > 0) 619 671 usleep(m_delay); 672 return 0; 620 673 } 621 674 -
libs/libmythtv/vsync.h
old new class VideoSync 64 64 virtual void Start(void); 65 65 66 66 /** \brief Waits for next a frame or field. 67 * Returns delay to real frame timing in usec 67 68 * 68 69 * Start(void), WaitForFrame(void), and Stop(void) should 69 70 * always be called from same thread, to prevent bad … … class VideoSync 72 73 * \param sync_delay time until the desired frame or field 73 74 * \sa CalcDelay(void), KeepPhase(void) 74 75 */ 75 virtual voidWaitForFrame(int sync_delay) = 0;76 virtual int WaitForFrame(int sync_delay) = 0; 76 77 77 78 /// \brief Returns the (minimum) refresh interval of the output device. 78 79 int getRefreshInterval(void) const { return m_refresh_interval; } … … class VideoSync 92 93 uint frame_interval, uint refresh_interval, 93 94 bool interlaced); 94 95 protected: 95 static void OffsetTimeval(struct timeval& tv, int offset);96 96 int CalcDelay(void); 97 97 void KeepPhase(void); 98 98 … … class VideoSync 100 100 int m_frame_interval; // of video 101 101 int m_refresh_interval; // of display 102 102 bool m_interlaced; 103 struct timevalm_nexttrigger;103 int64_t m_nexttrigger; 104 104 int m_delay; 105 bool m_synchronous; 105 106 106 107 static int m_forceskip; 107 108 }; … … class DRMVideoSync : public VideoSync 123 124 QString getName(void) const { return QString("DRM"); } 124 125 bool TryInit(void); 125 126 void Start(void); 126 voidWaitForFrame(int sync_delay);127 int WaitForFrame(int sync_delay); 127 128 128 129 private: 129 130 int m_dri_fd; … … class OpenGLVideoSync : public VideoSync 164 165 QString getName(void) const { return QString("SGI OpenGL"); } 165 166 bool TryInit(void); 166 167 void Start(void); 167 voidWaitForFrame(int sync_delay);168 int WaitForFrame(int sync_delay); 168 169 169 170 private: 170 171 MythRenderOpenGL *m_context; … … class RTCVideoSync : public VideoSync 192 193 193 194 QString getName(void) const { return QString("RTC"); } 194 195 bool TryInit(void); 195 voidWaitForFrame(int sync_delay);196 int WaitForFrame(int sync_delay); 196 197 197 198 private: 198 199 int m_rtcfd; … … class VDPAUVideoSync : public VideoSync 212 213 213 214 QString getName(void) const { return QString("VDPAU"); } 214 215 bool TryInit(void); 215 voidWaitForFrame(int sync_delay);216 int WaitForFrame(int sync_delay); 216 217 217 218 private: 218 219 }; … … class BusyWaitVideoSync : public VideoSy 239 240 240 241 QString getName(void) const { return QString("USleep with busy wait"); } 241 242 bool TryInit(void); 242 voidWaitForFrame(int sync_delay);243 int WaitForFrame(int sync_delay); 243 244 244 245 private: 245 246 int m_cheat; … … class USleepVideoSync : public VideoSync 266 267 267 268 QString getName(void) const { return QString("USleep"); } 268 269 bool TryInit(void); 269 voidWaitForFrame(int sync_delay);270 int WaitForFrame(int sync_delay); 270 271 }; 271 272 #endif /* VSYNC_H_INCLUDED */