Ticket #7067: t7067_avsync_improvements_rev2.diff

File t7067_avsync_improvements_rev2.diff, 12.7 KB (added by tralph, 14 years ago)

remove deprecated isDVD() call and fix typo

  • libs/libmythtv/NuppelVideoPlayer.cpp

     
    704704     m_double_framerate = false;
    705705     m_double_process   = false;
    706706
    707      if (videosync)
    708          videosync->SetFrameInterval(frame_interval, false);
    709 
    710707     if (videoOutput)
    711708         videoOutput->FallbackDeint();
    712709}
     
    780777    if (interlaced && !m_deint_possible)
    781778    {
    782779        m_scan = scan;
    783         videosync->SetFrameInterval(frame_interval, false);
    784780        return;
    785781    }
    786782
     
    796792        if (videoOutput->NeedsDoubleFramerate())
    797793        {
    798794            m_double_framerate = true;
    799             videosync->SetFrameInterval(frame_interval, true);
    800             // Make sure video sync can double frame rate
    801             m_can_double = videosync->UsesFieldInterval();
     795            m_can_double = (frame_interval / 2 > videosync->getRefreshInterval() * 0.995);
    802796            if (!m_can_double)
    803797            {
    804798                VERBOSE(VB_IMPORTANT, LOC + "Video sync method can't support "
     
    815809        {
    816810            m_double_process = false;
    817811            m_double_framerate = false;
    818             videosync->SetFrameInterval(frame_interval, false);
    819812            videoOutput->SetDeinterlacingEnabled(false);
    820813            VERBOSE(VB_PLAYBACK, LOC + "Disabled deinterlacing");
    821814        }
     
    15711564void NuppelVideoPlayer::AVSync(bool limit_delay)
    15721565{
    15731566    float diverge = 0.0f;
     1567    int frameDelay = m_double_framerate ? frame_interval / 2 : frame_interval;
    15741568    // attempt to reduce fps for standalone PIP
    15751569    if (player_ctx->IsPIP() && framesPlayed % 2)
    15761570    {
    1577         videosync->WaitForFrame(avsync_adjustment);
    1578         videosync->AdvanceTrigger();
     1571        videosync->WaitForFrame(frameDelay + avsync_adjustment);
    15791572        if (!using_null_videoout)
    15801573            videoOutput->SetFramesPlayed(framesPlayed + 1);
    15811574        return;
     
    16061599    if (kScan_Detect == m_scan || kScan_Ignore == m_scan)
    16071600        ps = kScan_Progressive;
    16081601
    1609     bool dropframe = false;
    16101602    if (diverge < -MAXDIVERGE)
    16111603    {
    1612         dropframe = true;
    16131604        // If video is way behind of audio, adjust for it...
    16141605        QString dbg = QString("Video is %1 frames behind audio (too slow), ")
    16151606            .arg(-diverge);
     
    16431634
    16441635        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, QString("AVSync waitforframe %1 %2")
    16451636                .arg(avsync_adjustment).arg(m_double_framerate));
    1646         videosync->WaitForFrame(avsync_adjustment + repeat_delay);
     1637        videosync->WaitForFrame(frameDelay + avsync_adjustment + repeat_delay);
    16471638        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, "AVSync show");
    16481639        videoOutput->Show(ps);
    16491640
     
    16731664                videoOutput->PrepareFrame(buffer, ps, osd);
    16741665
    16751666            // Display the second field
    1676             videosync->AdvanceTrigger();
    1677             videosync->WaitForFrame(avsync_adjustment);
     1667            videosync->WaitForFrame(frameDelay + avsync_adjustment);
    16781668            videoOutput->Show(ps);
    16791669        }
    16801670
     
    16861676    }
    16871677    else
    16881678    {
    1689         videosync->WaitForFrame(0);
     1679        videosync->WaitForFrame(frameDelay);
    16901680    }
    16911681
    16921682    if (output_jmeter)
    16931683        output_jmeter->RecordCycleTime();
    16941684
    1695     if (!dropframe)
    1696         videosync->AdvanceTrigger();
    16971685    avsync_adjustment = 0;
    16981686
    16991687    if (diverge > MAXDIVERGE)
     
    17281716            prevtc = buffer->timecode;
    17291717            //cerr << delta << " ";
    17301718
     1719            avsync_delay = (buffer->timecode - currentaudiotime) * 1000;//usec
     1720            // prevents major jitter when pts resets during dvd title
     1721            if (avsync_delay > 2000000 && limit_delay)
     1722                avsync_delay = 90000;
     1723            avsync_avg = (avsync_delay + (avsync_avg * 3)) / 4;
     1724
    17311725            // If the timecode is off by a frame (dropped frame) wait to sync
    17321726            if (delta > (int) frame_interval / 1200 &&
    17331727                delta < (int) frame_interval / 1000 * 3 &&
    17341728                prevrp == 0)
    17351729            {
    1736                 //cerr << "+ ";
    1737                 videosync->AdvanceTrigger();
    1738                 if (m_double_framerate)
    1739                     videosync->AdvanceTrigger();
     1730                // wait an extra frame interval
     1731                avsync_adjustment = frame_interval;
    17401732            }
    17411733            prevrp = buffer->repeat_pict;
    17421734
    1743             avsync_delay = (buffer->timecode - currentaudiotime) * 1000;//usec
    1744             // prevents major jitter when pts resets during dvd title
    1745             if (avsync_delay > 2000000 && limit_delay)
    1746                 avsync_delay = 90000;
    1747             avsync_avg = (avsync_delay + (avsync_avg * 3)) / 4;
    17481735
    17491736            /* If the audio time codes and video diverge, shift
    17501737               the video by one interlaced field (1/2 frame) */
     
    17521739            {
    17531740                if (avsync_avg > frame_interval * 3 / 2)
    17541741                {
    1755                     avsync_adjustment = refreshrate;
     1742                    avsync_adjustment += refreshrate;
    17561743                    lastsync = true;
    17571744                }
    17581745                else if (avsync_avg < 0 - frame_interval * 3 / 2)
    17591746                {
    1760                     avsync_adjustment = -refreshrate;
     1747                    avsync_adjustment -= refreshrate;
    17611748                    lastsync = true;
    17621749                }
    17631750            }
     
    19871974        // Make sure video sync can do it
    19881975        if (videosync != NULL && m_double_framerate)
    19891976        {
    1990             videosync->SetFrameInterval(frame_interval, m_double_framerate);
    1991             m_can_double = videosync->UsesFieldInterval();
     1977            m_can_double = (frame_interval / 2 > videosync->getRefreshInterval() * 0.995);
    19921978            if (!m_can_double)
    19931979            {
    19941980                VERBOSE(VB_IMPORTANT, "Video sync method can't support double "
     
    30072993
    30082994        m_double_framerate = videoOutput->NeedsDoubleFramerate();
    30092995        m_double_process = videoOutput->IsExtraProcessingRequired();
    3010         videosync->SetFrameInterval(frame_interval, m_double_framerate);
    30112996    }
    30122997
    30132998    if (normal_speed && audio.HasAudioOut())
  • libs/libmythtv/vsync.cpp

     
    128128    m_delay(-1)
    129129{
    130130    bzero(&m_nexttrigger, sizeof(m_nexttrigger));
    131 
    132     int tolerance = m_refresh_interval / 200;
    133     if (m_interlaced && m_refresh_interval > ((m_frame_interval/2) + tolerance))
    134         m_interlaced = false; // can't display both fields at 2x rate
    135 
    136     //cout << "Frame interval: " << m_frame_interval << endl;
    137131}
    138132
    139133void VideoSync::Start(void)
     
    141135    gettimeofday(&m_nexttrigger, NULL); // now
    142136}
    143137
    144 /** \fn VideoSync::SetFrameInterval(int fr, bool intr)
    145  *  \brief Change frame interval and interlacing attributes
    146  */
    147 void VideoSync::SetFrameInterval(int fr, bool intr)
    148 {
    149     m_frame_interval = fr;
    150     m_interlaced = intr;
    151     int tolerance = m_refresh_interval / 200;
    152     if (m_interlaced && m_refresh_interval > ((m_frame_interval/2) + tolerance))
    153         m_interlaced = false; // can't display both fields at 2x rate
    154 
    155     VERBOSE(VB_PLAYBACK, LOC + QString("Set video sync frame interval to %1")
    156                                        .arg(m_frame_interval));
    157 }
    158 
    159138void VideoSync::OffsetTimeval(struct timeval& tv, int offset)
    160139{
    161140    tv.tv_usec += offset;
     
    171150    }
    172151}
    173152
    174 /** \fn VideoSync::UpdateNexttrigger()
    175  *  \brief Internal method to tells video synchronization method to use
    176  *         the next frame (or field, if interlaced) for CalcDelay()
    177  *         and WaitForFrame().
    178  */
    179 void VideoSync::UpdateNexttrigger()
    180 {
    181     // Offset by frame interval -- if interlaced, only delay by half
    182     // frame interval
    183     if (m_interlaced)
    184         OffsetTimeval(m_nexttrigger, m_frame_interval/2);
    185     else
    186         OffsetTimeval(m_nexttrigger, m_frame_interval);
    187 }
    188 
    189153/** \fn VideoSync::CalcDelay()
    190154 *  \brief Calculates the delay to the next frame.
    191155 *
     
    372336        //cerr << "Wait " << n << " intervals. Count " << blank.request.sequence;
    373337        //cerr  << " Delay " << m_delay << endl;
    374338    }
    375 }
    376339
    377 void DRMVideoSync::AdvanceTrigger(void)
    378 {
    379340    KeepPhase();
    380     UpdateNexttrigger();
    381341}
    382342#endif /* !_WIN32 */
    383343
     
    480440        m_context->WaitForVideoSync((n+1), (frameNum+n)%(n+1), &frameNum);
    481441        m_delay = CalcDelay();
    482442    }
    483 #endif /* USING_OPENGL_VSYNC */
    484 }
    485443
    486 void OpenGLVideoSync::AdvanceTrigger(void)
    487 {
    488 #ifdef USING_OPENGL_VSYNC
    489 
    490444    KeepPhase();
    491     UpdateNexttrigger();
    492445#endif /* USING_OPENGL_VSYNC */
    493446}
    494447#endif /* !_WIN32 */
     
    551504            usleep(m_delay);
    552505    }
    553506}
    554 
    555 void RTCVideoSync::AdvanceTrigger(void)
    556 {
    557     UpdateNexttrigger();
    558 }
    559507#endif /* __linux__ */
    560508
    561509#ifdef USING_VDPAU
     
    590538    VideoOutputVDPAU *vo = (VideoOutputVDPAU *)(m_video_output);
    591539    vo->SetNextFrameDisplayTimeOffset(m_delay);
    592540}
    593 
    594 void VDPAUVideoSync::AdvanceTrigger(void)
    595 {
    596     UpdateNexttrigger();
    597 }
    598 
    599541#endif
    600542
    601543BusyWaitVideoSync::BusyWaitVideoSync(VideoOutput *vo,
     
    646588    }
    647589}
    648590
    649 void BusyWaitVideoSync::AdvanceTrigger(void)
    650 {
    651     UpdateNexttrigger();
    652 }
    653 
    654591USleepVideoSync::USleepVideoSync(VideoOutput *vo,
    655592                                 int fr, int ri, bool intl) :
    656593    VideoSync(vo, fr, ri, intl)
     
    676613        usleep(m_delay);
    677614}
    678615
    679 void USleepVideoSync::AdvanceTrigger(void)
    680 {
    681     UpdateNexttrigger();
    682 }
  • 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;
     77    /// \brief Returns the (minimum) refresh interval of the output device.
     78    int getRefreshInterval(void) const { return m_refresh_interval; }
    8679
    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; }
    93 
    9480    /** \brief Stops VSync; must be called from main thread.
    9581     *
    9682     *   Start(void), WaitForFrame(void), and Stop(void) should
     
    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    MythRenderOpenGL  *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 */