Ticket #2808: time_based_seeking.2.diff

File time_based_seeking.2.diff, 13.0 KB (added by skamithi, 17 years ago)

2nd attempt. still undergoing testing. should also fix where if hit the skip button repeatedly it jumps back to the beginning of the title.

  • libs/libmythtv/NuppelVideoPlayer.cpp

     
    12581258        long long real_skip = (toBegin) ? -curFrame : ffrew_skip;
    12591259        GetDecoder()->DoRewind(curFrame + real_skip, false);
    12601260        stopFFREW = framesPlayed <= keyframedist;
     1261        if (ringBuffer->isDVD())
     1262            stopFFREW = (ringBuffer->DVD()->GetCurrentTime() < 2);
    12611263    }
    12621264
    12631265    if (stopFFREW)
     
    40064008                ret = 0;
    40074009            else if (behind - ff <= maxtime * 2)
    40084010                ret = behind - maxtime * 2;
     4011
     4012            if (ringBuffer->isDVD())
     4013            {
     4014                if (ringBuffer->DVD()->GetCurrentTime() >
     4015                    ringBuffer->DVD()->GetTotalTimeOfTitle() - 5)
     4016                {
     4017                    ret = 0;
     4018                }
     4019            }
    40094020        }
    40104021    }
    40114022
  • libs/libmythtv/DVDRingBuffer.cpp

     
    11#include <unistd.h>
     2#include <math.h>
    23
    34#include "DVDRingBuffer.h"
    45#include "mythcontext.h"
     
    2627      dvdBlockRPos(0),  dvdBlockWPos(0),
    2728      pgLength(0),      pgcLength(0),
    2829      cellStart(0),     pgStart(0),
     30      currentpos(0),
    2931      lastNav(NULL),    part(0),
    3032      title(0),         titleParts(0),
    3133      gotStop(false),
     
    4042      menupktpts(0), curAudioTrack(0),
    4143      curSubtitleTrack(0), autoselectaudio(true),
    4244      autoselectsubtitle(true),
    43       jumptotitle(true), repeatseek(false),
     45      jumptotitle(true),
    4446      seekpos(0), seekwhence(0),
    4547      dvdname(NULL), serialnumber(NULL),
     48      seeking(false), seekTime(0),
    4649      parent(0)
    4750{
    4851    memset(&dvdMenuButton, 0, sizeof(AVSubtitle));
     
    7073            (NumMenuButtons() > 0));
    7174}
    7275
    73 long long DVDRingBufferPriv::NormalSeek(long long pos, int whence)
     76long long DVDRingBufferPriv::NormalSeek(long long time)
    7477{
    7578    QMutexLocker lock(&seekLock);
    76     return Seek(pos, whence);
     79    return Seek(time);
    7780}
    7881
    79 long long DVDRingBufferPriv::Seek(long long pos, int whence)
     82long long DVDRingBufferPriv::Seek(long long time)
    8083{
    81     dvdnav_status_t dvdRet = dvdnav_sector_search(this->dvdnav, pos / DVD_BLOCK_SIZE , whence);
    82     if (dvdRet == DVDNAV_STATUS_ERR && !repeatseek)
     84    seekTime = (uint64_t)time;
     85    dvdnav_status_t dvdRet = dvdnav_time_search(this->dvdnav, seekTime);
     86    if (dvdRet == DVDNAV_STATUS_ERR)
    8387    {
    84         VERBOSE(VB_PLAYBACK, LOC + QString("Seek failed to jump to position %1").arg(pos) +
    85                             " Will try and seek to this position at the next cell change");
    86         repeatseek = true;
    87         seekpos = pos;
    88         seekwhence = whence;
     88        VERBOSE(VB_PLAYBACK, LOC_ERR +
     89                QString("Seek() to time %1 failed").arg(time));
    8990    }
    90     gotStop = false;
    91     return GetReadPosition();
     91    else
     92    {
     93        gotStop = false;
     94        if (time > 0)
     95            seeking = true;
     96    }
     97   
     98    return currentpos;
    9299}
    93100           
    94101void DVDRingBufferPriv::GetDescForPos(QString &desc) const
     
    173180{
    174181    uint32_t pos = 0;
    175182    uint32_t length = 1;
    176     if (dvdnav) 
     183    if (dvdnav)
    177184    {
    178185        if (dvdnav_get_position(dvdnav, &pos, &length) == DVDNAV_STATUS_ERR)
    179186        {
    180187            // try one more time
    181             usleep(10000);
    182188            dvdnav_get_position(dvdnav, &pos, &length);
    183189        }
    184190    }
     
    196202    char           *dest         = (char*) data;
    197203    int             offset       = 0;
    198204
     205    QMutexLocker lock(&seekLock);
    199206    if (gotStop)
    200207    {
    201208        VERBOSE(VB_IMPORTANT, LOC + "safe_read: called after DVDNAV_STOP");
     
    221228        switch (dvdEvent)
    222229        {
    223230            case DVDNAV_BLOCK_OK:
    224                 // We need at least a DVD blocks worth of data so copy it in.
    225                 memcpy(dest + offset, blockBuf, DVD_BLOCK_SIZE);
     231                if (!seeking)
     232                {
     233                    // We need at least a DVD blocks worth of data so copy it in.
     234                    memcpy(dest + offset, blockBuf, DVD_BLOCK_SIZE);
    226235                       
    227                 tot += DVD_BLOCK_SIZE;
    228                        
     236                    tot += DVD_BLOCK_SIZE;
     237                }
     238               
    229239                if (blockBuf != dvdBlockWriteBuf)
    230240                {
    231241                    dvdnav_free_cache_block(dvdnav, blockBuf);
     
    259269                dvdnav_get_number_of_parts(dvdnav, title, &titleParts);
    260270                dvdnav_get_position(dvdnav, &pos, &length);
    261271                titleLength = length *DVD_BLOCK_SIZE;
    262                 cellstartPos = GetReadPosition();
     272                if (!seeking)
     273                    cellstartPos = GetReadPosition();
    263274
    264275                VERBOSE(VB_PLAYBACK,
    265276                        QString("DVDNAV_CELL_CHANGE: "
     
    294305                    autoselectsubtitle = true;
    295306                }
    296307
    297                 if (repeatseek)
    298                 {
    299                     QMutexLocker lock(&seekLock);
    300                     Seek(seekpos, seekwhence);
    301                     repeatseek = false;
    302                 }       
    303 
    304308                if (blockBuf != dvdBlockWriteBuf)
    305309                {
    306310                    dvdnav_free_cache_block(dvdnav, blockBuf);
     
    372376            case DVDNAV_NAV_PACKET:
    373377            {
    374378                lastNav = (dvdnav_t *)blockBuf;
     379                dsi_t *dsi = dvdnav_get_current_nav_dsi(dvdnav);
    375380                if (vobid == 0 && cellid == 0)
    376381                {
    377                     dsi_t *dsi = dvdnav_get_current_nav_dsi(dvdnav);
    378382                    vobid  = dsi->dsi_gi.vobu_vob_idn;
    379383                    cellid = dsi->dsi_gi.vobu_c_idn;
    380384                    if ((lastvobid == vobid) && (lastcellid == cellid)
     
    383387                        cellRepeated = true;
    384388                    }
    385389                }
     390
     391                currentpos = GetReadPosition();
     392               
     393                if (seeking)
     394                {
     395                    dvd_time_t timeFromCellStart = dsi->dsi_gi.c_eltm;
     396                    uint64_t currentpts = cellStart +
     397                        (uint)dvdnav_convert_time(&timeFromCellStart);
     398                    if (currentpts >= seekTime)
     399                    {
     400                        seeking = false;
     401                        seekTime = 0;
     402                    }
     403                }
     404               
    386405                if (blockBuf != dvdBlockWriteBuf)
    387406                {
    388407                    dvdnav_free_cache_block(dvdnav, blockBuf);
     
    522541    else
    523542    {
    524543        QMutexLocker lock(&seekLock);
    525         Seek(0,SEEK_SET);
     544        Seek(0);
    526545    }
    527546    gotStop = false;
    528547}
     
    967986
    968987uint DVDRingBufferPriv::GetCurrentTime(void)
    969988{
     989    QMutexLocker lock(&seekLock);
    970990    dsi_t *dvdnavDsi = dvdnav_get_current_nav_dsi(dvdnav);
    971991    dvd_time_t timeFromCellStart = dvdnavDsi->dsi_gi.c_eltm;
    972992    uint currentTime = GetCellStart() +
     
    10271047    if (type == kTrackTypeSubtitle)
    10281048    {
    10291049        curSubtitleTrack = trackNo;
    1030         autoselectsubtitle = false;
     1050        if (trackNo < 0)
     1051            autoselectsubtitle = true;
     1052        else
     1053            autoselectsubtitle = false;
    10311054    }
    10321055    else if (type == kTrackTypeAudio)
    10331056    {
     
    11041127{
    11051128    QMutexLocker lock(&seekLock);
    11061129    gotoCellStart = true;
    1107     Seek(cellstartPos, SEEK_SET);
     1130    Seek(cellStart);
    11081131}
    11091132
    11101133/**
  • libs/libmythtv/RingBuffer.cpp

     
    11801180#ifdef USING_FRONTEND
    11811181    else if (dvdPriv)
    11821182    {
    1183         dvdPriv->NormalSeek(pos, whence);
     1183        dvdPriv->NormalSeek(pos);
    11841184    }
    11851185#endif // USING_FRONTEND
    11861186    else
  • libs/libmythtv/DVDRingBuffer.h

     
    7979    bool nextTrack(void);
    8080    void prevTrack(void);
    8181    int  safe_read(void *data, unsigned sz);
    82     long long NormalSeek(long long pos, int whence);
     82    long long NormalSeek(long long time);
    8383    void SkipStillFrame(void);
    8484    void WaitSkip(void);
    8585    void GoToMenu(const QString str);
     
    113113    long long      pgcLength;
    114114    long long      cellStart;
    115115    long long      pgStart;
     116    long long      currentpos;
    116117    dvdnav_t      *lastNav; // This really belongs in the player.
    117118    int32_t        part;
    118119    int32_t        title;
     
    153154    bool           autoselectaudio;
    154155    bool           autoselectsubtitle;
    155156    bool           jumptotitle;
    156     bool           repeatseek;
    157157    long long      seekpos;
    158158    int            seekwhence;
    159159    QString        dvdname;
    160160    QString        serialnumber;
    161        
     161    bool           seeking;
     162    uint64_t       seekTime;
    162163
    163164    NuppelVideoPlayer *parent;
    164165
    165166    QMutex menuBtnLock;
    166167    QMutex seekLock;
    167168
    168     long long Seek(long long pos, int whence);
     169    long long Seek(long long time);
    169170    bool DrawMenuButton(uint8_t *spu_pkt, int buf_size);
    170171    bool DVDButtonUpdate(bool b_mode);
    171172    void ClearMenuSPUParameters(void);
  • libs/libmythtv/decoderbase.cpp

     
    11#include <unistd.h>
     2#include <math.h>
    23
    34#include <algorithm>
    45using namespace std;
     
    450451    normalframes = max(normalframes, 0);
    451452    SeekReset(lastKey, normalframes, true, discardFrames);
    452453
    453     if (discardFrames)
     454    if (ringBuffer->isDVD() || discardFrames)
    454455    {
    455456        // We need to tell the NVP and VideoOutput what frame we're on.
    456457        GetNVP()->SetFramesPlayed(framesPlayed+1);
     
    720721    if (!ringBuffer->isDVD())
    721722        return 0;
    722723
    723     int size = m_positionMap.size() - 1;
    724     int multiplier = m_positionMap[size].pos / m_positionMap[size].index ;
    725     return (long long)(desiredFrame * multiplier);
     724    int diffTime = 0;
     725    int desiredTimePos;
     726    diffTime = (int)ceil((desiredFrame - framesPlayed) / fps);
     727    desiredTimePos = ringBuffer->DVD()->GetCurrentTime() +
     728                        diffTime;
     729    if (diffTime <= 0)
     730        desiredTimePos--;
     731    else
     732        desiredTimePos++;
     733
     734    if (desiredTimePos < 0)
     735        desiredTimePos = 0;
     736       
     737    return (long long)(desiredTimePos * 90000);
    726738}
    727739
    728740long long DecoderBase::DVDCurrentFrameNumber(void)
  • libs/libmythdvdnav/searching.c

     
    101101 
    102102  uint64_t target = time;
    103103  uint64_t length = 0;
     104  uint64_t cell_length = 0;
     105  uint64_t prev_length = 0;
    104106  uint32_t first_cell_nr, last_cell_nr, cell_nr;
    105107  int32_t found;
     108  uint64_t offset = 0;
     109  float diff2 = 1.0;
     110 
    106111  cell_playback_t *cell;
    107112  dvd_state_t *state;
     113  dsi_t *dsi;
    108114  dvdnav_status_t result;
    109115
    110116  if(this->position_current.still != 0) {
     
    137143  found = 0;
    138144  for(cell_nr = first_cell_nr; (cell_nr <= last_cell_nr) && !found; cell_nr ++) {
    139145    cell =  &(state->pgc->cell_playback[cell_nr-1]);
    140     length = dvdnav_convert_time(&cell->playback_time);
    141     if (target >= length) {
    142       target -= length;
    143     } else {
    144       /* FIXME: there must be a better way than interpolation */
    145       target = target * (cell->last_sector - cell->first_sector + 1) / length;
    146       target += cell->first_sector;
     146    cell_length = dvdnav_convert_time(&cell->playback_time);
     147    length += cell_length;
     148    if (target <= length) {
     149      offset = (cell->last_sector - cell->first_sector) / 2;
     150      diff2  = ((double)target - (double)prev_length) / (double)cell_length;
     151      offset = (diff2 * offset);
     152      if (offset > 65536)
     153        offset = 65536;
     154      else if (offset > 32768)
     155        offset = 32768;
     156      else if (offset > 16384)
     157        offset = 16384;
     158      else if (offset > 8192)
     159        offset = 8192;
     160      else if (offset > 4096)
     161        offset = 4096;
     162      else
     163        offset = 0;
     164      target = cell->first_sector;
     165      target += offset;
    147166     
    148167      found = 1;
    149168      break;
    150169    }
     170    prev_length = length;
    151171  }
    152172
     173
    153174  if(found) {
    154175    int32_t vobu;
    155176#ifdef LOG_DEBUG
     
    257278  found = 0;
    258279  for(cell_nr = first_cell_nr; (cell_nr <= last_cell_nr) && !found; cell_nr ++) {
    259280    cell =  &(state->pgc->cell_playback[cell_nr-1]);
    260     length = cell->last_sector - cell->first_sector + 1;
    261     if (target >= cell->first_sector && target <= cell->last_sector) {
     281    length += cell->last_sector - cell->first_sector + 1;
     282    if (target <= length) {
     283      /* convert the target sector from Cell-relative to absolute physical sector */
     284      target += cell->first_sector;
    262285      found = 1;
    263286      break;
    264287    }