Ticket #7067: mythtv.patch

File mythtv.patch, 13.9 KB (added by Davin McCall <davmac@…>, 2 years ago)

New patch for trunk. Solves problem for DVDs without menus.

  • libs/libmythtv/vsync.cpp

     
    126126    m_delay(-1) 
    127127{ 
    128128    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 rate 
    133  
    134     //cout << "Frame interval: " << m_frame_interval << endl; 
    135129} 
    136130 
    137131void VideoSync::Start(void) 
     
    139133    gettimeofday(&m_nexttrigger, NULL); // now 
    140134} 
    141135 
    142 /** \fn VideoSync::SetFrameInterval(int fr, bool intr) 
    143  *  \brief Change frame interval and interlacing attributes 
    144  */ 
    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 rate 
    152  
    153     VERBOSE(VB_PLAYBACK, QString("Set video sync frame interval to %1") 
    154                                  .arg(m_frame_interval)); 
    155 } 
    156  
    157136void VideoSync::OffsetTimeval(struct timeval& tv, int offset) 
    158137{ 
    159138    tv.tv_usec += offset; 
     
    221200    return ret_val; 
    222201} 
    223202 
    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 others 
    228  *   delay > 0 which would cause continous rapid fire stuttering. 
    229  *   This method is only useful for those sync methods where WaitForFrame 
    230  *   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  
    241203#ifndef _WIN32 
    242204#define DRM_VBLANK_RELATIVE 0x1; 
    243205 
     
    359321        //cerr  << " Delay " << m_delay << endl; 
    360322    } 
    361323} 
    362  
    363 void DRMVideoSync::AdvanceTrigger(void) 
    364 { 
    365     KeepPhase(); 
    366     UpdateNexttrigger(); 
    367 } 
    368324#endif /* !_WIN32 */ 
    369325 
    370326#ifndef _WIN32 
     
    529485     
    530486#endif /* USING_OPENGL_VSYNC */ 
    531487} 
    532  
    533 void OpenGLVideoSync::AdvanceTrigger(void) 
    534 { 
    535 #ifdef USING_OPENGL_VSYNC 
    536  
    537     KeepPhase(); 
    538     UpdateNexttrigger(); 
    539 #endif /* USING_OPENGL_VSYNC */ 
    540 } 
    541488#endif /* !_WIN32 */ 
    542489 
    543490#ifdef __linux__ 
     
    598545            usleep(m_delay); 
    599546    } 
    600547} 
    601  
    602 void RTCVideoSync::AdvanceTrigger(void) 
    603 { 
    604     UpdateNexttrigger(); 
    605 } 
    606548#endif /* __linux__ */ 
    607549 
    608550#ifdef USING_VDPAU 
     
    638580    vo->SetNextFrameDisplayTimeOffset(m_delay); 
    639581} 
    640582 
    641 void VDPAUVideoSync::AdvanceTrigger(void) 
    642 { 
    643     UpdateNexttrigger(); 
    644 } 
    645  
    646583#endif 
    647584 
    648585BusyWaitVideoSync::BusyWaitVideoSync(VideoOutput *vo, 
     
    692629    } 
    693630} 
    694631 
    695 void BusyWaitVideoSync::AdvanceTrigger(void) 
    696 { 
    697     UpdateNexttrigger(); 
    698 } 
    699  
    700632USleepVideoSync::USleepVideoSync(VideoOutput *vo, 
    701633                                 int fr, int ri, bool intl) :  
    702634    VideoSync(vo, fr, ri, intl) 
     
    721653    if (m_delay > 0) 
    722654        usleep(m_delay); 
    723655} 
    724  
    725 void USleepVideoSync::AdvanceTrigger(void) 
    726 { 
    727     UpdateNexttrigger(); 
    728 } 
  • libs/libmythtv/NuppelVideoPlayer.cpp

     
    2626#include <QKeyEvent> 
    2727#include <QDir> 
    2828 
    29 #define NEW_AVSYNC 
    30  
    3129// MythTV headers 
    3230#include "mythconfig.h" 
    3331#include "mythdbcon.h" 
     
    966964     m_double_framerate = false; 
    967965     m_double_process   = false; 
    968966 
    969      if (videosync) 
    970          videosync->SetFrameInterval(frame_interval, false); 
    971  
    972967     if (osd) 
    973968         osd->SetFrameInterval(frame_interval); 
    974969 
     
    10451040    if (interlaced && !m_deint_possible) 
    10461041    { 
    10471042        m_scan = scan; 
    1048         videosync->SetFrameInterval(frame_interval, false); 
    10491043        return; 
    10501044    } 
    10511045 
     
    10611055        if (videoOutput->NeedsDoubleFramerate()) 
    10621056        { 
    10631057            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) { 
    10691060                VERBOSE(VB_IMPORTANT, "Video sync method can't support double " 
    10701061                        "framerate (refresh rate too low for bob deint)"); 
    10711062                FallbackDeint(); 
     
    10801071        { 
    10811072            m_double_process = false; 
    10821073            m_double_framerate = false; 
    1083             videosync->SetFrameInterval(frame_interval, false); 
    10841074            videoOutput->SetDeinterlacingEnabled(false); 
    10851075            VERBOSE(VB_PLAYBACK, "Disabled deinterlacing"); 
    10861076        } 
     
    23682358void NuppelVideoPlayer::AVSync(void) 
    23692359{ 
    23702360    float diverge = 0.0f; 
     2361    int frameDelay = m_double_framerate ? frame_interval / 2 : frame_interval; 
    23712362    // attempt to reduce fps for standalone PIP 
    23722363    if (player_ctx->IsPIP() && framesPlayed % 2) 
    23732364    { 
    2374         videosync->WaitForFrame(avsync_adjustment); 
    2375         videosync->AdvanceTrigger(); 
     2365        videosync->WaitForFrame(frameDelay + avsync_adjustment); 
    23762366        if (!using_null_videoout) 
    23772367            videoOutput->SetFramesPlayed(framesPlayed + 1); 
    23782368        return; 
     
    23842374        VERBOSE(VB_IMPORTANT, LOC_ERR + "AVSync: No video buffer"); 
    23852375        return; 
    23862376    } 
     2377 
    23872378    if (videoOutput->IsErrored()) 
    23882379    { 
    23892380        VERBOSE(VB_IMPORTANT, LOC_ERR + "AVSync: " 
     
    24412432 
    24422433        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, QString("AVSync waitforframe %1 %2") 
    24432434                .arg(avsync_adjustment).arg(m_double_framerate)); 
    2444         videosync->WaitForFrame(avsync_adjustment); 
     2435        videosync->WaitForFrame(frameDelay + avsync_adjustment); 
    24452436        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, "AVSync show"); 
    24462437        if (!resetvideo) 
    24472438            videoOutput->Show(ps); 
     
    24822473                videoOutput->PrepareFrame(buffer, ps); 
    24832474 
    24842475            // 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); 
    24912477            if (!resetvideo) 
    24922478            { 
    24932479                videoOutput->Show(ps); 
     
    24962482    } 
    24972483    else 
    24982484    { 
    2499         videosync->WaitForFrame(0); 
     2485        videosync->WaitForFrame(frameDelay); 
    25002486    } 
    25012487 
    25022488    if (output_jmeter && output_jmeter->RecordCycleTime()) 
     
    25072493                .arg(warpfactor).arg(warpfactor_avg)); 
    25082494    } 
    25092495 
    2510     videosync->AdvanceTrigger(); 
    25112496    avsync_adjustment = 0; 
    25122497 
    25132498    if (diverge > MAXDIVERGE) 
     
    25152500        // If audio is way behind of video, adjust for it... 
    25162501        // by cutting the frame rate in half for the length of this frame 
    25172502 
    2518 #ifdef NEW_AVSYNC 
    25192503        avsync_adjustment = refreshrate; 
    2520 #else 
    2521         avsync_adjustment = frame_interval; 
    2522 #endif 
    25232504        lastsync = true; 
    25242505        VERBOSE(VB_PLAYBACK, LOC + 
    25252506                QString("Video is %1 frames ahead of audio,\n" 
     
    25512532            prevtc = buffer->timecode; 
    25522533            //cerr << delta << " "; 
    25532534 
    2554             // If the timecode is off by a frame (dropped frame) wait to sync 
    2555             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  
    25642535            avsync_delay = (buffer->timecode - currentaudiotime) * 1000;//usec 
    25652536            // prevents major jitter when pts resets during dvd title 
    25662537            if (avsync_delay > 2000000 && player_ctx->buffer->isDVD()) 
    25672538                avsync_delay = 90000; 
    25682539            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) 
    25702544            { 
    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. */ 
    25732552 
    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; 
    25862557                } 
    25872558                else 
    25882559                    lastsync = false; 
     
    29572928        // Make sure video sync can do it 
    29582929        if (videosync != NULL && m_double_framerate) 
    29592930        { 
    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) { 
    29642933                VERBOSE(VB_IMPORTANT, "Video sync method can't support double " 
    29652934                        "framerate (refresh rate too low for bob deint)"); 
    29662935                FallbackDeint(); 
     
    43334302            (frame_interval>>1) : frame_interval); 
    43344303    } 
    43354304 
    4336     if (videosync != NULL) 
    4337         videosync->SetFrameInterval(frame_interval, m_double_framerate); 
    4338  
    43394305    VERBOSE(VB_PLAYBACK, LOC + "DoPause() -- setting paused"); 
    43404306    paused = actuallypaused = true; 
    43414307    decoderThreadPaused.wakeAll(); 
     
    44124378 
    44134379        m_double_framerate = videoOutput->NeedsDoubleFramerate(); 
    44144380        m_double_process = videoOutput->IsExtraProcessingRequired(); 
    4415         videosync->SetFrameInterval(frame_interval, m_double_framerate); 
    44164381    } 
    44174382 
    44184383    if (osd) 
  • libs/libmythtv/vsync.h

     
    3939 *   The factory method BestMethod tries subclasses in roughly quality 
    4040 *   order until one succeeds. 
    4141 * 
    42  *   A/V sync methods may supply an additonal delay per frame. Other 
     42 *   A/V sync methods may supply the nominal delay per frame. Other 
    4343 *   than that, video timing is entirely up to these classes. When 
    4444 *   WaitForFrame returns, it is time to show the frame. 
    45  * 
    46  *   There is some basic support for interlaced video timing where the 
    47  *   fields need to be displayed sequentially. Passing true for the 
    48  *   interlaced flags for the constructors, BestMethod, and 
    49  *   SetFrameInterval will cause us to wait for half the specified frame 
    50  *   interval, if the refresh rate is sufficient to do so. 
    5145 */ 
    5246class VideoSync 
    5347// virtual base class 
     
    8074     */ 
    8175    virtual void WaitForFrame(int sync_delay) = 0; 
    8276 
    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; } 
    9379 
    9480    /** \brief Stops VSync; must be called from main thread. 
    9581     * 
     
    10793    static void OffsetTimeval(struct timeval& tv, int offset); 
    10894    void UpdateNexttrigger(void); 
    10995    int CalcDelay(void); 
    110     void KeepPhase(void); 
    11196 
    11297    VideoOutput *m_video_output; 
    11398    int m_frame_interval; // of video 
     
    137122    bool TryInit(void); 
    138123    void Start(void); 
    139124    void WaitForFrame(int sync_delay); 
    140     void AdvanceTrigger(void); 
    141125 
    142126  private: 
    143127    int m_dri_fd; 
     
    179163    bool TryInit(void); 
    180164    void Start(void); 
    181165    void WaitForFrame(int sync_delay); 
    182     void AdvanceTrigger(void); 
    183166 
    184167  private: 
    185168    OpenGLContext  *m_context; 
     
    208191    QString getName(void) const { return QString("RTC"); } 
    209192    bool TryInit(void); 
    210193    void WaitForFrame(int sync_delay); 
    211     void AdvanceTrigger(void); 
    212194 
    213195  private: 
    214196    int m_rtcfd; 
     
    229211    QString getName(void) const { return QString("VDPAU"); } 
    230212    bool TryInit(void); 
    231213    void WaitForFrame(int sync_delay); 
    232     void AdvanceTrigger(void); 
    233214 
    234215  private: 
    235216}; 
     
    257238    QString getName(void) const { return QString("USleep with busy wait"); } 
    258239    bool TryInit(void); 
    259240    void WaitForFrame(int sync_delay); 
    260     void AdvanceTrigger(void); 
    261241 
    262242  private: 
    263243    int m_cheat; 
     
    285265    QString getName(void) const { return QString("USleep"); } 
    286266    bool TryInit(void); 
    287267    void WaitForFrame(int sync_delay); 
    288     void AdvanceTrigger(void); 
    289268}; 
    290269#endif /* VSYNC_H_INCLUDED */