Ticket #13383: 20190213_1544_catchup_plus.patch

File 20190213_1544_catchup_plus.patch, 10.6 KB (added by Peter Bennett, 20 months ago)

Adds a setting (Setup->Video->Playback->General->Live TV wait. Setting a vaule in there causes a pause for that number of milliseconds when starting Live TV. Also reduce the number of Live TV catch-up messages.

  • mythtv/libs/libmythtv/mythplayer.cpp

    diff --git a/mythtv/libs/libmythtv/mythplayer.cpp b/mythtv/libs/libmythtv/mythplayer.cpp
    index 5b80c452a3b..db5bb6f06eb 100644
    a b MythPlayer::MythPlayer(PlayerFlags flags) 
    223223      rtcbase(0),
    224224      maxtcval(0), maxtcframes(0),
    225225      numdroppedframes(0),
     226      prior_audiotimecode(0),
     227      prior_videotimecode(0),
    226228      // LiveTVChain stuff
    227229      m_tv(nullptr),                isDummy(false),
    228230      // Counter for buffering messages
    bool MythPlayer::Play(float speed, bool normal, bool unpauseaudio) 
    415417        return false;
    416418    }
    417419    rtcbase = 0;
     420    prior_audiotimecode = 0;
     421    prior_videotimecode = 0;
    418422    SetEof(kEofStateNone);
    419423    UnpauseBuffer();
    420424    UnpauseDecoder();
    void MythPlayer::ResetAVSync(void) 
    18061810    prevtc = 0;
    18071811    avsync_next = avsync_interval;      // Frames till next sync check
    18081812    rtcbase = 0;
     1813    prior_audiotimecode = 0;
     1814    prior_videotimecode = 0;
    18091815    LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC + "A/V sync reset");
    18101816}
    18111817
    void MythPlayer::InitAVSync(void) 
    18221828    // Number of frames over which to average time divergence
    18231829    avsync_averaging=4;
    18241830    rtcbase = 0;
     1831    prior_audiotimecode = 0;
     1832    prior_videotimecode = 0;
    18251833
    18261834    // Special averaging default of 60 for OpenMAX passthru
    18271835    QString device = gCoreContext->GetSetting("AudioOutputDevice","");
    void wait_for_time(int64_t framedue) 
    21702178        QThread::usleep(delay);
    21712179}
    21722180
    2173 #define AVSYNC_MAX_LATE 1000000
     2181#define AVSYNC_MAX_LATE 10000000
    21742182void MythPlayer::AVSync2(VideoFrame *buffer)
    21752183{
    21762184    if (videoOutput->IsErrored())
    void MythPlayer::AVSync2(VideoFrame *buffer) 
    21802188        SetErrored(tr("Failed to initialize A/V Sync"));
    21812189        return;
    21822190    }
    2183     int64_t audiotimecode = audio.GetAudioTime();
    21842191    int64_t videotimecode = 0;
    21852192
    21862193    bool dropframe = false;
    void MythPlayer::AVSync2(VideoFrame *buffer) 
    21912198    int64_t unow = 0;
    21922199    int64_t lateness = 0;
    21932200    int64_t playspeed1000 = (float)1000 / play_speed;
     2201    bool reset = false;
    21942202
    21952203    while (framedue == 0)
    21962204    {
    2197         bool reset = false;
    21982205        if (buffer)
    21992206        {
    22002207            videotimecode = buffer->timecode & 0x0000ffffffffffff;
    void MythPlayer::AVSync2(VideoFrame *buffer) 
    22102217        {
    22112218            // cater for DVB radio
    22122219            if (videotimecode == 0)
    2213                 videotimecode = audiotimecode;
     2220                videotimecode = audio.GetAudioTime();;
    22142221            // On first frame we get nothing, so exit out.
    22152222            if (videotimecode == 0)
    22162223                return;
    void MythPlayer::AVSync2(VideoFrame *buffer) 
    22442251        if (lateness > 30000)
    22452252            dropframe = !FlagIsSet(kMusicChoice) && numdroppedframes < 10;
    22462253
    2247         if (lateness <= 30000 && audiotimecode > 0 && normal_speed && !FlagIsSet(kMusicChoice))
     2254        if (lateness <= 30000 && prior_audiotimecode > 0
     2255            && prior_videotimecode > 0 && normal_speed && !FlagIsSet(kMusicChoice))
    22482256        {
    22492257            // Get video in sync with audio
    2250             audio_adjustment = audiotimecode - videotimecode;
    2251             int sign = audio_adjustment < 0 ? -1 : 1;
    2252             if (audio_adjustment * sign > 40)
     2258            audio_adjustment = prior_audiotimecode - prior_videotimecode;
     2259            // If there is excess audio - throw it away.
     2260            if (audio_adjustment < -200)
    22532261            {
    2254                 // adjust by AVSyncIncrementMS milliseconds at a time (range 1-40)
    2255                 rtcbase -= (int64_t)1000000 * avsync2adjustms * sign / playspeed1000;
     2262                audio.Reset();
     2263                audio_adjustment = 0;
     2264            }
     2265            int sign = audio_adjustment < 0 ? -1 : 1;
     2266            int64_t fix_amount = audio_adjustment * sign;
     2267            if (fix_amount > avsync2adjustms)
     2268                fix_amount = avsync2adjustms;
     2269            // Faster catch-up when off by more than 200 ms
     2270            if (audio_adjustment * sign > 200)
     2271                // fix the sync within 15 - 20 frames
     2272                fix_amount = audio_adjustment * sign / 15;
     2273            int64_t speedup1000 = (float)1000 * play_speed;
     2274            rtcbase -= (int64_t)1000000 * fix_amount * sign / speedup1000;
     2275            if (audio_adjustment * sign > 20 || (framesPlayed % 400 == 0))
    22562276                LOG(VB_PLAYBACK, LOG_INFO, LOC +
    22572277                    QString("AV Sync, audio ahead by %1 ms").arg(audio_adjustment));
    2258             }
    2259             if (audio_adjustment > 1000)
     2278            if (audio_adjustment > 200)
    22602279                pause_audio = true;
    22612280        }
    22622281        // sanity check - reset rtcbase if time codes have gone crazy.
    void MythPlayer::AVSync2(VideoFrame *buffer) 
    22772296            reset = true;
    22782297        }
    22792298    }
    2280 
     2299    prior_videotimecode = videotimecode;
    22812300    disp_timecode = videotimecode;
    22822301
    22832302    output_jmeter && output_jmeter->RecordCycleTime();
    void MythPlayer::AVSync2(VideoFrame *buffer) 
    23072326        audio.Pause(true);
    23082327    }
    23092328
    2310     LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC +
    2311         QString("A/V timecodes audio=%1 video=%2 frameinterval=%3 "
    2312                 "audioadj=%4 tcoffset=%5 unow=%6 udue=%7")
    2313             .arg(audiotimecode)
    2314             .arg(videotimecode)
    2315             .arg(frame_interval)
    2316             .arg(audio_adjustment)
    2317             .arg(tc_wrap[TC_AUDIO])
    2318             .arg(unow)
    2319             .arg(framedue)
    2320                 );
    23212329
    23222330    if (dropframe)
    23232331        numdroppedframes++;
    void MythPlayer::AVSync2(VideoFrame *buffer) 
    23382346        // the primary PBP will become out of sync
    23392347        if (!player_ctx->IsPBP() || player_ctx->IsPrimaryPBP())
    23402348            wait_for_time(framedue);
     2349        // get time codes for calculating difference next time
     2350        prior_audiotimecode = audio.GetAudioTime();
    23412351        videoOutput->Show(ps);
    23422352        if (videoOutput->IsErrored())
    23432353        {
    void MythPlayer::AVSync2(VideoFrame *buffer) 
    23732383    }
    23742384    else
    23752385        wait_for_time(framedue);
     2386
     2387    LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC +
     2388        QString("A/V timecodes audio=%1 video=%2 frameinterval=%3 "
     2389                "audioadj=%4 tcoffset=%5 unow=%6 udue=%7")
     2390            .arg(prior_audiotimecode)
     2391            .arg(prior_videotimecode)
     2392            .arg(frame_interval)
     2393            .arg(audio_adjustment)
     2394            .arg(tc_wrap[TC_AUDIO])
     2395            .arg(unow)
     2396            .arg(framedue)
     2397                );
     2398
    23762399}
    23772400
    23782401void MythPlayer::RefreshPauseFrame(void)
    bool MythPlayer::PrebufferEnoughFrames(int min_buffers) 
    24512474    if (!videoOutput)
    24522475        return false;
    24532476
    2454     bool paused_now = false;
    24552477    if (!(min_buffers ? (videoOutput->ValidVideoFrames() >= min_buffers) :
    24562478                        (GetEof() != kEofStateNone) ||
    24572479                        (videoOutput->hasHWAcceleration() ?
    bool MythPlayer::PrebufferEnoughFrames(int min_buffers) 
    24672489        // for the jerking is detected.
    24682490
    24692491        bool watchingTV = IsWatchingInprogress();
    2470         if (!paused_now && (livetv || watchingTV) && !FlagIsSet(kMusicChoice))
     2492        if ( (livetv || watchingTV) && !FlagIsSet(kMusicChoice))
    24712493        {
    24722494            uint64_t frameCount = GetCurrentFrameCount();
    24732495            uint64_t framesLeft = frameCount - framesPlayed;
    24742496            uint64_t margin = (uint64_t) (video_frame_rate * 3);
    24752497            if (framesLeft < margin)
    24762498            {
    2477                 LOG(VB_PLAYBACK, LOG_NOTICE, LOC +
    2478                     QString("Pause to allow live tv catch up. Position in sec. Current: %2, Total: %3")
    2479                     .arg(framesPlayed).arg(frameCount));
     2499                if (rtcbase)
     2500                    LOG(VB_PLAYBACK, LOG_NOTICE, LOC +
     2501                        QString("Pause to allow live tv catch up. Position in sec. Current: %2, Total: %3")
     2502                        .arg(framesPlayed).arg(frameCount));
    24802503                audio.Pause(true);
    24812504                avsync_audiopaused = true;
    2482                 paused_now = true;
     2505                rtcbase = 0;
    24832506            }
    24842507        }
    24852508        usleep(frame_interval >> 3);
  • mythtv/libs/libmythtv/mythplayer.h

    diff --git a/mythtv/libs/libmythtv/mythplayer.h b/mythtv/libs/libmythtv/mythplayer.h
    index 7358d617a9d..4b295af28fe 100644
    a b class MTV_PUBLIC MythPlayer 
    856856    int       maxtcframes;    // number of frames seen since max to date tc
    857857    int64_t   avsync2adjustms; // number of milliseconds to adjust for av sync errors
    858858    int       numdroppedframes; // number of consecutive dropped frames.
     859    int64_t   prior_audiotimecode;    // time code from prior frame
     860    int64_t   prior_videotimecode;    // time code from prior frame
    859861
    860862    // LiveTV
    861863    TV *m_tv;
  • mythtv/libs/libmythtv/tv_play.cpp

    diff --git a/mythtv/libs/libmythtv/tv_play.cpp b/mythtv/libs/libmythtv/tv_play.cpp
    index ea0aa806d59..37894f75431 100644
    a b bool TV::StartTV(ProgramInfo *tvrec, uint flags, 
    409409                startSysEventSent = true;
    410410                startLivetvEventSent = true;
    411411                gCoreContext->SendSystemEvent("LIVETV_STARTED");
     412                usleep(gCoreContext->GetNumSetting("LiveTVWaitMS", 0)*1000);
    412413            }
    413414
    414415            LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "tv->LiveTV() -- end");
  • mythtv/programs/mythfrontend/globalsettings.cpp

    diff --git a/mythtv/programs/mythfrontend/globalsettings.cpp b/mythtv/programs/mythfrontend/globalsettings.cpp
    index e0551ef2840..4118c585ad5 100644
    a b static HostSpinBoxSetting *LiveTVIdleTimeout() 
    18101810    return gs;
    18111811}
    18121812
     1813static HostSpinBoxSetting *LiveTVWaitMS()
     1814{
     1815    HostSpinBoxSetting *gs = new HostSpinBoxSetting("LiveTVWaitMS", 0, 30000, 100);
     1816
     1817    gs->setLabel(PlaybackSettings::tr("Live TV wait (milliseconds)"));
     1818
     1819    gs->setValue(0);
     1820
     1821    gs->setHelpText(PlaybackSettings::tr("Wait the specified number of milliseconds "
     1822                                         "before beginning playback of Live TV "
     1823                                         "to avoid stuttering during the first minute"));
     1824    return gs;
     1825}
     1826
     1827
    18131828// static HostCheckBoxSetting *PlaybackPreview()
    18141829// {
    18151830//     HostCheckBoxSetting *gc = new HostCheckBoxSetting("PlaybackPreview");
    void PlaybackSettings::Load(void) 
    42244239    general->addChild(UseProgStartMark());
    42254240    general->addChild(AutomaticSetWatched());
    42264241    general->addChild(ContinueEmbeddedTVPlay());
     4242    general->addChild(LiveTVWaitMS());
    42274243    general->addChild(LiveTVIdleTimeout());
    42284244
    42294245#if CONFIG_DEBUGTYPE