Ticket #13383: 20190214_1507_catchup_plus.patch

File 20190214_1507_catchup_plus.patch, 11.4 KB (added by Peter Bennett, 20 months ago)

The Live TV Wait is now applied when starting Live TV, changing channels or changing inputs. Also the maximum Live TV wait is now 10 seconds

  • 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..0ad00a335ba 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");
    void TV::SwitchInputs(PlayerContext *ctx, 
    74797480        delete testrec;
    74807481    }
    74817482
     7483    usleep(gCoreContext->GetNumSetting("LiveTVWaitMS", 0)*1000);
    74827484    UnpauseLiveTV(ctx);
    74837485    UpdateOSDInput(ctx);
    74847486
    void TV::ChangeChannel(PlayerContext *ctx, ChannelChangeDirection direction) 
    77957797    if (ctx->player)
    77967798        ctx->player->GetAudio()->Reset();
    77977799
     7800    usleep(gCoreContext->GetNumSetting("LiveTVWaitMS", 0)*1000);
    77987801    UnpauseLiveTV(ctx);
    77997802
    78007803    if (oldinputname != ctx->recorder->GetInput())
    void TV::ChangeChannel(PlayerContext *ctx, uint chanid, const QString &chan) 
    79647967    if (ctx->player)
    79657968        ctx->player->GetAudio()->Reset();
    79667969
     7970    usleep(gCoreContext->GetNumSetting("LiveTVWaitMS", 0)*1000);
    79677971    UnpauseLiveTV(ctx, chanid && GetQueuedChanID());
    79687972
    79697973    if (oldinputname != ctx->recorder->GetInput())
  • mythtv/programs/mythfrontend/globalsettings.cpp

    diff --git a/mythtv/programs/mythfrontend/globalsettings.cpp b/mythtv/programs/mythfrontend/globalsettings.cpp
    index e0551ef2840..b963a8dce87 100644
    a b static HostSpinBoxSetting *LiveTVIdleTimeout() 
    18101810    return gs;
    18111811}
    18121812
     1813static HostSpinBoxSetting *LiveTVWaitMS()
     1814{
     1815    HostSpinBoxSetting *gs = new HostSpinBoxSetting("LiveTVWaitMS", 0, 10000, 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