Ticket #13383: 20190212_1721_catchup_plus_fixed.patch

File 20190212_1721_catchup_plus_fixed.patch, 8.3 KB (added by Peter Bennett, 5 years ago)

New version of patch that fixes LiveTV. When starting live TV there may be a few short pauses while recording catches up with playback, then it will be smooth.

  • mythtv/libs/libmythtv/mythplayer.cpp

    diff --git a/mythtv/libs/libmythtv/mythplayer.cpp b/mythtv/libs/libmythtv/mythplayer.cpp
    index 5b80c452a3b..8620164b2e2 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;
    bool MythPlayer::PrebufferEnoughFrames(int min_buffers) 
    24792501                    .arg(framesPlayed).arg(frameCount));
    24802502                audio.Pause(true);
    24812503                avsync_audiopaused = true;
    2482                 paused_now = true;
     2504                rtcbase = 0;
    24832505            }
    24842506        }
    24852507        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;