Ticket #7067: mythtv.3.patch
File mythtv.3.patch, 13.8 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; … … 169 148 } 170 149 } 171 150 172 /** \fn VideoSync::UpdateNexttrigger()173 * \brief Internal method to tells video synchronization method to use174 * the next frame (or field, if interlaced) for CalcDelay()175 * and WaitForFrame().176 */177 void VideoSync::UpdateNexttrigger()178 {179 // Offset by frame interval -- if interlaced, only delay by half180 // frame interval181 if (m_interlaced)182 OffsetTimeval(m_nexttrigger, m_frame_interval/2);183 else184 OffsetTimeval(m_nexttrigger, m_frame_interval);185 }186 187 151 /** \fn VideoSync::CalcDelay() 188 152 * \brief Calculates the delay to the next frame. 189 153 * … … 370 334 //cerr << "Wait " << n << " intervals. Count " << blank.request.sequence; 371 335 //cerr << " Delay " << m_delay << endl; 372 336 } 373 }374 337 375 void DRMVideoSync::AdvanceTrigger(void)376 {377 338 KeepPhase(); 378 UpdateNexttrigger();379 339 } 380 340 #endif /* !_WIN32 */ 381 341 … … 539 499 m_delay = CalcDelay(); 540 500 } 541 501 542 #endif /* USING_OPENGL_VSYNC */543 }544 545 void OpenGLVideoSync::AdvanceTrigger(void)546 {547 #ifdef USING_OPENGL_VSYNC548 549 502 KeepPhase(); 550 UpdateNexttrigger();551 503 #endif /* USING_OPENGL_VSYNC */ 552 504 } 553 505 #endif /* !_WIN32 */ … … 610 562 usleep(m_delay); 611 563 } 612 564 } 613 614 void RTCVideoSync::AdvanceTrigger(void)615 {616 UpdateNexttrigger();617 }618 565 #endif /* __linux__ */ 619 566 620 567 #ifdef USING_VDPAU … … 650 597 vo->SetNextFrameDisplayTimeOffset(m_delay); 651 598 } 652 599 653 void VDPAUVideoSync::AdvanceTrigger(void)654 {655 UpdateNexttrigger();656 }657 658 600 #endif 659 601 660 602 BusyWaitVideoSync::BusyWaitVideoSync(VideoOutput *vo, … … 705 647 } 706 648 } 707 649 708 void BusyWaitVideoSync::AdvanceTrigger(void)709 {710 UpdateNexttrigger();711 }712 713 650 USleepVideoSync::USleepVideoSync(VideoOutput *vo, 714 651 int fr, int ri, bool intl) : 715 652 VideoSync(vo, fr, ri, intl) … … 734 671 if (m_delay > 0) 735 672 usleep(m_delay); 736 673 } 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" … … 960 958 m_double_framerate = false; 961 959 m_double_process = false; 962 960 963 if (videosync)964 videosync->SetFrameInterval(frame_interval, false);965 966 961 if (osd) 967 962 osd->SetFrameInterval(frame_interval); 968 963 … … 1039 1034 if (interlaced && !m_deint_possible) 1040 1035 { 1041 1036 m_scan = scan; 1042 videosync->SetFrameInterval(frame_interval, false);1043 1037 return; 1044 1038 } 1045 1039 … … 1055 1049 if (videoOutput->NeedsDoubleFramerate()) 1056 1050 { 1057 1051 m_double_framerate = true; 1058 videosync->SetFrameInterval(frame_interval, true); 1059 // Make sure video sync can double frame rate 1060 m_can_double = videosync->UsesFieldInterval(); 1052 m_can_double = (frame_interval / 2 > videosync->getRefreshInterval() * 1.005); 1061 1053 if (!m_can_double) 1062 1054 { 1063 1055 VERBOSE(VB_IMPORTANT, "Video sync method can't support double " … … 1074 1066 { 1075 1067 m_double_process = false; 1076 1068 m_double_framerate = false; 1077 videosync->SetFrameInterval(frame_interval, false);1078 1069 videoOutput->SetDeinterlacingEnabled(false); 1079 1070 VERBOSE(VB_PLAYBACK, "Disabled deinterlacing"); 1080 1071 } … … 2364 2355 void NuppelVideoPlayer::AVSync(void) 2365 2356 { 2366 2357 float diverge = 0.0f; 2358 int frameDelay = m_double_framerate ? frame_interval / 2 : frame_interval; 2367 2359 // attempt to reduce fps for standalone PIP 2368 2360 if (player_ctx->IsPIP() && framesPlayed % 2) 2369 2361 { 2370 videosync->WaitForFrame(avsync_adjustment); 2371 videosync->AdvanceTrigger(); 2362 videosync->WaitForFrame(frameDelay + avsync_adjustment); 2372 2363 if (!using_null_videoout) 2373 2364 videoOutput->SetFramesPlayed(framesPlayed + 1); 2374 2365 return; … … 2380 2371 VERBOSE(VB_IMPORTANT, LOC_ERR + "AVSync: No video buffer"); 2381 2372 return; 2382 2373 } 2374 2383 2375 if (videoOutput->IsErrored()) 2384 2376 { 2385 2377 VERBOSE(VB_IMPORTANT, LOC_ERR + "AVSync: " … … 2402 2394 if (kScan_Detect == m_scan || kScan_Ignore == m_scan) 2403 2395 ps = kScan_Progressive; 2404 2396 2405 bool dropframe = false;2406 2397 if (diverge < -MAXDIVERGE) 2407 2398 { 2408 dropframe = true;2409 2399 // If video is way behind of audio, adjust for it... 2410 2400 QString dbg = QString("Video is %1 frames behind audio (too slow), ") 2411 2401 .arg(-diverge); … … 2439 2429 2440 2430 VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, QString("AVSync waitforframe %1 %2") 2441 2431 .arg(avsync_adjustment).arg(m_double_framerate)); 2442 videosync->WaitForFrame( avsync_adjustment + repeat_delay);2432 videosync->WaitForFrame(frameDelay + avsync_adjustment + repeat_delay); 2443 2433 VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, "AVSync show"); 2444 2434 if (!resetvideo) 2445 2435 videoOutput->Show(ps); … … 2480 2470 videoOutput->PrepareFrame(buffer, ps); 2481 2471 2482 2472 // Display the second field 2483 videosync->AdvanceTrigger(); 2484 #ifdef NEW_AVSYNC 2485 videosync->WaitForFrame(avsync_adjustment); 2486 #else 2487 videosync->WaitForFrame(0); 2488 #endif 2473 videosync->WaitForFrame(frameDelay + avsync_adjustment); 2489 2474 if (!resetvideo) 2490 2475 { 2491 2476 videoOutput->Show(ps); … … 2500 2485 } 2501 2486 else 2502 2487 { 2503 videosync->WaitForFrame( 0);2488 videosync->WaitForFrame(frameDelay); 2504 2489 } 2505 2490 2506 2491 if (output_jmeter && output_jmeter->RecordCycleTime()) … … 2511 2496 .arg(warpfactor).arg(warpfactor_avg)); 2512 2497 } 2513 2498 2514 if (!dropframe)2515 videosync->AdvanceTrigger();2516 2499 avsync_adjustment = 0; 2517 2500 2518 2501 if (diverge > MAXDIVERGE) … … 2520 2503 // If audio is way behind of video, adjust for it... 2521 2504 // by cutting the frame rate in half for the length of this frame 2522 2505 2523 #ifdef NEW_AVSYNC2524 2506 avsync_adjustment = refreshrate; 2525 #else2526 avsync_adjustment = frame_interval;2527 #endif2528 2507 lastsync = true; 2529 2508 VERBOSE(VB_PLAYBACK, LOC + 2530 2509 QString("Video is %1 frames ahead of audio,\n" … … 2556 2535 prevtc = buffer->timecode; 2557 2536 //cerr << delta << " "; 2558 2537 2538 avsync_delay = (buffer->timecode - currentaudiotime) * 1000;//usec 2539 // prevents major jitter when pts resets during dvd title 2540 if (avsync_delay > 2000000 && player_ctx->buffer->isDVD()) 2541 avsync_delay = 90000; 2542 avsync_avg = (avsync_delay + (avsync_avg * 3)) / 4; 2543 2559 2544 // If the timecode is off by a frame (dropped frame) wait to sync 2560 2545 if (delta > (int) frame_interval / 1200 && 2561 2546 delta < (int) frame_interval / 1000 * 3 && 2562 2547 prevrp == 0) 2563 2548 { 2564 //cerr << "+ "; 2565 videosync->AdvanceTrigger(); 2566 if (m_double_framerate) 2567 videosync->AdvanceTrigger(); 2549 // wait an extra frame interval 2550 avsync_adjustment = frame_interval; 2568 2551 } 2569 prevrp = buffer->repeat_pict;2570 2571 avsync_delay = (buffer->timecode - currentaudiotime) * 1000;//usec2572 // prevents major jitter when pts resets during dvd title2573 if (avsync_delay > 2000000 && player_ctx->buffer->isDVD())2574 avsync_delay = 90000;2575 avsync_avg = (avsync_delay + (avsync_avg * 3)) / 4;2576 2552 if (!usevideotimebase) 2577 2553 { 2578 /* If the audio time codes and video diverge, shift2579 the video by one interlaced field (1/2 frame)*/2554 /* Adjust by the smoothed divergence amount; 2555 * divide by two to soften the effect. */ 2580 2556 2581 2557 if (!lastsync) 2582 2558 { … … 2594 2570 else 2595 2571 lastsync = false; 2596 2572 } 2573 prevrp = buffer->repeat_pict; 2597 2574 } 2598 2575 else 2599 2576 { … … 2964 2941 // Make sure video sync can do it 2965 2942 if (videosync != NULL && m_double_framerate) 2966 2943 { 2967 videosync->SetFrameInterval(frame_interval, m_double_framerate); 2968 m_can_double = videosync->UsesFieldInterval(); 2969 if (!m_can_double) 2970 { 2944 m_can_double = (frame_interval / 2 > videosync->getRefreshInterval() * 1.005); 2945 if (! m_can_double) { 2971 2946 VERBOSE(VB_IMPORTANT, "Video sync method can't support double " 2972 2947 "framerate (refresh rate too low for bob deint)"); 2973 2948 FallbackDeint(); … … 4343 4318 (frame_interval>>1) : frame_interval); 4344 4319 } 4345 4320 4346 if (videosync != NULL)4347 videosync->SetFrameInterval(frame_interval, m_double_framerate);4348 4349 4321 VERBOSE(VB_PLAYBACK, LOC + "DoPause() -- setting paused"); 4350 4322 paused = actuallypaused = true; 4351 4323 decoderThreadPaused.wakeAll(); … … 4422 4394 4423 4395 m_double_framerate = videoOutput->NeedsDoubleFramerate(); 4424 4396 m_double_process = videoOutput->IsExtraProcessingRequired(); 4425 videosync->SetFrameInterval(frame_interval, m_double_framerate);4426 4397 } 4427 4398 4428 4399 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 * … … 105 91 bool interlaced); 106 92 protected: 107 93 static void OffsetTimeval(struct timeval& tv, int offset); 108 void UpdateNexttrigger(void);109 94 int CalcDelay(void); 110 95 void KeepPhase(void); 111 96 … … 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 */