Ticket #7067: mythtv.4.patch

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

Another patch. Same as the last, but corrects the tolerance for checking whether framerate can be doubled.

  • 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() * 1.005);
     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 */