Ticket #9727: snappyseeks_v3.patch

File snappyseeks_v3.patch, 18.9 KB (added by Jim Stichnoth <stichnot@…>, 9 years ago)
  • mythtv/libs/libmythtv/avformatdecoder.cpp

    diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp
    index bedd20d..29eadbf 100644
    a b bool AvFormatDecoder::DoFastForward(long long desiredFrame, bool discardFrames) 
    569569    long double seekts = desiredFrame * AV_TIME_BASE / fps;
    570570    ts += (long long)seekts;
    571571
    572     bool exactseeks = DecoderBase::getExactSeeks();
     572    //bool exactseeks = DecoderBase::getExactSeeks();
     573    // XXX figure out how to do snapping in this case
     574    bool exactseeks = !DecoderBase::getSeekSnap();
    573575
    574576    int flags = (dorewind || exactseeks) ? AVSEEK_FLAG_BACKWARD : 0;
    575577
  • mythtv/libs/libmythtv/decoderbase.cpp

    diff --git a/mythtv/libs/libmythtv/decoderbase.cpp b/mythtv/libs/libmythtv/decoderbase.cpp
    index 8e8d844..33729da 100644
    a b DecoderBase::DecoderBase(MythPlayer *parent, const ProgramInfo &pginfo) 
    3939      m_positionMapLock(QMutex::Recursive),
    4040      dontSyncPositionMap(false),
    4141
    42       exactseeks(false), livetv(false), watchingrecording(false),
     42      seeksnap(-1), livetv(false), watchingrecording(false),
    4343
    4444      hasKeyFrameAdjustTable(false), lowbuffers(false),
    4545      getrawframes(false), getrawvideo(false),
    bool DecoderBase::DoRewind(long long desiredFrame, bool discardFrames) 
    516516
    517517    // Do any Extra frame-by-frame seeking for exactseeks mode
    518518    // And flush pre-seek frame if we are allowed to and need to..
    519     int normalframes = (exactseeks) ? desiredFrame - framesPlayed : 0;
     519    int normalframes = desiredFrame - (framesPlayed - 1) > seeksnap
     520        ? desiredFrame - framesPlayed : 0;
    520521    normalframes = max(normalframes, 0);
    521522    SeekReset(lastKey, normalframes, true, discardFrames);
    522523
    bool DecoderBase::DoRewindSeek(long long desiredFrame) 
    568569    PosMapEntry e;
    569570    {
    570571        QMutexLocker locker(&m_positionMapLock);
    571         int pos_idx  = min(pre_idx, post_idx);
    572         e = m_positionMap[pos_idx];
     572        PosMapEntry e_pre  = m_positionMap[pre_idx];
     573        PosMapEntry e_post = m_positionMap[post_idx];
     574        int pos_idx = pre_idx;
     575        e = e_pre;
     576        if (((uint64_t) (GetKey(e_post) - desiredFrame)) <= seeksnap &&
     577            framesPlayed - 1 > GetKey(e_post) &&
     578            GetKey(e_post) - desiredFrame <= desiredFrame - GetKey(e_pre))
     579        {
     580            // Snap to the right if e_post is within snap distance and
     581            // is at least as close a snap as e_pre.  Take into
     582            // account that if framesPlayed has already reached
     583            // e_post, we should only snap to the left.
     584            pos_idx = post_idx;
     585            e = e_post;
     586        }
    573587        lastKey = GetKey(e);
    574588
    575589        // ??? Don't rewind past the beginning of the file
    bool DecoderBase::DoFastForward(long long desiredFrame, bool discardFrames) 
    731745
    732746    // Do any Extra frame-by-frame seeking for exactseeks mode
    733747    // And flush pre-seek frame if we are allowed to and need to..
    734     int normalframes = (exactseeks) ? desiredFrame - framesPlayed : 0;
     748    int normalframes = desiredFrame - (framesPlayed - 1) > seeksnap
     749        ? desiredFrame - framesPlayed : 0;
    735750    normalframes = max(normalframes, 0);
    736751    SeekReset(lastKey, normalframes, needflush, discardFrames);
    737752
    void DecoderBase::DoFastForwardSeek(long long desiredFrame, bool &needflush) 
    789804    FindPosition(desiredFrame, hasKeyFrameAdjustTable, pre_idx, post_idx);
    790805
    791806    // if exactseeks, use keyframe <= desiredFrame
    792     uint pos_idx = (exactseeks) ? pre_idx : max(pre_idx, post_idx);
    793807
    794     PosMapEntry e;
     808    PosMapEntry e, e_pre, e_post;
    795809    {
    796810        QMutexLocker locker(&m_positionMapLock);
    797         e = m_positionMap[pos_idx];
     811        e_pre  = m_positionMap[pre_idx];
     812        e_post = m_positionMap[post_idx];
     813    }
     814    e = e_pre;
     815    if (((uint64_t) (GetKey(e_post) - desiredFrame)) <= seeksnap &&
     816        (framesPlayed - 1 >= GetKey(e_pre) ||
     817         GetKey(e_post) - desiredFrame < desiredFrame - GetKey(e_pre)))
     818    {
     819        // Snap to the right if e_post is within snap distance and is
     820        // a closer snap than e_pre.  Take into account that if
     821        // framesPlayed has already reached e_pre, we should only snap
     822        // to the right.
     823        e = e_post;
    798824    }
    799825    lastKey = GetKey(e);
    800826
  • mythtv/libs/libmythtv/decoderbase.h

    diff --git a/mythtv/libs/libmythtv/decoderbase.h b/mythtv/libs/libmythtv/decoderbase.h
    index fe16fe9..e7253e3 100644
    a b class DecoderBase 
    9797    virtual void SetEof(bool eof)  { ateof = eof;  }
    9898    bool         GetEof(void)      { return ateof; }
    9999
    100     void setExactSeeks(bool exact) { exactseeks = exact; }
    101     bool getExactSeeks(void) const { return exactseeks;  }
     100    void setSeekSnap(uint64_t snap)  { seeksnap = snap; }
     101    uint64_t getSeekSnap(void) const { return seeksnap;  }
    102102    void setLiveTVMode(bool live)  { livetv = live;      }
    103103
    104104    // Must be done while player is paused.
    class DecoderBase 
    255255    vector<PosMapEntry> m_positionMap;
    256256    bool dontSyncPositionMap;
    257257
    258     bool exactseeks;
     258    uint64_t seeksnap;
    259259    bool livetv;
    260260    bool watchingrecording;
    261261
  • mythtv/libs/libmythtv/mythplayer.cpp

    diff --git a/mythtv/libs/libmythtv/mythplayer.cpp b/mythtv/libs/libmythtv/mythplayer.cpp
    index b2a991b..62547af 100644
    a b MythPlayer::MythPlayer(bool muted) 
    147147      // Bookmark stuff
    148148      bookmarkseek(0),
    149149      // Seek
    150       fftime(0),                    exactseeks(false),
     150      fftime(0),                    seeksnap(-1),
    151151      // Playback misc.
    152152      videobuf_retries(0),          framesPlayed(0),
    153153      totalFrames(0),               totalLength(0),
    int MythPlayer::OpenFile(uint retries, bool allow_libmpeg2) 
    966966        return -1;
    967967    }
    968968
    969     decoder->setExactSeeks(exactseeks);
     969    decoder->setSeekSnap(seeksnap);
    970970    decoder->setLiveTVMode(livetv);
    971971    decoder->setWatchingRecording(watchingrecording);
    972972    decoder->setTranscoding(transcoding);
    void MythPlayer::JumpToProgram(void) 
    24312431        nextpos = 0;
    24322432
    24332433    if (nextpos > 10)
    2434         DoFastForward(nextpos, true, false);
     2434        DoFastForward(nextpos, true, -1);
    24352435
    24362436    player_ctx->SetPlayerChangingBuffers(false);
    24372437    LOG(VB_PLAYBACK, LOG_INFO, LOC + "JumpToProgram - end");
    void MythPlayer::InitialSeek(void) 
    24752475    // TODO handle initial commskip and/or cutlist skip as well
    24762476    if (bookmarkseek > 30)
    24772477    {
    2478         DoFastForward(bookmarkseek, true, false);
     2478        DoFastForward(bookmarkseek, true, -1);
    24792479        if (clearSavedPosition && !player_ctx->IsPIP())
    24802480            SetBookmark(true);
    24812481    }
    void MythPlayer::EventLoop(void) 
    26662666            if (!msg.isEmpty())
    26672667                SetOSDStatus(msg, kOSDTimeout_Med);
    26682668            if (jump)
    2669                 DoJumpToFrame(jumpto, true, true);
     2669                DoJumpToFrame(jumpto, true, 0);
    26702670        }
    26712671        commBreakMap.SkipCommercials(0);
    26722672        return;
    void MythPlayer::EventLoop(void) 
    26842684        if (!msg.isEmpty())
    26852685            SetOSDStatus(msg, kOSDTimeout_Med);
    26862686        if (jump)
    2687             DoJumpToFrame(jumpto, true, true);
     2687            DoJumpToFrame(jumpto, true, 0);
    26882688    }
    26892689
    26902690    // Handle cutlist skipping
    void MythPlayer::EventLoop(void) 
    27012701        }
    27022702        else
    27032703        {
    2704             DoJumpToFrame(jumpto, true, true);
     2704            DoJumpToFrame(jumpto, true, 0);
    27052705        }
    27062706    }
    27072707}
    void MythPlayer::ChangeSpeed(void) 
    32023202    {
    32033203        videoOutput->SetPrebuffering(ffrew_skip == 1);
    32043204        if (decoder)
    3205             decoder->setExactSeeks(exactseeks && ffrew_skip == 1);
     3205            decoder->setSeekSnap(ffrew_skip == 1 ? seeksnap : -1);
    32063206        if (play_speed != 0.0f && !(last_speed == 0.0f && ffrew_skip == 1))
    32073207            DoJumpToFrame(framesPlayed + fftime - rewindtime);
    32083208    }
    void MythPlayer::ChangeSpeed(void) 
    32503250}
    32513251
    32523252bool MythPlayer::DoRewind(uint64_t frames, bool override_seeks,
    3253                           bool seeks_wanted)
     3253                          uint64_t seeksnap_wanted)
    32543254{
    32553255    if (player_ctx->buffer && !player_ctx->buffer->IsSeekingAllowed())
    32563256        return false;
    32573257
    32583258    uint64_t number = frames + 1;
    32593259    uint64_t desiredFrame = (framesPlayed > number) ? framesPlayed - number : 0;
    bool MythPlayer::DoRewind(uint64_t frames, bool override_seeks, 
    32593259    if (desiredFrame < video_frame_rate)
    32603260        limitKeyRepeat = true;
    32613261
    3262     WaitForSeek(desiredFrame, override_seeks, seeks_wanted);
     3262    WaitForSeek(desiredFrame, override_seeks, seeksnap_wanted);
    32633263    rewindtime = 0;
    32643264    ClearAfterSeek();
    32653265    return true;
    bool MythPlayer::IsNearEnd(void) 
    34023402}
    34033403
    34043404bool MythPlayer::DoFastForward(uint64_t frames, bool override_seeks,
    3405                                bool seeks_wanted)
     3405                               uint64_t seeksnap_wanted)
    34063406{
    34073407    if (player_ctx->buffer && !player_ctx->buffer->IsSeekingAllowed())
    34083408        return false;
    34093409
    34103410    uint64_t number = frames - 1;
    34113411    uint64_t desiredFrame = framesPlayed + number;
    bool MythPlayer::DoFastForward(uint64_t frames, bool override_seeks, 
    34143414            desiredFrame = endcheck;
    34153415    }
    34163416
    3417     WaitForSeek(desiredFrame, override_seeks, seeks_wanted);
     3417    WaitForSeek(desiredFrame, override_seeks, seeksnap_wanted);
    34183418    fftime = 0;
    34193419    ClearAfterSeek(false);
    34203420    return true;
    34213421}
    34223422
    34233423void MythPlayer::DoJumpToFrame(uint64_t frame, bool override_seeks,
    3424                                bool seeks_wanted)
     3424                               uint64_t seeksnap_wanted)
    34253425{
    34263426    if (frame > framesPlayed)
    3427         DoFastForward(frame - framesPlayed, override_seeks, seeks_wanted);
     3427        DoFastForward(frame - framesPlayed, override_seeks, seeksnap_wanted);
    34283428    else if (frame <= framesPlayed)
    3429         DoRewind(framesPlayed - frame, override_seeks, seeks_wanted);
     3429        DoRewind(framesPlayed - frame, override_seeks, seeksnap_wanted);
    34303430}
    34313431
    34323432void MythPlayer::WaitForSeek(uint64_t frame, bool override_seeks,
    3433                              bool seeks_wanted)
     3433                             uint64_t seeksnap_wanted)
    34343434{
    34353435    if (!decoder)
    34363436        return;
    34373437
    3438     bool after  = exactseeks && (ffrew_skip == 1);
    3439     bool before = override_seeks ? seeks_wanted :
    3440                            (allpaused && !deleteMap.IsEditing()) ? true: after;
    3441     decoder->setExactSeeks(before);
     3438    uint64_t after  = (ffrew_skip == 1) ? seeksnap : -1;
     3439    uint64_t before = override_seeks ? seeksnap_wanted :
     3440                           (allpaused && !deleteMap.IsEditing()) ? 0: after;
     3441    decoder->setSeekSnap(before);
    34423442
    34433443    bool islivetvcur = (livetv && player_ctx->tvchain &&
    34443444                        !player_ctx->tvchain->HasNext());
    void MythPlayer::WaitForSeek(uint64_t frame, bool override_seeks, 
    34803480            osd->HideWindow("osd_message");
    34813481        osdLock.unlock();
    34823482    }
    3483     decoder->setExactSeeks(after);
     3483    decoder->setSeekSnap(after);
    34843484}
    34853485
    34863486/** \fn MythPlayer::ClearAfterSeek(bool)
    void MythPlayer::ClearAfterSeek(bool clearvideobuffers) 
    35193519}
    35203520
    35213521void MythPlayer::SetPlayerInfo(TV *tv, QWidget *widget,
    3522                                bool frame_exact_seek, PlayerContext *ctx)
     3522                               uint64_t frame_seek_snap, PlayerContext *ctx)
    35233523{
    35243524    deleteMap.SetPlayerContext(ctx);
    35253525    m_tv = tv;
    35263526    parentWidget = widget;
    3527     exactseeks   = frame_exact_seek;
     3527    seeksnap     = frame_seek_snap;
    35283528    player_ctx   = ctx;
    35293529    livetv       = ctx->tvchain;
    35303530}
    bool MythPlayer::HandleProgramEditorActions(QStringList &actions, 
    36073607    {
    36083608        QString action = actions[i];
    36093609        handled = true;
     3610        int seekamount = deleteMap.GetSeekAmount();
    36103611        if (action == ACTION_LEFT)
    36113612        {
    36123613            if (deleteMap.GetSeekAmount() > 0)
    36133614            {
    3614                 DoRewind(deleteMap.GetSeekAmount(), true, true);
     3615                DoRewind(seekamount, true, seekamount > 1 ? seekamount / 2 : 0);
    36153616            }
    36163617            else
    36173618                HandleArbSeek(false);
    bool MythPlayer::HandleProgramEditorActions(QStringList &actions, 
    36203621        {
    36213622            if (deleteMap.GetSeekAmount() > 0)
    36223623            {
    3623                 DoFastForward(deleteMap.GetSeekAmount(), true, true);
     3624                DoFastForward(seekamount, true, seekamount > 1 ? seekamount / 2 : 0);
    36243625            }
    36253626            else
    36263627                HandleArbSeek(true);
    bool MythPlayer::HandleProgramEditorActions(QStringList &actions, 
    36513652#define FFREW_MULTICOUNT 10
    36523653        else if (action == ACTION_BIGJUMPREW)
    36533654        {
    3654             if (deleteMap.GetSeekAmount() > 0)
    3655                 DoRewind(deleteMap.GetSeekAmount() * FFREW_MULTICOUNT,
    3656                          true, true);
     3655            if (seekamount > 0)
     3656                DoRewind(seekamount * FFREW_MULTICOUNT,
     3657                            true, seekamount > 1 ? seekamount * FFREW_MULTICOUNT / 2: 0);
    36573658            else
    36583659            {
    36593660                int fps = (int)ceil(video_frame_rate);
    3660                 DoRewind(fps * FFREW_MULTICOUNT / 2, true, true);
     3661                DoRewind(fps * FFREW_MULTICOUNT / 2, true, 0);
    36613662            }
    36623663        }
    36633664        else if (action == ACTION_BIGJUMPFWD)
    36643665        {
    3665             if (deleteMap.GetSeekAmount() > 0)
    3666                 DoFastForward(deleteMap.GetSeekAmount() * FFREW_MULTICOUNT,
    3667                               true, true);
     3666            if (seekamount > 0)
     3667                DoFastForward(seekamount * FFREW_MULTICOUNT,
     3668                              true, seekamount > 1 ? seekamount * FFREW_MULTICOUNT / 2: 0);
    36683669            else
    36693670            {
    36703671                int fps = (int)ceil(video_frame_rate);
    3671                 DoFastForward(fps * FFREW_MULTICOUNT / 2, true, true);
     3672                DoFastForward(fps * FFREW_MULTICOUNT / 2, true, 0);
    36723673            }
    36733674        }
    36743675        else if (action == ACTION_SELECT)
    void MythPlayer::HandleArbSeek(bool right) 
    37693770        long long framenum = deleteMap.GetNearestMark(framesPlayed,
    37703771                                                      totalFrames, right);
    37713772        if (right && (framenum > (int64_t)framesPlayed))
    3772             DoFastForward(framenum - framesPlayed, true, true);
     3773            DoFastForward(framenum - framesPlayed, true, 0);
    37733774        else if (!right && ((int64_t)framesPlayed > framenum))
    3774             DoRewind(framesPlayed - framenum, true, true);
     3775            DoRewind(framesPlayed - framenum, true, 0);
    37753776    }
    37763777    else
    37773778    {
    void MythPlayer::HandleArbSeek(bool right) 
    37823783            // the position map uses MARK_GOP_BYFRAME. (see DecoderBase)
    37833784            float editKeyFrameDist = keyframedist <= 2 ? 18 : keyframedist;
    37843785
    3785             DoFastForward((long long)(editKeyFrameDist * 1.1), true, false);
     3786            DoFastForward((long long)(editKeyFrameDist * 1.1), true, -1);
    37863787        }
    37873788        else
    37883789        {
    3789             DoRewind(2, true, false);
     3790            DoRewind(2, true, -1);
    37903791        }
    37913792    }
    37923793}
    VideoFrame* MythPlayer::GetRawVideoFrame(long long frameNumber) 
    41154116
    41164117    if (frameNumber >= 0)
    41174118    {
    4118         DoJumpToFrame(frameNumber, true, true);
     4119        DoJumpToFrame(frameNumber, true, 0);
    41194120        ClearAfterSeek();
    41204121    }
    41214122
    void MythPlayer::InitForTranscode(bool copyaudio, bool copyvideo) 
    42004201    if (copyaudio && decoder)
    42014202        decoder->SetRawAudioState(true);
    42024203
    4203     SetExactSeeks(true);
     4204    SetSeekSnap(0);
    42044205    if (decoder)
    42054206    {
    4206         decoder->setExactSeeks(exactseeks);
     4207        decoder->setSeekSnap(seeksnap);
    42074208        decoder->SetLowBuffers(true);
    42084209    }
    42094210}
  • mythtv/libs/libmythtv/mythplayer.h

    diff --git a/mythtv/libs/libmythtv/mythplayer.h b/mythtv/libs/libmythtv/mythplayer.h
    index 8415fca..6e7f026 100644
    a b class MTV_PUBLIC MythPlayer 
    116116    bool InitVideo(void);
    117117
    118118    // Public Sets
    119     void SetPlayerInfo(TV *tv, QWidget *widget, bool frame_exact_seek,
     119    void SetPlayerInfo(TV *tv, QWidget *widget, uint64_t frame_seek_snap,
    120120                       PlayerContext *ctx);
    121121    void SetNullVideo(void)                   { using_null_videoout = true; }
    122     void SetExactSeeks(bool exact)            { exactseeks = exact; }
     122    void SetSeekSnap(uint64_t snap)           { seeksnap = snap; }
    123123    void SetLength(int len)                   { totalLength = len; }
    124124    void SetFramesPlayed(uint64_t played);
    125125    void SetVideoFilters(const QString &override);
    class MTV_PUBLIC MythPlayer 
    490490    // These actually execute commands requested by public members
    491491    virtual void ChangeSpeed(void);
    492492    bool DoFastForward(uint64_t frames, bool override_seeks = false,
    493                        bool seeks_wanted = false);
     493                       uint64_t seeksnap_wanted = -1);
    494494    bool DoRewind(uint64_t frames, bool override_seeks = false,
    495                   bool seeks_wanted = false);
     495                  uint64_t seeksnap_wanted = -1);
    496496    void DoJumpToFrame(uint64_t frame, bool override_seeks = false,
    497                        bool seeks_wanted = false);
     497                       uint64_t seeksnap_wanted = -1);
    498498
    499499    // Private seeking stuff
    500500    void WaitForSeek(uint64_t frame, bool override_seeks = false,
    501                      bool seeks_wanted = false);
     501                     uint64_t seeksnap_wanted = -1);
    502502    void ClearAfterSeek(bool clearvideobuffers = true);
    503503
    504504    // Private chapter stuff
    class MTV_PUBLIC MythPlayer 
    588588    /// If fftime>0, number of frames to seek forward.
    589589    /// If fftime<0, number of frames to seek backward.
    590590    long long fftime;
    591     /// Iff true we ignore seek amount and try to seek to an
    592     /// exact frame ignoring key frame restrictions.
    593     bool     exactseeks;
     591    /// When seeking, snap to a key frame if the target is within
     592    /// seeksnap frames.  Use seeksnap=0 for exact seeks,
     593    /// seeksnap=-1 for completely non-exact seeks.
     594    uint64_t seeksnap;
    594595
    595596    // Playback misc.
    596597    /// How often we have tried to wait for a video output buffer and failed
  • mythtv/programs/mythcommflag/PrePostRollFlagger.cpp

    diff --git a/mythtv/programs/mythcommflag/PrePostRollFlagger.cpp b/mythtv/programs/mythcommflag/PrePostRollFlagger.cpp
    index cc9f921..b21c8c9 100644
    a b PrePostRollFlagger::PrePostRollFlagger(SkipType commDetectMethod, 
    2626void PrePostRollFlagger::Init()
    2727{
    2828    ClassicCommDetector::Init();
    29     player->SetExactSeeks(true);
     29    player->SetSeekSnap(0);
    3030}
    3131
    3232bool PrePostRollFlagger::go()
    long long PrePostRollFlagger::findBreakInrange(long long startFrame, 
    230230    player->DiscardVideoFrame(player->GetRawVideoFrame(0));
    231231
    232232    long long tmpStartFrame = startFrame;
    233     player->SetExactSeeks(true);
     233    player->SetSeekSnap(0);
    234234    VideoFrame* f = player->GetRawVideoFrame(tmpStartFrame);
    235235    float aspect = player->GetVideoAspect();
    236236    currentFrameNumber = f->frameNumber;