Ticket #7964: mythtv_smoothsync.3.patch

File mythtv_smoothsync.3.patch, 9.1 KB (added by Mark Spieth, 14 years ago)

vsync fix + predictive skip at any rate

  • mythtv/libs/libmythtv/NuppelVideoPlayer.cpp

    commit 4beb6d77a3fae93785ee5b8482e486b8d258fcc9
    Author: Mark Spieth <mspieth@digivation.com.au>
    Date:   Tue Apr 27 07:51:51 2010 +1000
    
        smoother vsync with predictive frame skipping
    
    diff --git a/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp b/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
    index ce2b45d..88a071b 100644
    a b NuppelVideoPlayer::NuppelVideoPlayer(bool muted) 
    205205      videosync(NULL),              delay(0),
    206206      vsynctol(30/4),               avsync_delay(0),
    207207      avsync_adjustment(0),         avsync_avg(0),
    208       avsync_oldavg(0),             refreshrate(0),
     208      avsync_oldavg(0),             
     209      avsync_predictor(0),          avsync_predictor_enabled(false),
     210      refreshrate(0),
    209211      lastsync(false),              m_playing_slower(false),
    210212      m_stored_audio_stretchfactor(1.0),
    211213      audio_paused(false),
    NuppelVideoPlayer::NuppelVideoPlayer(bool muted) 
    237239    db_prefer708     = gContext->GetNumSetting("Prefer708Captions", 1);
    238240    autocommercialskip = (CommSkipMode)
    239241        gContext->GetNumSetting("AutoCommercialSkip", kCommSkipOff);
     242    usesmoothsync    = gContext->GetNumSetting("UseSmoothSync", 1) != 0;
    240243
    241244    lastIgnoredManualSkip = QDateTime::currentDateTime().addSecs(-10);
    242245
    void NuppelVideoPlayer::SetVideoParams(int width, int height, double fps, 
    11191122        video_frame_rate = fps;
    11201123        float temp_speed = (play_speed == 0.0f) ?
    11211124            audio_stretchfactor : play_speed;
    1122         frame_interval = (int)(1000000.0f / video_frame_rate / temp_speed);
     1125        SetFrameInterval(kScan_Progressive, 1.0 / (video_frame_rate * temp_speed));
    11231126    }
    11241127
    11251128    if (videoOutput)
    float NuppelVideoPlayer::WarpFactor(void) 
    23112314    return divergence;
    23122315}
    23132316
     2317void NuppelVideoPlayer::SetFrameInterval(FrameScanType scan, double frame_period)
     2318{
     2319    frame_interval = (int)(1000000.0f * frame_period + 0.5f);
     2320    avsync_predictor = 0;
     2321    avsync_predictor_enabled = false;
     2322
     2323    VERBOSE(VB_PLAYBACK, LOC + QString("SetFrameInterval ps:%1 scan:%2 usesmoothsync:%3")
     2324            .arg(play_speed).arg(scan).arg(usesmoothsync)
     2325           );
     2326    //if (play_speed <= 1 || play_speed > 2 || scan != kScan_Progressive || !usesmoothsync)
     2327    if (play_speed < 1 || play_speed > 2 || refreshrate <= 0 || !usesmoothsync)
     2328        return;
     2329
     2330    avsync_predictor_enabled = ((frame_interval-(frame_interval/200)) < refreshrate);
     2331}
     2332
    23142333void NuppelVideoPlayer::InitAVSync(void)
    23152334{
    23162335    videosync->Start();
    void NuppelVideoPlayer::InitAVSync(void) 
    23342353                       .arg(refreshrate).arg(frame_interval);
    23352354        VERBOSE(VB_PLAYBACK, msg);
    23362355
     2356        SetFrameInterval(m_scan, 1.0 / (video_frame_rate * play_speed));
     2357
    23372358        // try to get preferential scheduling, but ignore if we fail to.
    23382359        myth_nice(-19);
    23392360    }
    void NuppelVideoPlayer::AVSync(void) 
    23812402        ps = kScan_Progressive;
    23822403
    23832404    bool dropframe = false;
     2405    QString dbg;
     2406
     2407    if (avsync_predictor_enabled)
     2408    {
     2409        avsync_predictor += frame_interval;
     2410        if (avsync_predictor >= refreshrate)
     2411        {
     2412            int refreshperiodsinframe = avsync_predictor/refreshrate;
     2413            avsync_predictor -= refreshrate * refreshperiodsinframe;
     2414        }
     2415        else
     2416        {
     2417            dropframe = true;
     2418            dbg = "A/V predict drop frame, ";
     2419        }
     2420    }
     2421
    23842422    if (diverge < -MAXDIVERGE)
    23852423    {
    23862424        dropframe = true;
    23872425        // If video is way behind of audio, adjust for it...
    2388         QString dbg = QString("Video is %1 frames behind audio (too slow), ")
     2426        dbg = QString("Video is %1 frames behind audio (too slow), ")
    23892427            .arg(-diverge);
     2428    }
    23902429
     2430    if (dropframe)
     2431    {
    23912432        // Reset A/V Sync
    23922433        lastsync = true;
    23932434
    void NuppelVideoPlayer::AVSync(void) 
    25172558#if 1
    25182559        VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, QString(
    25192560                    "A/V timecodes audio %1 video %2 frameinterval %3 "
    2520                     "avdel %4 avg %5 tcoffset %6")
     2561                    "avdel %4 avg %5 tcoffset %6"
     2562                    " avp %7 avpen %8"
     2563                    )
    25212564                .arg(currentaudiotime)
    25222565                .arg(buffer->timecode)
    25232566                .arg(frame_interval)
    25242567                .arg(buffer->timecode - currentaudiotime)
    25252568                .arg(avsync_avg)
    25262569                .arg(tc_wrap[TC_AUDIO])
     2570                .arg(avsync_predictor)
     2571                .arg(avsync_predictor_enabled)
    25272572                 );
    25282573#endif
    25292574        if (currentaudiotime != 0 && buffer->timecode != 0)
    void NuppelVideoPlayer::AVSync(void) 
    25322577            // last->timecode
    25332578            int delta = (int)((buffer->timecode - prevtc)/play_speed) - (frame_interval / 1000);
    25342579            prevtc = buffer->timecode;
    2535             //cerr << delta << " ";
    25362580
    25372581            // If the timecode is off by a frame (dropped frame) wait to sync
    25382582            if (delta > (int) frame_interval / 1200 &&
    void NuppelVideoPlayer::AVSync(void) 
    25402584                prevrp == 0)
    25412585            {
    25422586                //cerr << "+ ";
     2587                VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, QString("A/V delay %1").arg(delta));
    25432588                videosync->AdvanceTrigger();
    25442589                if (m_double_framerate)
    25452590                    videosync->AdvanceTrigger();
    void NuppelVideoPlayer::AVSync(void) 
    25582603            {
    25592604                if (avsync_avg > frame_interval * 3 / 2)
    25602605                {
    2561                     avsync_adjustment = refreshrate;
     2606                    avsync_adjustment += refreshrate;
    25622607                    lastsync = true;
     2608                    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, "A/V avg high extend");
    25632609                }
    25642610                else if (avsync_avg < 0 - frame_interval * 3 / 2)
    25652611                {
    2566                     avsync_adjustment = -refreshrate;
     2612                    avsync_adjustment += -refreshrate;
    25672613                    lastsync = true;
     2614                    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, "A/V avg high skip");
    25682615                }
    25692616            }
    25702617            else
    void NuppelVideoPlayer::AVSync(void) 
    25742621        {
    25752622            avsync_avg = 0;
    25762623            avsync_oldavg = 0;
     2624            avsync_predictor = 0;
    25772625        }
    25782626    }
    25792627    else
    void NuppelVideoPlayer::DoPause(void) 
    42244272    }
    42254273
    42264274    float temp_speed = audio_stretchfactor;
    4227     frame_interval = (int)(1000000.0 * ffrew_skip / video_frame_rate / temp_speed);
     4275    SetFrameInterval(m_scan, ffrew_skip / (video_frame_rate * temp_speed));
    42284276    VERBOSE(VB_PLAYBACK, QString("rate: %1 speed: %2 skip: %3 = interval %4")
    42294277                                 .arg(video_frame_rate).arg(temp_speed)
    42304278                                 .arg(ffrew_skip).arg(frame_interval));
    void NuppelVideoPlayer::DoPlay(void) 
    42864334        ClearAfterSeek();
    42874335    }
    42884336
    4289     frame_interval = (int) (1000000.0f * ffrew_skip / video_frame_rate /
    4290                             play_speed);
     4337    SetFrameInterval(m_scan, ffrew_skip / (video_frame_rate * play_speed));
    42914338
    42924339    VERBOSE(VB_PLAYBACK, LOC + "DoPlay: " +
    42934340            QString("rate: %1 speed: %2 skip: %3 => new interval %4")
  • mythtv/libs/libmythtv/NuppelVideoPlayer.h

    diff --git a/mythtv/libs/libmythtv/NuppelVideoPlayer.h b/mythtv/libs/libmythtv/NuppelVideoPlayer.h
    index d19ff73..57fab97 100644
    a b class MPUBLIC NuppelVideoPlayer : public CC608Reader, public CC708Reader 
    519519    float WarpFactor(void);
    520520    void  WrapTimecode(long long &timecode, TCTypes tc_type);
    521521    void  InitAVSync(void);
     522    void  SetFrameInterval(FrameScanType scan, double speed);
    522523    void  AVSync(void);
    523524    void  FallbackDeint(void);
    524525    void  CheckExtraAudioDecode(void);
    class MPUBLIC NuppelVideoPlayer : public CC608Reader, public CC708Reader 
    805806    int        avsync_adjustment;
    806807    int        avsync_avg;
    807808    int        avsync_oldavg;
     809    bool       usesmoothsync;
     810    int        avsync_predictor;
     811    bool       avsync_predictor_enabled;
    808812    int        refreshrate;
    809813    bool       lastsync;
    810814    bool       m_playing_slower;
  • mythtv/libs/libmythtv/vsync.cpp

    diff --git a/mythtv/libs/libmythtv/vsync.cpp b/mythtv/libs/libmythtv/vsync.cpp
    index 060402d..2d9691d 100644
    a b void DRMVideoSync::WaitForFrame(int sync_delay) 
    360360    if (m_delay > 0)
    361361    {
    362362        // Wait for any remaining retrace intervals in one pass.
    363         int n = m_delay / m_refresh_interval + 1;
     363        int n = (m_delay + m_refresh_interval - 1) / m_refresh_interval;
    364364
    365365        drm_wait_vblank_t blank;
    366366        blank.request.type = DRM_VBLANK_RELATIVE;
    void OpenGLVideoSync::WaitForFrame(int sync_delay) 
    533533    // Wait for any remaining retrace intervals in one pass.
    534534    if (m_delay > 0)
    535535    {
    536         uint n = m_delay / m_refresh_interval + 1;
     536        uint n = (m_delay + m_refresh_interval - 1) / m_refresh_interval;
    537537        err = gMythGLXWaitVideoSyncSGI((n+1), (frameNum+n)%(n+1), &frameNum);
    538538        checkGLSyncError(msg2, err);
    539539        m_delay = CalcDelay();