Ticket #7067: mythtv.patch

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

New patch for trunk. Solves problem for DVDs without menus.

  • 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;
     
    221200    return ret_val;
    222201}
    223202
    224 /** \fn VideoSync::KeepPhase()
    225  *  \brief Keep our nexttrigger from drifting too close to the exact retrace.
    226  *
    227  *   If delay is near zero, some frames will be delay < 0 and others
    228  *   delay > 0 which would cause continous rapid fire stuttering.
    229  *   This method is only useful for those sync methods where WaitForFrame
    230  *   targets hardware retrace rather than targeting nexttrigger.
    231  */
    232 void VideoSync::KeepPhase()
    233 {
    234     // cerr << m_delay << endl;
    235     if (m_delay < -(m_refresh_interval/2))
    236         OffsetTimeval(m_nexttrigger, 200);
    237     else if (m_delay > -500)
    238         OffsetTimeval(m_nexttrigger, -2000);
    239 }
    240 
    241203#ifndef _WIN32
    242204#define DRM_VBLANK_RELATIVE 0x1;
    243205
     
    359321        //cerr  << " Delay " << m_delay << endl;
    360322    }
    361323}
    362 
    363 void DRMVideoSync::AdvanceTrigger(void)
    364 {
    365     KeepPhase();
    366     UpdateNexttrigger();
    367 }
    368324#endif /* !_WIN32 */
    369325
    370326#ifndef _WIN32
     
    529485   
    530486#endif /* USING_OPENGL_VSYNC */
    531487}
    532 
    533 void OpenGLVideoSync::AdvanceTrigger(void)
    534 {
    535 #ifdef USING_OPENGL_VSYNC
    536 
    537     KeepPhase();
    538     UpdateNexttrigger();
    539 #endif /* USING_OPENGL_VSYNC */
    540 }
    541488#endif /* !_WIN32 */
    542489
    543490#ifdef __linux__
     
    598545            usleep(m_delay);
    599546    }
    600547}
    601 
    602 void RTCVideoSync::AdvanceTrigger(void)
    603 {
    604     UpdateNexttrigger();
    605 }
    606548#endif /* __linux__ */
    607549
    608550#ifdef USING_VDPAU
     
    638580    vo->SetNextFrameDisplayTimeOffset(m_delay);
    639581}
    640582
    641 void VDPAUVideoSync::AdvanceTrigger(void)
    642 {
    643     UpdateNexttrigger();
    644 }
    645 
    646583#endif
    647584
    648585BusyWaitVideoSync::BusyWaitVideoSync(VideoOutput *vo,
     
    692629    }
    693630}
    694631
    695 void BusyWaitVideoSync::AdvanceTrigger(void)
    696 {
    697     UpdateNexttrigger();
    698 }
    699 
    700632USleepVideoSync::USleepVideoSync(VideoOutput *vo,
    701633                                 int fr, int ri, bool intl) :
    702634    VideoSync(vo, fr, ri, intl)
     
    721653    if (m_delay > 0)
    722654        usleep(m_delay);
    723655}
    724 
    725 void USleepVideoSync::AdvanceTrigger(void)
    726 {
    727     UpdateNexttrigger();
    728 }
  • 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"
     
    966964     m_double_framerate = false;
    967965     m_double_process   = false;
    968966
    969      if (videosync)
    970          videosync->SetFrameInterval(frame_interval, false);
    971 
    972967     if (osd)
    973968         osd->SetFrameInterval(frame_interval);
    974969
     
    10451040    if (interlaced && !m_deint_possible)
    10461041    {
    10471042        m_scan = scan;
    1048         videosync->SetFrameInterval(frame_interval, false);
    10491043        return;
    10501044    }
    10511045
     
    10611055        if (videoOutput->NeedsDoubleFramerate())
    10621056        {
    10631057            m_double_framerate = true;
    1064             videosync->SetFrameInterval(frame_interval, true);
    1065             // Make sure video sync can double frame rate
    1066             m_can_double = videosync->UsesFieldInterval();
    1067             if (!m_can_double)
    1068             {
     1058            m_can_double = (frame_interval / 2 > videosync->getRefreshInterval() * 1.005);
     1059            if (! m_can_double) {
    10691060                VERBOSE(VB_IMPORTANT, "Video sync method can't support double "
    10701061                        "framerate (refresh rate too low for bob deint)");
    10711062                FallbackDeint();
     
    10801071        {
    10811072            m_double_process = false;
    10821073            m_double_framerate = false;
    1083             videosync->SetFrameInterval(frame_interval, false);
    10841074            videoOutput->SetDeinterlacingEnabled(false);
    10851075            VERBOSE(VB_PLAYBACK, "Disabled deinterlacing");
    10861076        }
     
    23682358void NuppelVideoPlayer::AVSync(void)
    23692359{
    23702360    float diverge = 0.0f;
     2361    int frameDelay = m_double_framerate ? frame_interval / 2 : frame_interval;
    23712362    // attempt to reduce fps for standalone PIP
    23722363    if (player_ctx->IsPIP() && framesPlayed % 2)
    23732364    {
    2374         videosync->WaitForFrame(avsync_adjustment);
    2375         videosync->AdvanceTrigger();
     2365        videosync->WaitForFrame(frameDelay + avsync_adjustment);
    23762366        if (!using_null_videoout)
    23772367            videoOutput->SetFramesPlayed(framesPlayed + 1);
    23782368        return;
     
    23842374        VERBOSE(VB_IMPORTANT, LOC_ERR + "AVSync: No video buffer");
    23852375        return;
    23862376    }
     2377
    23872378    if (videoOutput->IsErrored())
    23882379    {
    23892380        VERBOSE(VB_IMPORTANT, LOC_ERR + "AVSync: "
     
    24412432
    24422433        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, QString("AVSync waitforframe %1 %2")
    24432434                .arg(avsync_adjustment).arg(m_double_framerate));
    2444         videosync->WaitForFrame(avsync_adjustment);
     2435        videosync->WaitForFrame(frameDelay + avsync_adjustment);
    24452436        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, "AVSync show");
    24462437        if (!resetvideo)
    24472438            videoOutput->Show(ps);
     
    24822473                videoOutput->PrepareFrame(buffer, ps);
    24832474
    24842475            // Display the second field
    2485             videosync->AdvanceTrigger();
    2486 #ifdef NEW_AVSYNC
    2487             videosync->WaitForFrame(avsync_adjustment);
    2488 #else
    2489             videosync->WaitForFrame(0);
    2490 #endif
     2476            videosync->WaitForFrame(frameDelay + avsync_adjustment);
    24912477            if (!resetvideo)
    24922478            {
    24932479                videoOutput->Show(ps);
     
    24962482    }
    24972483    else
    24982484    {
    2499         videosync->WaitForFrame(0);
     2485        videosync->WaitForFrame(frameDelay);
    25002486    }
    25012487
    25022488    if (output_jmeter && output_jmeter->RecordCycleTime())
     
    25072493                .arg(warpfactor).arg(warpfactor_avg));
    25082494    }
    25092495
    2510     videosync->AdvanceTrigger();
    25112496    avsync_adjustment = 0;
    25122497
    25132498    if (diverge > MAXDIVERGE)
     
    25152500        // If audio is way behind of video, adjust for it...
    25162501        // by cutting the frame rate in half for the length of this frame
    25172502
    2518 #ifdef NEW_AVSYNC
    25192503        avsync_adjustment = refreshrate;
    2520 #else
    2521         avsync_adjustment = frame_interval;
    2522 #endif
    25232504        lastsync = true;
    25242505        VERBOSE(VB_PLAYBACK, LOC +
    25252506                QString("Video is %1 frames ahead of audio,\n"
     
    25512532            prevtc = buffer->timecode;
    25522533            //cerr << delta << " ";
    25532534
    2554             // If the timecode is off by a frame (dropped frame) wait to sync
    2555             if (delta > (int) frame_interval / 1200 &&
    2556                 delta < (int) frame_interval / 1000 * 3)
    2557             {
    2558                 //cerr << "+ ";
    2559                 videosync->AdvanceTrigger();
    2560                 if (m_double_framerate)
    2561                     videosync->AdvanceTrigger();
    2562             }
    2563 
    25642535            avsync_delay = (buffer->timecode - currentaudiotime) * 1000;//usec
    25652536            // prevents major jitter when pts resets during dvd title
    25662537            if (avsync_delay > 2000000 && player_ctx->buffer->isDVD())
    25672538                avsync_delay = 90000;
    25682539            avsync_avg = (avsync_delay + (avsync_avg * 3)) / 4;
    2569             if (!usevideotimebase)
     2540
     2541            // If the timecode is off by a frame (dropped frame) wait to sync
     2542            if (delta > (int) frame_interval / 1200 &&
     2543                delta < (int) frame_interval / 1000 * 3)
    25702544            {
    2571                 /* If the audio time codes and video diverge, shift
    2572                    the video by one interlaced field (1/2 frame) */
     2545                // wait an extra frame interval
     2546                avsync_adjustment = frame_interval;
     2547            }
     2548            else if (!usevideotimebase)
     2549            {
     2550                /* Adjust by the smoothed divergence amount;
     2551                 * dividy by two to soften the effect. */
    25732552
    2574                 if (!lastsync)
    2575                 {
    2576                     if (avsync_avg > frame_interval * 3 / 2)
    2577                     {
    2578                         avsync_adjustment = refreshrate;
    2579                         lastsync = true;
    2580                     }
    2581                     else if (avsync_avg < 0 - frame_interval * 3 / 2)
    2582                     {
    2583                         avsync_adjustment = -refreshrate;
    2584                         lastsync = true;
    2585                     }
     2553                if (!lastsync) {
     2554                    avsync_adjustment = avsync_avg / 2;
     2555                    if (avsync_adjustment > frame_interval * 4)
     2556                        avsync_adjustment = frame_interval * 4;
    25862557                }
    25872558                else
    25882559                    lastsync = false;
     
    29572928        // Make sure video sync can do it
    29582929        if (videosync != NULL && m_double_framerate)
    29592930        {
    2960             videosync->SetFrameInterval(frame_interval, m_double_framerate);
    2961             m_can_double = videosync->UsesFieldInterval();
    2962             if (!m_can_double)
    2963             {
     2931            m_can_double = (frame_interval / 2 > videosync->getRefreshInterval() * 1.005);
     2932            if (! m_can_double) {
    29642933                VERBOSE(VB_IMPORTANT, "Video sync method can't support double "
    29652934                        "framerate (refresh rate too low for bob deint)");
    29662935                FallbackDeint();
     
    43334302            (frame_interval>>1) : frame_interval);
    43344303    }
    43354304
    4336     if (videosync != NULL)
    4337         videosync->SetFrameInterval(frame_interval, m_double_framerate);
    4338 
    43394305    VERBOSE(VB_PLAYBACK, LOC + "DoPause() -- setting paused");
    43404306    paused = actuallypaused = true;
    43414307    decoderThreadPaused.wakeAll();
     
    44124378
    44134379        m_double_framerate = videoOutput->NeedsDoubleFramerate();
    44144380        m_double_process = videoOutput->IsExtraProcessingRequired();
    4415         videosync->SetFrameInterval(frame_interval, m_double_framerate);
    44164381    }
    44174382
    44184383    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 */