Ticket #7067: mythtv.2.patch

File mythtv.2.patch, 14.4 KB (added by Davin McCall <davmac@…>, 14 years ago)

Updated patch, applies to current trunk (23321)

  • 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;
     
    233212    return ret_val;
    234213}
    235214
    236 /** \fn VideoSync::KeepPhase()
    237  *  \brief Keep our nexttrigger from drifting too close to the exact retrace.
    238  *
    239  *   If delay is near zero, some frames will be delay < 0 and others
    240  *   delay > 0 which would cause continous rapid fire stuttering.
    241  *   This method is only useful for those sync methods where WaitForFrame
    242  *   targets hardware retrace rather than targeting nexttrigger.
    243  */
    244 void VideoSync::KeepPhase()
    245 {
    246     // cerr << m_delay << endl;
    247     if (m_delay < -(m_refresh_interval/2))
    248         OffsetTimeval(m_nexttrigger, 200);
    249     else if (m_delay > -500)
    250         OffsetTimeval(m_nexttrigger, -2000);
    251 }
    252 
    253215#ifndef _WIN32
    254216#define DRM_VBLANK_RELATIVE 0x1;
    255217
     
    371333        //cerr  << " Delay " << m_delay << endl;
    372334    }
    373335}
    374 
    375 void DRMVideoSync::AdvanceTrigger(void)
    376 {
    377     KeepPhase();
    378     UpdateNexttrigger();
    379 }
    380336#endif /* !_WIN32 */
    381337
    382338#ifndef _WIN32
     
    541497   
    542498#endif /* USING_OPENGL_VSYNC */
    543499}
    544 
    545 void OpenGLVideoSync::AdvanceTrigger(void)
    546 {
    547 #ifdef USING_OPENGL_VSYNC
    548 
    549     KeepPhase();
    550     UpdateNexttrigger();
    551 #endif /* USING_OPENGL_VSYNC */
    552 }
    553500#endif /* !_WIN32 */
    554501
    555502#ifdef __linux__
     
    610557            usleep(m_delay);
    611558    }
    612559}
    613 
    614 void RTCVideoSync::AdvanceTrigger(void)
    615 {
    616     UpdateNexttrigger();
    617 }
    618560#endif /* __linux__ */
    619561
    620562#ifdef USING_VDPAU
     
    650592    vo->SetNextFrameDisplayTimeOffset(m_delay);
    651593}
    652594
    653 void VDPAUVideoSync::AdvanceTrigger(void)
    654 {
    655     UpdateNexttrigger();
    656 }
    657 
    658595#endif
    659596
    660597BusyWaitVideoSync::BusyWaitVideoSync(VideoOutput *vo,
     
    705642    }
    706643}
    707644
    708 void BusyWaitVideoSync::AdvanceTrigger(void)
    709 {
    710     UpdateNexttrigger();
    711 }
    712 
    713645USleepVideoSync::USleepVideoSync(VideoOutput *vo,
    714646                                 int fr, int ri, bool intl) :
    715647    VideoSync(vo, fr, ri, intl)
     
    734666    if (m_delay > 0)
    735667        usleep(m_delay);
    736668}
    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"
     
    967965     m_double_framerate = false;
    968966     m_double_process   = false;
    969967
    970      if (videosync)
    971          videosync->SetFrameInterval(frame_interval, false);
    972 
    973968     if (osd)
    974969         osd->SetFrameInterval(frame_interval);
    975970
     
    10461041    if (interlaced && !m_deint_possible)
    10471042    {
    10481043        m_scan = scan;
    1049         videosync->SetFrameInterval(frame_interval, false);
    10501044        return;
    10511045    }
    10521046
     
    10621056        if (videoOutput->NeedsDoubleFramerate())
    10631057        {
    10641058            m_double_framerate = true;
    1065             videosync->SetFrameInterval(frame_interval, true);
    1066             // Make sure video sync can double frame rate
    1067             m_can_double = videosync->UsesFieldInterval();
     1059            m_can_double = (frame_interval / 2 > videosync->getRefreshInterval() * 1.005);
    10681060            if (!m_can_double)
    10691061            {
    10701062                VERBOSE(VB_IMPORTANT, "Video sync method can't support double "
     
    10811073        {
    10821074            m_double_process = false;
    10831075            m_double_framerate = false;
    1084             videosync->SetFrameInterval(frame_interval, false);
    10851076            videoOutput->SetDeinterlacingEnabled(false);
    10861077            VERBOSE(VB_PLAYBACK, "Disabled deinterlacing");
    10871078        }
     
    23712362void NuppelVideoPlayer::AVSync(void)
    23722363{
    23732364    float diverge = 0.0f;
     2365    int frameDelay = m_double_framerate ? frame_interval / 2 : frame_interval;
    23742366    // attempt to reduce fps for standalone PIP
    23752367    if (player_ctx->IsPIP() && framesPlayed % 2)
    23762368    {
    2377         videosync->WaitForFrame(avsync_adjustment);
    2378         videosync->AdvanceTrigger();
     2369        videosync->WaitForFrame(frameDelay + avsync_adjustment);
    23792370        if (!using_null_videoout)
    23802371            videoOutput->SetFramesPlayed(framesPlayed + 1);
    23812372        return;
     
    23872378        VERBOSE(VB_IMPORTANT, LOC_ERR + "AVSync: No video buffer");
    23882379        return;
    23892380    }
     2381
    23902382    if (videoOutput->IsErrored())
    23912383    {
    23922384        VERBOSE(VB_IMPORTANT, LOC_ERR + "AVSync: "
     
    24092401    if (kScan_Detect == m_scan || kScan_Ignore == m_scan)
    24102402        ps = kScan_Progressive;
    24112403
    2412     bool dropframe = false;
    24132404    if (diverge < -MAXDIVERGE)
    24142405    {
    2415         dropframe = true;
    24162406        // If video is way behind of audio, adjust for it...
    24172407        QString dbg = QString("Video is %1 frames behind audio (too slow), ")
    24182408            .arg(-diverge);
     
    24462436
    24472437        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, QString("AVSync waitforframe %1 %2")
    24482438                .arg(avsync_adjustment).arg(m_double_framerate));
    2449         videosync->WaitForFrame(avsync_adjustment + repeat_delay);
     2439        videosync->WaitForFrame(frameDelay + avsync_adjustment + repeat_delay);
    24502440        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, "AVSync show");
    24512441        if (!resetvideo)
    24522442            videoOutput->Show(ps);
     
    24872477                videoOutput->PrepareFrame(buffer, ps);
    24882478
    24892479            // Display the second field
    2490             videosync->AdvanceTrigger();
    2491 #ifdef NEW_AVSYNC
    2492             videosync->WaitForFrame(avsync_adjustment);
    2493 #else
    2494             videosync->WaitForFrame(0);
    2495 #endif
     2480            videosync->WaitForFrame(frameDelay + avsync_adjustment);
    24962481            if (!resetvideo)
    24972482            {
    24982483                videoOutput->Show(ps);
     
    25072492    }
    25082493    else
    25092494    {
    2510         videosync->WaitForFrame(0);
     2495        videosync->WaitForFrame(frameDelay);
    25112496    }
    25122497
    25132498    if (output_jmeter && output_jmeter->RecordCycleTime())
     
    25182503                .arg(warpfactor).arg(warpfactor_avg));
    25192504    }
    25202505
    2521     if (!dropframe)
    2522         videosync->AdvanceTrigger();
    25232506    avsync_adjustment = 0;
    25242507
    25252508    if (diverge > MAXDIVERGE)
     
    25272510        // If audio is way behind of video, adjust for it...
    25282511        // by cutting the frame rate in half for the length of this frame
    25292512
    2530 #ifdef NEW_AVSYNC
    25312513        avsync_adjustment = refreshrate;
    2532 #else
    2533         avsync_adjustment = frame_interval;
    2534 #endif
    25352514        lastsync = true;
    25362515        VERBOSE(VB_PLAYBACK, LOC +
    25372516                QString("Video is %1 frames ahead of audio,\n"
     
    25632542            prevtc = buffer->timecode;
    25642543            //cerr << delta << " ";
    25652544
     2545            avsync_delay = (buffer->timecode - currentaudiotime) * 1000;//usec
     2546            // prevents major jitter when pts resets during dvd title
     2547            if (avsync_delay > 2000000 && player_ctx->buffer->isDVD())
     2548                avsync_delay = 90000;
     2549            avsync_avg = (avsync_delay + (avsync_avg * 3)) / 4;
     2550
    25662551            // If the timecode is off by a frame (dropped frame) wait to sync
    25672552            if (delta > (int) frame_interval / 1200 &&
    25682553                delta < (int) frame_interval / 1000 * 3 &&
    25692554                prevrp == 0)
    25702555            {
    2571                 //cerr << "+ ";
    2572                 videosync->AdvanceTrigger();
    2573                 if (m_double_framerate)
    2574                     videosync->AdvanceTrigger();
     2556                // wait an extra frame interval
     2557                avsync_adjustment = frame_interval;
    25752558            }
    2576             prevrp = buffer->repeat_pict;
    2577 
    2578             avsync_delay = (buffer->timecode - currentaudiotime) * 1000;//usec
    2579             // prevents major jitter when pts resets during dvd title
    2580             if (avsync_delay > 2000000 && player_ctx->buffer->isDVD())
    2581                 avsync_delay = 90000;
    2582             avsync_avg = (avsync_delay + (avsync_avg * 3)) / 4;
    2583             if (!usevideotimebase)
     2559            else if (!usevideotimebase)
    25842560            {
    2585                 /* If the audio time codes and video diverge, shift
    2586                    the video by one interlaced field (1/2 frame) */
     2561                /* Adjust by the smoothed divergence amount;
     2562                 * divide by two to soften the effect. */
    25872563
    2588                 if (!lastsync)
    2589                 {
    2590                     if (avsync_avg > frame_interval * 3 / 2)
    2591                     {
    2592                         avsync_adjustment = refreshrate;
    2593                         lastsync = true;
    2594                     }
    2595                     else if (avsync_avg < 0 - frame_interval * 3 / 2)
    2596                     {
    2597                         avsync_adjustment = -refreshrate;
    2598                         lastsync = true;
    2599                     }
     2564                if (!lastsync) {
     2565                    avsync_adjustment = avsync_avg / 2;
     2566                    if (avsync_adjustment > frame_interval * 4)
     2567                        avsync_adjustment = frame_interval * 4;
    26002568                }
    26012569                else
    26022570                    lastsync = false;
    26032571            }
     2572            prevrp = buffer->repeat_pict;
    26042573        }
    26052574        else
    26062575        {
     
    29712940        // Make sure video sync can do it
    29722941        if (videosync != NULL && m_double_framerate)
    29732942        {
    2974             videosync->SetFrameInterval(frame_interval, m_double_framerate);
    2975             m_can_double = videosync->UsesFieldInterval();
    2976             if (!m_can_double)
    2977             {
     2943            m_can_double = (frame_interval / 2 > videosync->getRefreshInterval() * 1.005);
     2944            if (! m_can_double) {
    29782945                VERBOSE(VB_IMPORTANT, "Video sync method can't support double "
    29792946                        "framerate (refresh rate too low for bob deint)");
    29802947                FallbackDeint();
     
    43504317            (frame_interval>>1) : frame_interval);
    43514318    }
    43524319
    4353     if (videosync != NULL)
    4354         videosync->SetFrameInterval(frame_interval, m_double_framerate);
    4355 
    43564320    VERBOSE(VB_PLAYBACK, LOC + "DoPause() -- setting paused");
    43574321    paused = actuallypaused = true;
    43584322    decoderThreadPaused.wakeAll();
     
    44294393
    44304394        m_double_framerate = videoOutput->NeedsDoubleFramerate();
    44314395        m_double_process = videoOutput->IsExtraProcessingRequired();
    4432         videosync->SetFrameInterval(frame_interval, m_double_framerate);
    44334396    }
    44344397
    44354398    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     *
     
    10793    static void OffsetTimeval(struct timeval& tv, int offset);
    10894    void UpdateNexttrigger(void);
    10995    int CalcDelay(void);
    110     void KeepPhase(void);
    11196
    11297    VideoOutput *m_video_output;
    11398    int m_frame_interval; // of video
     
    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 */