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

File smoother-vsync-vsync-opt.11.patch, 12.1 KB (added by Mark Spieth, 16 years ago)
  • mythtv/libs/libmythtv/vsync.cpp

    commit 08ce0149ce184d26173e34e0a6888543e981b830
    Author: Mark Spieth <mspieth@digivation.com.au>
    Date:   Sun Aug 15 17:35:09 2010 +1000
    
        vsync calc optimizations and pll out
    
    diff --git a/mythtv/libs/libmythtv/vsync.cpp b/mythtv/libs/libmythtv/vsync.cpp
    index 41d3736..ddedceb 100644
    a b VideoSync::VideoSync(VideoOutput *video_output,  
    128128                     bool halve_frame_interval) :
    129129    m_video_output(video_output),   m_frame_interval(frameint),
    130130    m_refresh_interval(refreshint), m_interlaced(halve_frame_interval),
    131     m_delay(-1)
     131    m_nexttrigger(0),
     132    m_delay(-1),
     133    m_synchronous(false)
    132134{
    133     bzero(&m_nexttrigger, sizeof(m_nexttrigger));
     135    int fieldint = frameint;
     136    if (halve_frame_interval)
     137        fieldint /= 2;
     138    double sync_factor = fieldint * 2.0f / refreshint;
     139    sync_factor = sync_factor - round(sync_factor);
     140    m_synchronous = (sync_factor >= -0.005) && (sync_factor <= 0.005);
     141    VERBOSE(VB_PLAYBACK, LOC + QString("Set video sync frame interval to %1 (synced:%2)")
     142                                 .arg(m_frame_interval).arg(m_synchronous));
    134143}
    135144
    136 void VideoSync::Start(void)
     145int64_t GetTime(void)
    137146{
    138     gettimeofday(&m_nexttrigger, NULL); // now
     147    struct timeval now_tv;
     148    gettimeofday(&now_tv, NULL); // now
     149    return now_tv.tv_sec * 1000000LL + now_tv.tv_usec;
    139150}
    140151
    141 void VideoSync::OffsetTimeval(struct timeval& tv, int offset)
     152void VideoSync::Start(void)
    142153{
    143     tv.tv_usec += offset;
    144     while (tv.tv_usec > 999999)
    145     {
    146         tv.tv_sec++;
    147         tv.tv_usec -= 1000000;
    148     }
    149     while (tv.tv_usec < 0)
    150     {
    151         tv.tv_sec--;
    152         tv.tv_usec += 1000000;
    153     }
     154    m_nexttrigger = GetTime();
    154155}
    155156
    156157/** \fn VideoSync::CalcDelay()
    void VideoSync::OffsetTimeval(struct timeval& tv, int offset)  
    166167 */
    167168int VideoSync::CalcDelay()
    168169{
    169     struct timeval now;
    170     gettimeofday(&now, NULL);
     170    int64_t now = GetTime();
    171171    //cout << "CalcDelay: next: " << timeval_str(m_nexttrigger) << " now "
    172172    // << timeval_str(now) << endl;
    173173
    174     int ret_val = (m_nexttrigger.tv_sec - now.tv_sec) * 1000000 +
    175                   (m_nexttrigger.tv_usec - now.tv_usec);
     174    int ret_val = m_nexttrigger - now;
    176175
    177176    //cout << "delay " << ret_val << endl;
    178177
    int VideoSync::CalcDelay()  
    184183            ret_val = m_frame_interval * 4;
    185184
    186185        // set nexttrigger to our new target time
    187         m_nexttrigger.tv_sec = now.tv_sec;
    188         m_nexttrigger.tv_usec = now.tv_usec;
    189         OffsetTimeval(m_nexttrigger, ret_val);
     186        m_nexttrigger = now;
     187        m_nexttrigger += ret_val;
    190188    }
    191189
    192     if (ret_val < -m_frame_interval)
     190    if ((ret_val < -m_frame_interval) && (m_frame_interval >= m_refresh_interval))
    193191    {
    194192        ret_val = -m_frame_interval;
    195193
    196194        // set nexttrigger to our new target time
    197         m_nexttrigger.tv_sec = now.tv_sec;
    198         m_nexttrigger.tv_usec = now.tv_usec;
    199         OffsetTimeval(m_nexttrigger, ret_val);
     195        m_nexttrigger = now;
     196        m_nexttrigger += ret_val;
    200197    }
    201198
    202199    return ret_val;
    int VideoSync::CalcDelay()  
    213210void VideoSync::KeepPhase()
    214211{
    215212    // cerr << m_delay << endl;
    216     if (m_delay < -(m_refresh_interval/2))
    217         OffsetTimeval(m_nexttrigger, 200);
    218     else if (m_delay > -500)
    219         OffsetTimeval(m_nexttrigger, -2000);
     213    if (m_synchronous)
     214    {
     215        if (m_delay < -(m_refresh_interval - 500))
     216            m_nexttrigger += 200;
     217        else if (m_delay > -500)
     218            m_nexttrigger += -2000;
     219    }
     220    else
     221    {
     222        if (m_delay < -(m_refresh_interval + 500))
     223            m_nexttrigger += 200;
     224        else if (m_delay >= 0)
     225            m_nexttrigger += -2000;
     226    }
    220227}
    221228
    222229#ifndef _WIN32
    void DRMVideoSync::Start(void)  
    306313    VideoSync::Start();
    307314}
    308315
    309 void DRMVideoSync::WaitForFrame(int sync_delay)
     316int DRMVideoSync::WaitForFrame(int sync_delay)
    310317{
    311318    // Offset for externally-provided A/V sync delay
    312     OffsetTimeval(m_nexttrigger, sync_delay);
     319    m_nexttrigger += sync_delay;
    313320
    314321    m_delay = CalcDelay();
    315322    //cerr << "WaitForFrame at : " << m_delay;
    void DRMVideoSync::WaitForFrame(int sync_delay)  
    329336    if (m_delay > 0)
    330337    {
    331338        // Wait for any remaining retrace intervals in one pass.
    332         int n = m_delay / m_refresh_interval + 1;
     339        int n = (m_delay + m_refresh_interval - 1) / m_refresh_interval;
    333340
    334341        drm_wait_vblank_t blank;
    335342        blank.request.type = DRM_VBLANK_RELATIVE;
    void DRMVideoSync::WaitForFrame(int sync_delay)  
    339346        //cerr << "Wait " << n << " intervals. Count " << blank.request.sequence;
    340347        //cerr  << " Delay " << m_delay << endl;
    341348    }
     349    return m_delay;
    342350
    343351    KeepPhase();
    344352}
    void OpenGLVideoSync::Start(void)  
    409417#endif /* USING_OPENGL_VSYNC */
    410418}
    411419
    412 void OpenGLVideoSync::WaitForFrame(int sync_delay)
     420int OpenGLVideoSync::WaitForFrame(int sync_delay)
    413421{
    414422    (void) sync_delay;
    415423#ifdef USING_OPENGL_VSYNC
     424//#define GLVSYNCDEBUG
     425#ifdef GLVSYNCDEBUG
     426    int refreshcount = 0;
     427#endif
    416428    const QString msg1("First A/V Sync"), msg2("Second A/V Sync");
    417     OffsetTimeval(m_nexttrigger, sync_delay);
     429    m_nexttrigger += sync_delay;
    418430
    419431    if (m_video_output && m_video_output->IsEmbedding())
    420432    {
    421433        m_delay = CalcDelay();
    422434        if (m_delay > 0)
    423435            usleep(m_delay);
    424         return;
     436        return 0;
    425437    }
    426438
    427439    if (!m_context)
    428         return;
     440        return 0;
    429441
    430442    unsigned int frameNum = m_context->GetVideoSyncCount();
    431443
     444#ifdef GLVSYNCDEBUG
     445    int delay1 = m_delay;
     446    int delay2;
     447#endif
    432448    // Always sync to the next retrace execpt when we are very late.
    433449    if ((m_delay = CalcDelay()) > -(m_refresh_interval/2))
    434450    {
     451#ifdef GLVSYNCDEBUG
     452        delay2 = m_delay;
     453#endif
    435454        m_context->WaitForVideoSync(2, (frameNum+1)%2 ,&frameNum);
    436455        m_delay = CalcDelay();
     456#ifdef GLVSYNCDEBUG
     457        refreshcount++;
     458#endif
    437459    }
     460#ifdef GLVSYNCDEBUG
     461    else
     462        delay2 = m_delay;
     463#endif
    438464
     465#ifdef GLVSYNCDEBUG
     466    int delay3 = m_delay;
     467#endif
    439468    // Wait for any remaining retrace intervals in one pass.
    440469    if (m_delay > 0)
    441470    {
    442         uint n = m_delay / m_refresh_interval + 1;
     471        //uint n = m_delay / m_refresh_interval + 1;
     472        uint n = (m_delay + m_refresh_interval - 1) / m_refresh_interval;
    443473        m_context->WaitForVideoSync((n+1), (frameNum+n)%(n+1), &frameNum);
     474#ifdef GLVSYNCDEBUG
     475        refreshcount += (int)n;
     476#endif
    444477        m_delay = CalcDelay();
    445478    }
     479#ifdef GLVSYNCDEBUG
     480    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, QString("VS: WFF: ri:%1 fi:%2 delay1:%3 delay2:%4 delay3:%5 skip:%6 finaldelay:%7")
     481            .arg(m_refresh_interval)
     482            .arg(m_frame_interval)
     483            .arg(delay1)
     484            .arg(delay2)
     485            .arg(delay3)
     486            .arg(refreshcount)
     487            .arg(m_delay)
     488           );
     489#endif
     490
     491    return m_delay;
    446492
    447493    KeepPhase();
     494#ifdef GLVSYNCDEBUG
     495    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, "VS: AdvanceTrigger");
     496#endif
    448497#endif /* USING_OPENGL_VSYNC */
    449498}
    450499#endif /* !_WIN32 */
    bool RTCVideoSync::TryInit(void)  
    491540    return true;
    492541}
    493542
    494 void RTCVideoSync::WaitForFrame(int sync_delay)
     543int RTCVideoSync::WaitForFrame(int sync_delay)
    495544{
    496     OffsetTimeval(m_nexttrigger, sync_delay);
     545    m_nexttrigger += sync_delay;
    497546
    498547    m_delay = CalcDelay();
    499548
    void RTCVideoSync::WaitForFrame(int sync_delay)  
    506555        if ((val < 0) && (m_delay > 0))
    507556            usleep(m_delay);
    508557    }
     558    return 0;
    509559}
    510560#endif /* __linux__ */
    511561
    bool VDPAUVideoSync::TryInit(void)  
    529579    return true;
    530580}
    531581
    532 void VDPAUVideoSync::WaitForFrame(int sync_delay)
     582int VDPAUVideoSync::WaitForFrame(int sync_delay)
    533583{
    534584    // Offset for externally-provided A/V sync delay
    535     OffsetTimeval(m_nexttrigger, sync_delay);
     585    m_nexttrigger += sync_delay;
    536586    m_delay = CalcDelay();
    537587
    538588    if (m_delay < 0)
    void VDPAUVideoSync::WaitForFrame(int sync_delay)  
    540590
    541591    VideoOutputVDPAU *vo = (VideoOutputVDPAU *)(m_video_output);
    542592    vo->SetNextFrameDisplayTimeOffset(m_delay);
     593    return 0;
    543594}
    544595#endif
    545596
    bool BusyWaitVideoSync::TryInit(void)  
    560611    return true;
    561612}
    562613
    563 void BusyWaitVideoSync::WaitForFrame(int sync_delay)
     614int BusyWaitVideoSync::WaitForFrame(int sync_delay)
    564615{
    565616    // Offset for externally-provided A/V sync delay
    566     OffsetTimeval(m_nexttrigger, sync_delay);
     617    m_nexttrigger += sync_delay;
    567618
    568619    m_delay = CalcDelay();
    569620
    void BusyWaitVideoSync::WaitForFrame(int sync_delay)  
    589640        if (cnt > 1)
    590641            m_cheat -= 200;
    591642    }
     643    return 0;
    592644}
    593645
    594646USleepVideoSync::USleepVideoSync(VideoOutput *vo,
    bool USleepVideoSync::TryInit(void)  
    606658    return true;
    607659}
    608660
    609 void USleepVideoSync::WaitForFrame(int sync_delay)
     661int USleepVideoSync::WaitForFrame(int sync_delay)
    610662{
    611663    // Offset for externally-provided A/V sync delay
    612     OffsetTimeval(m_nexttrigger, sync_delay);
     664    m_nexttrigger += sync_delay;
    613665
    614666    m_delay = CalcDelay();
    615667    if (m_delay > 0)
    616668        usleep(m_delay);
     669    return 0;
    617670}
    618671
  • mythtv/libs/libmythtv/vsync.h

    diff --git a/mythtv/libs/libmythtv/vsync.h b/mythtv/libs/libmythtv/vsync.h
    index f3f267f..47b75c0 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  
    9091                                 uint frame_interval, uint refresh_interval,
    9192                                 bool interlaced);
    9293  protected:
    93     static void OffsetTimeval(struct timeval& tv, int offset);
    9494    int CalcDelay(void);
    9595    void KeepPhase(void);
    9696
    class VideoSync  
    9898    int m_frame_interval; // of video
    9999    int m_refresh_interval; // of display
    100100    bool m_interlaced;
    101     struct timeval m_nexttrigger;
     101    int64_t m_nexttrigger;
    102102    int m_delay;
     103    bool m_synchronous;
    103104   
    104105    static int m_forceskip;
    105106};
    class DRMVideoSync : public VideoSync  
    121122    QString getName(void) const { return QString("DRM"); }
    122123    bool TryInit(void);
    123124    void Start(void);
    124     void WaitForFrame(int sync_delay);
     125    int WaitForFrame(int sync_delay);
    125126
    126127  private:
    127128    int m_dri_fd;
    class OpenGLVideoSync : public VideoSync  
    162163    QString getName(void) const { return QString("SGI OpenGL"); }
    163164    bool TryInit(void);
    164165    void Start(void);
    165     void WaitForFrame(int sync_delay);
     166    int WaitForFrame(int sync_delay);
    166167
    167168  private:
    168169    MythRenderOpenGL  *m_context;
    class RTCVideoSync : public VideoSync  
    190191
    191192    QString getName(void) const { return QString("RTC"); }
    192193    bool TryInit(void);
    193     void WaitForFrame(int sync_delay);
     194    int WaitForFrame(int sync_delay);
    194195
    195196  private:
    196197    int m_rtcfd;
    class VDPAUVideoSync : public VideoSync  
    210211
    211212    QString getName(void) const { return QString("VDPAU"); }
    212213    bool TryInit(void);
    213     void WaitForFrame(int sync_delay);
     214    int WaitForFrame(int sync_delay);
    214215
    215216  private:
    216217};
    class BusyWaitVideoSync : public VideoSync  
    237238
    238239    QString getName(void) const { return QString("USleep with busy wait"); }
    239240    bool TryInit(void);
    240     void WaitForFrame(int sync_delay);
     241    int WaitForFrame(int sync_delay);
    241242
    242243  private:
    243244    int m_cheat;
    class USleepVideoSync : public VideoSync  
    264265
    265266    QString getName(void) const { return QString("USleep"); }
    266267    bool TryInit(void);
    267     void WaitForFrame(int sync_delay);
     268    int WaitForFrame(int sync_delay);
    268269};
    269270#endif /* VSYNC_H_INCLUDED */