Ticket #7964: smoother-vsync-vsync-opt.11-trunk.patch

File smoother-vsync-vsync-opt.11-trunk.patch, 11.9 KB (added by jpoet, 15 years ago)

Updated for 206bde055d2d440a730270bf15c34dcf42992d8f

  • mythtv/libs/libmythtv/vsync.cpp

    diff --git a/mythtv/libs/libmythtv/vsync.cpp b/mythtv/libs/libmythtv/vsync.cpp
    index 1f08fc5..75528bc 100644
    a b VideoSync::VideoSync(VideoOutput *video_output,  
    130130                     bool halve_frame_interval) :
    131131    m_video_output(video_output),   m_frame_interval(frameint),
    132132    m_refresh_interval(refreshint), m_interlaced(halve_frame_interval),
    133     m_delay(-1)
     133    m_nexttrigger(0),
     134    m_delay(-1),
     135    m_synchronous(false)
    134136{
    135     bzero(&m_nexttrigger, sizeof(m_nexttrigger));
     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));
    136145}
    137146
    138 void VideoSync::Start(void)
     147int64_t GetTime(void)
    139148{
    140     gettimeofday(&m_nexttrigger, NULL); // now
     149    struct timeval now_tv;
     150    gettimeofday(&now_tv, NULL); // now
     151    return now_tv.tv_sec * 1000000LL + now_tv.tv_usec;
    141152}
    142153
    143 void VideoSync::OffsetTimeval(struct timeval& tv, int offset)
     154void VideoSync::Start(void)
    144155{
    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();
    156157}
    157158
    158159/** \fn VideoSync::CalcDelay()
    void VideoSync::OffsetTimeval(struct timeval& tv, int offset)  
    168169 */
    169170int VideoSync::CalcDelay()
    170171{
    171     struct timeval now;
    172     gettimeofday(&now, NULL);
     172    int64_t now = GetTime();
    173173    //cout << "CalcDelay: next: " << timeval_str(m_nexttrigger) << " now "
    174174    // << timeval_str(now) << endl;
    175175
    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;
    178177
    179178    //cout << "delay " << ret_val << endl;
    180179
    int VideoSync::CalcDelay()  
    186185            ret_val = m_frame_interval * 4;
    187186
    188187        // 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;
    192190    }
    193191
    194     if (ret_val < -m_frame_interval)
     192    if ((ret_val < -m_frame_interval) && (m_frame_interval >= m_refresh_interval))
    195193    {
    196194        ret_val = -m_frame_interval;
    197195
    198196        // 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;
    202199    }
    203200
    204201    return ret_val;
    int VideoSync::CalcDelay()  
    215212void VideoSync::KeepPhase()
    216213{
    217214    // 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    }
    222229}
    223230
    224231#ifndef _WIN32
    void DRMVideoSync::Start(void)  
    308315    VideoSync::Start();
    309316}
    310317
    311 void DRMVideoSync::WaitForFrame(int sync_delay)
     318int DRMVideoSync::WaitForFrame(int sync_delay)
    312319{
    313320    // Offset for externally-provided A/V sync delay
    314     OffsetTimeval(m_nexttrigger, sync_delay);
     321    m_nexttrigger += sync_delay;
    315322
    316323    m_delay = CalcDelay();
    317324    //cerr << "WaitForFrame at : " << m_delay;
    void DRMVideoSync::WaitForFrame(int sync_delay)  
    331338    if (m_delay > 0)
    332339    {
    333340        // 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;
    335342
    336343        drm_wait_vblank_t blank;
    337344        blank.request.type = DRM_VBLANK_RELATIVE;
    void DRMVideoSync::WaitForFrame(int sync_delay)  
    341348        //cerr << "Wait " << n << " intervals. Count " << blank.request.sequence;
    342349        //cerr  << " Delay " << m_delay << endl;
    343350    }
     351    return m_delay;
    344352
    345353    KeepPhase();
    346354}
    void OpenGLVideoSync::Start(void)  
    412420#endif /* USING_OPENGL_VSYNC */
    413421}
    414422
    415 void OpenGLVideoSync::WaitForFrame(int sync_delay)
     423int OpenGLVideoSync::WaitForFrame(int sync_delay)
    416424{
    417425    (void) sync_delay;
    418426#ifdef USING_OPENGL_VSYNC
     427//#define GLVSYNCDEBUG
     428#ifdef GLVSYNCDEBUG
     429    int refreshcount = 0;
     430#endif
    419431    const QString msg1("First A/V Sync"), msg2("Second A/V Sync");
    420     OffsetTimeval(m_nexttrigger, sync_delay);
     432    m_nexttrigger += sync_delay;
    421433
    422434    if (m_video_output && m_video_output->IsEmbedding())
    423435    {
    424436        m_delay = CalcDelay();
    425437        if (m_delay > 0)
    426438            usleep(m_delay);
    427         return;
     439        return 0;
    428440    }
    429441
    430442    if (!m_context)
    431         return;
     443        return 0;
    432444
    433445    unsigned int frameNum = m_context->GetVideoSyncCount();
    434446
     447#ifdef GLVSYNCDEBUG
     448    int delay1 = m_delay;
     449    int delay2;
     450#endif
    435451    // Always sync to the next retrace execpt when we are very late.
    436452    if ((m_delay = CalcDelay()) > -(m_refresh_interval/2))
    437453    {
     454#ifdef GLVSYNCDEBUG
     455        delay2 = m_delay;
     456#endif
    438457        m_context->WaitForVideoSync(2, (frameNum+1)%2 ,&frameNum);
    439458        m_delay = CalcDelay();
     459#ifdef GLVSYNCDEBUG
     460        refreshcount++;
     461#endif
    440462    }
     463#ifdef GLVSYNCDEBUG
     464    else
     465        delay2 = m_delay;
     466#endif
    441467
     468#ifdef GLVSYNCDEBUG
     469    int delay3 = m_delay;
     470#endif
    442471    // Wait for any remaining retrace intervals in one pass.
    443472    if (m_delay > 0)
    444473    {
    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;
    446476        m_context->WaitForVideoSync((n+1), (frameNum+n)%(n+1), &frameNum);
     477#ifdef GLVSYNCDEBUG
     478        refreshcount += (int)n;
     479#endif
    447480        m_delay = CalcDelay();
    448481    }
     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;
    449495
    450496    KeepPhase();
     497#ifdef GLVSYNCDEBUG
     498    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, "VS: AdvanceTrigger");
     499#endif
    451500#endif /* USING_OPENGL_VSYNC */
    452501}
    453502#endif /* !_WIN32 */
    bool RTCVideoSync::TryInit(void)  
    494543    return true;
    495544}
    496545
    497 void RTCVideoSync::WaitForFrame(int sync_delay)
     546int RTCVideoSync::WaitForFrame(int sync_delay)
    498547{
    499     OffsetTimeval(m_nexttrigger, sync_delay);
     548    m_nexttrigger += sync_delay;
    500549
    501550    m_delay = CalcDelay();
    502551
    void RTCVideoSync::WaitForFrame(int sync_delay)  
    509558        if ((val < 0) && (m_delay > 0))
    510559            usleep(m_delay);
    511560    }
     561    return 0;
    512562}
    513563#endif /* __linux__ */
    514564
    bool VDPAUVideoSync::TryInit(void)  
    532582    return true;
    533583}
    534584
    535 void VDPAUVideoSync::WaitForFrame(int sync_delay)
     585int VDPAUVideoSync::WaitForFrame(int sync_delay)
    536586{
    537587    // Offset for externally-provided A/V sync delay
    538     OffsetTimeval(m_nexttrigger, sync_delay);
     588    m_nexttrigger += sync_delay;
    539589    m_delay = CalcDelay();
    540590
    541591    if (m_delay < 0)
    void VDPAUVideoSync::WaitForFrame(int sync_delay)  
    543593
    544594    VideoOutputVDPAU *vo = (VideoOutputVDPAU *)(m_video_output);
    545595    vo->SetNextFrameDisplayTimeOffset(m_delay);
     596    return 0;
    546597}
    547598#endif
    548599
    bool BusyWaitVideoSync::TryInit(void)  
    563614    return true;
    564615}
    565616
    566 void BusyWaitVideoSync::WaitForFrame(int sync_delay)
     617int BusyWaitVideoSync::WaitForFrame(int sync_delay)
    567618{
    568619    // Offset for externally-provided A/V sync delay
    569     OffsetTimeval(m_nexttrigger, sync_delay);
     620    m_nexttrigger += sync_delay;
    570621
    571622    m_delay = CalcDelay();
    572623
    void BusyWaitVideoSync::WaitForFrame(int sync_delay)  
    592643        if (cnt > 1)
    593644            m_cheat -= 200;
    594645    }
     646    return 0;
    595647}
    596648
    597649USleepVideoSync::USleepVideoSync(VideoOutput *vo,
    bool USleepVideoSync::TryInit(void)  
    609661    return true;
    610662}
    611663
    612 void USleepVideoSync::WaitForFrame(int sync_delay)
     664int USleepVideoSync::WaitForFrame(int sync_delay)
    613665{
    614666    // Offset for externally-provided A/V sync delay
    615     OffsetTimeval(m_nexttrigger, sync_delay);
     667    m_nexttrigger += sync_delay;
    616668
    617669    m_delay = CalcDelay();
    618670    if (m_delay > 0)
    619671        usleep(m_delay);
     672    return 0;
    620673}
    621674
  • mythtv/libs/libmythtv/vsync.h

    diff --git a/mythtv/libs/libmythtv/vsync.h b/mythtv/libs/libmythtv/vsync.h
    index 156cdad..6c185dc 100644
    a b class VideoSync  
    6464    virtual void Start(void);
    6565
    6666    /** \brief Waits for next a frame or field.
     67     *   Returns delay to real frame timing in usec
    6768     *
    6869     *   Start(void), WaitForFrame(void), and Stop(void) should
    6970     *   always be called from same thread, to prevent bad
    class VideoSync  
    7273     *  \param sync_delay time until the desired frame or field
    7374     *  \sa CalcDelay(void), KeepPhase(void)
    7475     */
    75     virtual void WaitForFrame(int sync_delay) = 0;
     76    virtual int WaitForFrame(int sync_delay) = 0;
    7677
    7778    /// \brief Returns the (minimum) refresh interval of the output device.
    7879    int getRefreshInterval(void) const { return m_refresh_interval; }
    class VideoSync  
    9293                                 uint frame_interval, uint refresh_interval,
    9394                                 bool interlaced);
    9495  protected:
    95     static void OffsetTimeval(struct timeval& tv, int offset);
    9696    int CalcDelay(void);
    9797    void KeepPhase(void);
    9898
    class VideoSync  
    100100    int m_frame_interval; // of video
    101101    int m_refresh_interval; // of display
    102102    bool m_interlaced;
    103     struct timeval m_nexttrigger;
     103    int64_t m_nexttrigger;
    104104    int m_delay;
     105    bool m_synchronous;
    105106   
    106107    static int m_forceskip;
    107108};
    class DRMVideoSync : public VideoSync  
    123124    QString getName(void) const { return QString("DRM"); }
    124125    bool TryInit(void);
    125126    void Start(void);
    126     void WaitForFrame(int sync_delay);
     127    int WaitForFrame(int sync_delay);
    127128
    128129  private:
    129130    int m_dri_fd;
    class OpenGLVideoSync : public VideoSync  
    164165    QString getName(void) const { return QString("SGI OpenGL"); }
    165166    bool TryInit(void);
    166167    void Start(void);
    167     void WaitForFrame(int sync_delay);
     168    int WaitForFrame(int sync_delay);
    168169
    169170  private:
    170171    MythRenderOpenGL  *m_context;
    class RTCVideoSync : public VideoSync  
    192193
    193194    QString getName(void) const { return QString("RTC"); }
    194195    bool TryInit(void);
    195     void WaitForFrame(int sync_delay);
     196    int WaitForFrame(int sync_delay);
    196197
    197198  private:
    198199    int m_rtcfd;
    class VDPAUVideoSync : public VideoSync  
    212213
    213214    QString getName(void) const { return QString("VDPAU"); }
    214215    bool TryInit(void);
    215     void WaitForFrame(int sync_delay);
     216    int WaitForFrame(int sync_delay);
    216217
    217218  private:
    218219};
    class BusyWaitVideoSync : public VideoSync  
    239240
    240241    QString getName(void) const { return QString("USleep with busy wait"); }
    241242    bool TryInit(void);
    242     void WaitForFrame(int sync_delay);
     243    int WaitForFrame(int sync_delay);
    243244
    244245  private:
    245246    int m_cheat;
    class USleepVideoSync : public VideoSync  
    266267
    267268    QString getName(void) const { return QString("USleep"); }
    268269    bool TryInit(void);
    269     void WaitForFrame(int sync_delay);
     270    int WaitForFrame(int sync_delay);
    270271};
    271272#endif /* VSYNC_H_INCLUDED */