Ticket #7964: mythtv-smoothsync-extra-trunk-01.patch

File mythtv-smoothsync-extra-trunk-01.patch, 14.5 KB (added by tralph, 13 years ago)

Remaining extra code for smooth sync feature - needs review - updated for 49065221b40b3bc928bb372f57bb63b26077a871

  • mythtv/libs/libmythtv/mythplayer.cpp

    diff --git a/mythtv/libs/libmythtv/mythplayer.cpp b/mythtv/libs/libmythtv/mythplayer.cpp
    index 0e0e208..b6dad9e 100644
    a b void MythPlayer::InitAVSync(void) 
    16821682    }
    16831683}
    16841684
     1685int64_t MythPlayer::AVSyncGetAudiotime(void)
     1686{
     1687    int64_t currentaudiotime = 0;
     1688    if (normal_speed)
     1689    {
     1690        currentaudiotime = audio.GetAudioTime();
     1691    }
     1692    return currentaudiotime;
     1693}
     1694
    16851695#define MAXDIVERGE  3.0f
    16861696#define DIVERGELIMIT 30.0f
    16871697void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay)
    void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) 
    16981708
    16991709    float diverge = 0.0f;
    17001710    int frameDelay = m_double_framerate ? frame_interval / 2 : frame_interval;
     1711    int vsync_delay_clock = 0;
     1712    int64_t currentaudiotime = 0;
    17011713
    17021714    // attempt to reduce fps for standalone PIP
    17031715    if (player_ctx->IsPIP() && framesPlayed % 2)
    void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) 
    17581770        // Reset A/V Sync
    17591771        lastsync = true;
    17601772
     1773        currentaudiotime = AVSyncGetAudiotime();
    17611774        if (!using_null_videoout &&
    17621775            videoOutput->hasHWAcceleration() &&
    17631776           !videoOutput->IsSyncLocked())
    void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) 
    17861799        osdLock.unlock();
    17871800        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, LOC + QString("AVSync waitforframe %1 %2")
    17881801                .arg(avsync_adjustment).arg(m_double_framerate));
    1789         videosync->WaitForFrame(frameDelay + avsync_adjustment + repeat_delay);
     1802        vsync_delay_clock = videosync->WaitForFrame
     1803                            (frameDelay + avsync_adjustment + repeat_delay);
     1804        currentaudiotime = AVSyncGetAudiotime();
    17901805        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, LOC + "AVSync show");
    17911806        videoOutput->Show(ps);
    17921807
    void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) 
    18151830            videoOutput->PrepareFrame(buffer, ps, osd);
    18161831            osdLock.unlock();
    18171832            // Display the second field
    1818             videosync->WaitForFrame(frameDelay + avsync_adjustment);
     1833            vsync_delay_clock = videosync->WaitForFrame(frameDelay + avsync_adjustment);
    18191834            videoOutput->Show(ps);
    18201835        }
    18211836
    void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) 
    18271842    }
    18281843    else
    18291844    {
    1830         videosync->WaitForFrame(frameDelay);
     1845        vsync_delay_clock = videosync->WaitForFrame(frameDelay);
     1846        currentaudiotime = AVSyncGetAudiotime();
    18311847    }
    18321848
    18331849    if (output_jmeter)
    1834         output_jmeter->RecordCycleTime();
    1835 
     1850    {
     1851        if (output_jmeter->RecordCycleTime())
     1852        {
     1853            VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + QString("A/V avsync_delay: %1, "
     1854                    "avsync_avg: %2")
     1855                    .arg(avsync_delay / 1000).arg(avsync_avg / 1000)
     1856                    );
     1857        }
     1858    }
    18361859    avsync_adjustment = 0;
    18371860
    18381861    if (diverge > MAXDIVERGE)
    18391862    {
    18401863        // If audio is way behind of video, adjust for it...
    18411864        // by cutting the frame rate in half for the length of this frame
    1842         avsync_adjustment = refreshrate;
     1865        avsync_adjustment = frame_interval;
    18431866        lastsync = true;
    18441867        VERBOSE(VB_PLAYBACK, LOC +
    18451868                QString("Video is %1 frames ahead of audio,\n"
    void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) 
    18481871
    18491872    if (audio.HasAudioOut() && normal_speed)
    18501873    {
     1874        // must be sampled here due to Show delays
    18511875        int64_t currentaudiotime = audio.GetAudioTime();
    1852         VERBOSE(VB_TIMESTAMP, LOC + QString(
     1876        VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + QString(
    18531877                    "A/V timecodes audio %1 video %2 frameinterval %3 "
    18541878                    "avdel %4 avg %5 tcoffset %6 "
    1855                     "avp %7 avpen %8")
     1879                    "avp %7 avpen %8 avdc %9")
    18561880                .arg(currentaudiotime)
    18571881                .arg(timecode)
    18581882                .arg(frame_interval)
    1859                 .arg(timecode - currentaudiotime)
     1883                .arg(timecode - currentaudiotime - (int)(vsync_delay_clock*audio.GetStretchFactor()+500)/1000)
    18601884                .arg(avsync_avg)
    18611885                .arg(tc_wrap[TC_AUDIO])
    18621886                .arg(avsync_predictor)
    18631887                .arg(avsync_predictor_enabled)
     1888                .arg(vsync_delay_clock)
    18641889                 );
    18651890        if (currentaudiotime != 0 && timecode != 0)
    18661891        { // currentaudiotime == 0 after a seek
    18671892            // The time at the start of this frame (ie, now) is given by
    18681893            // last->timecode
    1869             int delta = (int)((timecode - prevtc)/play_speed) - (frame_interval / 1000);
    1870             prevtc = timecode;
    1871             //cerr << delta << " ";
    1872 
    1873             // If the timecode is off by a frame (dropped frame) wait to sync
    1874             if (delta > (int) frame_interval / 1200 &&
    1875                 delta < (int) frame_interval / 1000 * 3 &&
    1876                 prevrp == 0)
     1894            if (prevtc != 0)
    18771895            {
    1878                 // wait an extra frame interval
    1879                 avsync_adjustment += frame_interval;
     1896                int delta = (int)((timecode - prevtc)/play_speed) - (frame_interval / 1000);
     1897                // If the timecode is off by a frame (dropped frame) wait to sync
     1898                if (delta > (int) frame_interval / 1200 &&
     1899                    delta < (int) frame_interval / 1000 * 3 &&
     1900                    prevrp == 0)
     1901                {
     1902                    // wait an extra frame interval
     1903                    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + QString("A/V delay %1").arg(delta));
     1904                    avsync_adjustment += frame_interval;
     1905                }
    18801906            }
     1907            prevtc = timecode;
    18811908            prevrp = repeat_pict;
    18821909
    1883             avsync_delay = (timecode - currentaudiotime) * 1000;//usec
     1910            avsync_delay = (timecode - currentaudiotime) * 1000 - (int)(vsync_delay_clock*audio.GetStretchFactor());  //usec
    18841911            // prevents major jitter when pts resets during dvd title
    18851912            if (avsync_delay > 2000000 && limit_delay)
    18861913                avsync_delay = 90000;
    18871914            avsync_avg = (avsync_delay + (avsync_avg * 3)) / 4;
    18881915
     1916            int avsync_used = avsync_avg;
     1917            if (labs(avsync_used) > labs(avsync_delay))
     1918                avsync_used = avsync_delay;
     1919
    18891920            /* If the audio time codes and video diverge, shift
    18901921               the video by one interlaced field (1/2 frame) */
    18911922            if (!lastsync)
    18921923            {
    1893                 if (avsync_avg > frame_interval * 3 / 2)
     1924                if (avsync_used > refreshrate)
    18941925                {
    18951926                    avsync_adjustment += refreshrate;
    1896                     lastsync = true;
     1927                    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + "A/V avg high extend");
    18971928                }
    1898                 else if (avsync_avg < 0 - frame_interval * 3 / 2)
     1929                else if (avsync_avg < 0 - refreshrate)
    18991930                {
    19001931                    avsync_adjustment -= refreshrate;
    1901                     lastsync = true;
     1932                    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + "A/V avg high skip");
    19021933                }
    19031934            }
    19041935            else
    void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) 
    19091940            ResetAVSync();
    19101941        }
    19111942    }
     1943    else
     1944    {
     1945        VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + QString("A/V no sync proc ns:%1").arg(normal_speed));
     1946    }
    19121947}
    19131948
    19141949void MythPlayer::RefreshPauseFrame(void)
  • mythtv/libs/libmythtv/mythplayer.h

    diff --git a/mythtv/libs/libmythtv/mythplayer.h b/mythtv/libs/libmythtv/mythplayer.h
    index c4744bf..293f8ac 100644
    a b class MPUBLIC MythPlayer 
    514514    void  InitAVSync(void);
    515515    virtual void AVSync(VideoFrame *buffer, bool limit_delay = false);
    516516    void  ResetAVSync(void);
     517    int64_t AVSyncGetAudiotime(void);
    517518    void  SetFrameInterval(FrameScanType scan, double speed);
    518519    void  FallbackDeint(void);
    519520    void  CheckExtraAudioDecode(void);
  • mythtv/libs/libmythtv/vsync.cpp

    diff --git a/mythtv/libs/libmythtv/vsync.cpp b/mythtv/libs/libmythtv/vsync.cpp
    index 6e1b891..9d0a005 100644
    a b int VideoSync::CalcDelay() 
    178178        m_nexttrigger = now + ret_val;
    179179    }
    180180
    181     if (ret_val < -m_frame_interval)
     181    if (ret_val < -m_frame_interval && m_frame_interval >= m_refresh_interval)
    182182    {
    183183        ret_val = -m_frame_interval;
    184184
    void DRMVideoSync::Start(void) 
    293293    VideoSync::Start();
    294294}
    295295
    296 void DRMVideoSync::WaitForFrame(int sync_delay)
     296int DRMVideoSync::WaitForFrame(int sync_delay)
    297297{
    298298    // Offset for externally-provided A/V sync delay
    299299    m_nexttrigger += sync_delay;
    void DRMVideoSync::WaitForFrame(int sync_delay) 
    316316    if (m_delay > 0)
    317317    {
    318318        // Wait for any remaining retrace intervals in one pass.
    319         int n = m_delay / m_refresh_interval + 1;
     319        int n = (m_delay + m_refresh_interval - 1) / m_refresh_interval;
    320320
    321321        drm_wait_vblank_t blank;
    322322        blank.request.type = DRM_VBLANK_RELATIVE;
    void DRMVideoSync::WaitForFrame(int sync_delay) 
    327327        //cerr  << " Delay " << m_delay << endl;
    328328    }
    329329
     330    return m_delay;
     331
    330332    KeepPhase();
    331333}
    332334#endif /* !_WIN32 */
    void OpenGLVideoSync::Start(void) 
    397399#endif /* USING_OPENGL_VSYNC */
    398400}
    399401
    400 void OpenGLVideoSync::WaitForFrame(int sync_delay)
     402int OpenGLVideoSync::WaitForFrame(int sync_delay)
    401403{
    402404    (void) sync_delay;
    403405#ifdef USING_OPENGL_VSYNC
    void OpenGLVideoSync::WaitForFrame(int sync_delay) 
    409411        m_delay = CalcDelay();
    410412        if (m_delay > 0)
    411413            usleep(m_delay);
    412         return;
     414        return 0;
    413415    }
    414416
    415417    if (!m_context)
    416         return;
     418        return 0;
    417419
    418420    unsigned int frameNum = m_context->GetVideoSyncCount();
    419421
    void OpenGLVideoSync::WaitForFrame(int sync_delay) 
    427429    // Wait for any remaining retrace intervals in one pass.
    428430    if (m_delay > 0)
    429431    {
    430         uint n = m_delay / m_refresh_interval + 1;
     432        uint n = (m_delay + m_refresh_interval - 1) / m_refresh_interval;
    431433        m_context->WaitForVideoSync((n+1), (frameNum+n)%(n+1), &frameNum);
    432434        m_delay = CalcDelay();
    433435    }
    434436
     437    return m_delay;
     438
    435439    KeepPhase();
    436440#endif /* USING_OPENGL_VSYNC */
    437441}
    bool RTCVideoSync::TryInit(void) 
    479483    return true;
    480484}
    481485
    482 void RTCVideoSync::WaitForFrame(int sync_delay)
     486int RTCVideoSync::WaitForFrame(int sync_delay)
    483487{
    484488    m_nexttrigger += sync_delay;
    485489
    void RTCVideoSync::WaitForFrame(int sync_delay) 
    494498        if ((val < 0) && (m_delay > 0))
    495499            usleep(m_delay);
    496500    }
     501    return 0;
    497502}
    498503#endif /* __linux__ */
    499504
    bool VDPAUVideoSync::TryInit(void) 
    517522    return true;
    518523}
    519524
    520 void VDPAUVideoSync::WaitForFrame(int sync_delay)
     525int VDPAUVideoSync::WaitForFrame(int sync_delay)
    521526{
    522527    // Offset for externally-provided A/V sync delay
    523528    m_nexttrigger += sync_delay;
    void VDPAUVideoSync::WaitForFrame(int sync_delay) 
    528533
    529534    VideoOutputVDPAU *vo = (VideoOutputVDPAU *)(m_video_output);
    530535    vo->SetNextFrameDisplayTimeOffset(m_delay);
     536    return 0;
    531537}
    532538#endif
    533539
    bool BusyWaitVideoSync::TryInit(void) 
    548554    return true;
    549555}
    550556
    551 void BusyWaitVideoSync::WaitForFrame(int sync_delay)
     557int BusyWaitVideoSync::WaitForFrame(int sync_delay)
    552558{
    553559    // Offset for externally-provided A/V sync delay
    554560    m_nexttrigger += sync_delay;
    void BusyWaitVideoSync::WaitForFrame(int sync_delay) 
    577583        if (cnt > 1)
    578584            m_cheat -= 200;
    579585    }
     586    return 0;
    580587}
    581588
    582589USleepVideoSync::USleepVideoSync(VideoOutput *vo,
    bool USleepVideoSync::TryInit(void) 
    594601    return true;
    595602}
    596603
    597 void USleepVideoSync::WaitForFrame(int sync_delay)
     604int USleepVideoSync::WaitForFrame(int sync_delay)
    598605{
    599606    // Offset for externally-provided A/V sync delay
    600607    m_nexttrigger += sync_delay;
    void USleepVideoSync::WaitForFrame(int sync_delay) 
    602609    m_delay = CalcDelay();
    603610    if (m_delay > 0)
    604611        usleep(m_delay);
     612    return 0;
    605613}
    606614
  • mythtv/libs/libmythtv/vsync.h

    diff --git a/mythtv/libs/libmythtv/vsync.h b/mythtv/libs/libmythtv/vsync.h
    index 310d866..3db298b 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 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 */