Ticket #7067: mythtv.6.patch

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

Trying again.

  • 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; 
     
    169148    } 
    170149} 
    171150 
    172 /** \fn VideoSync::UpdateNexttrigger() 
    173  *  \brief Internal method to tells video synchronization method to use 
    174  *         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 half 
    180     // frame interval 
    181     if (m_interlaced) 
    182         OffsetTimeval(m_nexttrigger, m_frame_interval/2); 
    183     else 
    184         OffsetTimeval(m_nexttrigger, m_frame_interval); 
    185 } 
    186  
    187151/** \fn VideoSync::CalcDelay() 
    188152 *  \brief Calculates the delay to the next frame. 
    189153 * 
     
    370334        //cerr << "Wait " << n << " intervals. Count " << blank.request.sequence; 
    371335        //cerr  << " Delay " << m_delay << endl; 
    372336    } 
    373 } 
    374337 
    375 void DRMVideoSync::AdvanceTrigger(void) 
    376 { 
    377338    KeepPhase(); 
    378     UpdateNexttrigger(); 
    379339} 
    380340#endif /* !_WIN32 */ 
    381341 
     
    539499        m_delay = CalcDelay(); 
    540500    } 
    541501     
    542 #endif /* USING_OPENGL_VSYNC */ 
    543 } 
    544  
    545 void OpenGLVideoSync::AdvanceTrigger(void) 
    546 { 
    547 #ifdef USING_OPENGL_VSYNC 
    548  
    549502    KeepPhase(); 
    550     UpdateNexttrigger(); 
    551503#endif /* USING_OPENGL_VSYNC */ 
    552504} 
    553505#endif /* !_WIN32 */ 
     
    610562            usleep(m_delay); 
    611563    } 
    612564} 
    613  
    614 void RTCVideoSync::AdvanceTrigger(void) 
    615 { 
    616     UpdateNexttrigger(); 
    617 } 
    618565#endif /* __linux__ */ 
    619566 
    620567#ifdef USING_VDPAU 
     
    650597    vo->SetNextFrameDisplayTimeOffset(m_delay); 
    651598} 
    652599 
    653 void VDPAUVideoSync::AdvanceTrigger(void) 
    654 { 
    655     UpdateNexttrigger(); 
    656 } 
    657  
    658600#endif 
    659601 
    660602BusyWaitVideoSync::BusyWaitVideoSync(VideoOutput *vo, 
     
    705647    } 
    706648} 
    707649 
    708 void BusyWaitVideoSync::AdvanceTrigger(void) 
    709 { 
    710     UpdateNexttrigger(); 
    711 } 
    712  
    713650USleepVideoSync::USleepVideoSync(VideoOutput *vo, 
    714651                                 int fr, int ri, bool intl) :  
    715652    VideoSync(vo, fr, ri, intl) 
     
    734671    if (m_delay > 0) 
    735672        usleep(m_delay); 
    736673} 
    737  
    738 void USleepVideoSync::AdvanceTrigger(void) 
    739 { 
    740     UpdateNexttrigger(); 
    741 } 
  • 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" 
     
    960958     m_double_framerate = false; 
    961959     m_double_process   = false; 
    962960 
    963      if (videosync) 
    964          videosync->SetFrameInterval(frame_interval, false); 
    965  
    966961     if (osd) 
    967962         osd->SetFrameInterval(frame_interval); 
    968963 
     
    10391034    if (interlaced && !m_deint_possible) 
    10401035    { 
    10411036        m_scan = scan; 
    1042         videosync->SetFrameInterval(frame_interval, false); 
    10431037        return; 
    10441038    } 
    10451039 
     
    10551049        if (videoOutput->NeedsDoubleFramerate()) 
    10561050        { 
    10571051            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() * 0.995); 
    10611053            if (!m_can_double) 
    10621054            { 
    10631055                VERBOSE(VB_IMPORTANT, "Video sync method can't support double " 
     
    10741066        { 
    10751067            m_double_process = false; 
    10761068            m_double_framerate = false; 
    1077             videosync->SetFrameInterval(frame_interval, false); 
    10781069            videoOutput->SetDeinterlacingEnabled(false); 
    10791070            VERBOSE(VB_PLAYBACK, "Disabled deinterlacing"); 
    10801071        } 
     
    23642355void NuppelVideoPlayer::AVSync(void) 
    23652356{ 
    23662357    float diverge = 0.0f; 
     2358    int frameDelay = m_double_framerate ? frame_interval / 2 : frame_interval; 
    23672359    // attempt to reduce fps for standalone PIP 
    23682360    if (player_ctx->IsPIP() && framesPlayed % 2) 
    23692361    { 
    2370         videosync->WaitForFrame(avsync_adjustment); 
    2371         videosync->AdvanceTrigger(); 
     2362        videosync->WaitForFrame(frameDelay + avsync_adjustment); 
    23722363        if (!using_null_videoout) 
    23732364            videoOutput->SetFramesPlayed(framesPlayed + 1); 
    23742365        return; 
     
    23802371        VERBOSE(VB_IMPORTANT, LOC_ERR + "AVSync: No video buffer"); 
    23812372        return; 
    23822373    } 
     2374 
    23832375    if (videoOutput->IsErrored()) 
    23842376    { 
    23852377        VERBOSE(VB_IMPORTANT, LOC_ERR + "AVSync: " 
     
    24022394    if (kScan_Detect == m_scan || kScan_Ignore == m_scan) 
    24032395        ps = kScan_Progressive; 
    24042396 
    2405     bool dropframe = false; 
    24062397    if (diverge < -MAXDIVERGE) 
    24072398    { 
    2408         dropframe = true; 
    24092399        // If video is way behind of audio, adjust for it... 
    24102400        QString dbg = QString("Video is %1 frames behind audio (too slow), ") 
    24112401            .arg(-diverge); 
     
    24392429 
    24402430        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, QString("AVSync waitforframe %1 %2") 
    24412431                .arg(avsync_adjustment).arg(m_double_framerate)); 
    2442         videosync->WaitForFrame(avsync_adjustment + repeat_delay); 
     2432        videosync->WaitForFrame(frameDelay + avsync_adjustment + repeat_delay); 
    24432433        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, "AVSync show"); 
    24442434        if (!resetvideo) 
    24452435            videoOutput->Show(ps); 
     
    24802470                videoOutput->PrepareFrame(buffer, ps); 
    24812471 
    24822472            // 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); 
    24892474            if (!resetvideo) 
    24902475            { 
    24912476                videoOutput->Show(ps); 
     
    25002485    } 
    25012486    else 
    25022487    { 
    2503         videosync->WaitForFrame(0); 
     2488        videosync->WaitForFrame(frameDelay); 
    25042489    } 
    25052490 
    25062491    if (output_jmeter && output_jmeter->RecordCycleTime()) 
     
    25112496                .arg(warpfactor).arg(warpfactor_avg)); 
    25122497    } 
    25132498 
    2514     if (!dropframe) 
    2515         videosync->AdvanceTrigger(); 
    25162499    avsync_adjustment = 0; 
    25172500 
    25182501    if (diverge > MAXDIVERGE) 
     
    25202503        // If audio is way behind of video, adjust for it... 
    25212504        // by cutting the frame rate in half for the length of this frame 
    25222505 
    2523 #ifdef NEW_AVSYNC 
    25242506        avsync_adjustment = refreshrate; 
    2525 #else 
    2526         avsync_adjustment = frame_interval; 
    2527 #endif 
    25282507        lastsync = true; 
    25292508        VERBOSE(VB_PLAYBACK, LOC + 
    25302509                QString("Video is %1 frames ahead of audio,\n" 
     
    25562535            prevtc = buffer->timecode; 
    25572536            //cerr << delta << " "; 
    25582537 
     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 
    25592544            // If the timecode is off by a frame (dropped frame) wait to sync 
    25602545            if (delta > (int) frame_interval / 1200 && 
    25612546                delta < (int) frame_interval / 1000 * 3 && 
    25622547                prevrp == 0) 
    25632548            { 
    2564                 //cerr << "+ "; 
    2565                 videosync->AdvanceTrigger(); 
    2566                 if (m_double_framerate) 
    2567                     videosync->AdvanceTrigger(); 
     2549                // wait an extra frame interval 
     2550                avsync_adjustment = frame_interval; 
    25682551            } 
    2569             prevrp = buffer->repeat_pict; 
    2570  
    2571             avsync_delay = (buffer->timecode - currentaudiotime) * 1000;//usec 
    2572             // prevents major jitter when pts resets during dvd title 
    2573             if (avsync_delay > 2000000 && player_ctx->buffer->isDVD()) 
    2574                 avsync_delay = 90000; 
    2575             avsync_avg = (avsync_delay + (avsync_avg * 3)) / 4; 
    25762552            if (!usevideotimebase) 
    25772553            { 
    2578                 /* If the audio time codes and video diverge, shift 
    2579                    the video by one interlaced field (1/2 frame) */ 
     2554                /* Adjust by the smoothed divergence amount; 
     2555                 * divide by two to soften the effect. */ 
    25802556 
    25812557                if (!lastsync) 
    25822558                { 
     
    25942570                else 
    25952571                    lastsync = false; 
    25962572            } 
     2573            prevrp = buffer->repeat_pict; 
    25972574        } 
    25982575        else 
    25992576        { 
     
    29642941        // Make sure video sync can do it 
    29652942        if (videosync != NULL && m_double_framerate) 
    29662943        { 
    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() * 0.995); 
     2945            if (! m_can_double) { 
    29712946                VERBOSE(VB_IMPORTANT, "Video sync method can't support double " 
    29722947                        "framerate (refresh rate too low for bob deint)"); 
    29732948                FallbackDeint(); 
     
    43434318            (frame_interval>>1) : frame_interval); 
    43444319    } 
    43454320 
    4346     if (videosync != NULL) 
    4347         videosync->SetFrameInterval(frame_interval, m_double_framerate); 
    4348  
    43494321    VERBOSE(VB_PLAYBACK, LOC + "DoPause() -- setting paused"); 
    43504322    paused = actuallypaused = true; 
    43514323    decoderThreadPaused.wakeAll(); 
     
    44224394 
    44234395        m_double_framerate = videoOutput->NeedsDoubleFramerate(); 
    44244396        m_double_process = videoOutput->IsExtraProcessingRequired(); 
    4425         videosync->SetFrameInterval(frame_interval, m_double_framerate); 
    44264397    } 
    44274398 
    44284399    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     * 
     
    10591                                 bool interlaced); 
    10692  protected: 
    10793    static void OffsetTimeval(struct timeval& tv, int offset); 
    108     void UpdateNexttrigger(void); 
    10994    int CalcDelay(void); 
    11095    void KeepPhase(void); 
    11196 
     
    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 */