Ticket #7067: t7067_avsync_improvements.diff

File t7067_avsync_improvements.diff, 12.7 KB (added by tralph, 23 months ago)

fix a couple issues with previous patch

  • 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 && player_ctx->buffer->isDVD()) 
     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 */