Ticket #3355: stick_rew_ffw_dvd.diff

File stick_rew_ffw_dvd.diff, 12.1 KB (added by skamithi, 14 years ago)

uses data search information from the dvd to perform sticky rew/ffw.

  • libmythtv/NuppelVideoPlayer.cpp

     
    12381238{
    12391239    bool stopFFREW = false;
    12401240
     1241    if (ringBuffer->isDVD())
     1242        GetDecoder()->UpdateDVDFramesPlayed();
     1243
    12411244    if (ffrew_skip > 0)
    12421245    {
    12431246        long long delta = GetDecoder()->GetFramesRead() - framesPlayed;
     
    12551258        bool      toBegin   = -curFrame > ffrew_skip;
    12561259        long long real_skip = (toBegin) ? -curFrame : ffrew_skip;
    12571260        GetDecoder()->DoRewind(curFrame + real_skip, false);
    1258         stopFFREW = framesPlayed <= keyframedist;
    12591261        if (ringBuffer->isDVD())
    12601262            stopFFREW = (ringBuffer->DVD()->GetCurrentTime() < 2);
     1263        else
     1264            stopFFREW = framesPlayed <= keyframedist;
    12611265    }
    12621266
    12631267    if (stopFFREW)
     
    38353839#endif
    38363840
    38373841        GetDecoder()->setExactSeeks(exactseeks && ffrew_skip == 1);
    3838         if (!ringBuffer->isDVD())
    3839             GetDecoder()->DoRewind(framesPlayed);
     3842        GetDecoder()->DoRewind(framesPlayed);
    38403843        ClearAfterSeek();
    38413844    }
    38423845
     
    40224025            else if (behind - ff <= maxtime * 2)
    40234026                ret = behind - maxtime * 2;
    40244027
    4025             if (ringBuffer->isDVD())
     4028            if (ringBuffer->isDVD() &&
     4029                ringBuffer->DVD()->TitleTimeLeft() < 5)
    40264030            {
    4027                 if (ringBuffer->DVD()->GetCurrentTime() >
    4028                     ringBuffer->DVD()->GetTotalTimeOfTitle() - 5)
    4029                 {
    4030                     ret = 0;
    4031                 }
     4031                ret = 0;
    40324032            }
    40334033        }
    40344034    }
  • libmythtv/DVDRingBuffer.cpp

     
    5555      jumptotitle(true),
    5656      seekpos(0), seekwhence(0),
    5757      dvdname(NULL), serialnumber(NULL),
    58       seeking(false), seekTime(0),
     58      seeking(false), seektime(0),
    5959      currentTime(0),
    6060      parent(0)
    6161{
    6262    memset(&dvdMenuButton, 0, sizeof(AVSubtitle));
     63    uint def[8] = { 3, 5, 10, 20, 30, 60, 120, 180 };
     64    uint seekValues[8] = { 1, 2, 4, 8, 10, 15, 20, 60 };
     65
     66    for (uint i = 0; i < 8; i++)
     67        seekSpeedMap.insert(def[i], seekValues[i]);
    6368}
    6469
    6570DVDRingBufferPriv::~DVDRingBufferPriv()
     
    9398
    9499long long DVDRingBufferPriv::Seek(long long time)
    95100{
    96     seekTime = (uint64_t)time;
     101    dvdnav_status_t dvdRet = DVDNAV_STATUS_OK;
     102
    97103    uint searchToCellStart = 1;
     104    int seekSpeed = 0;
    98105    int ffrewSkip = 1;
    99106    if (parent)
    100107        ffrewSkip = parent->GetFFRewSkip();
    101     if (ffrewSkip != 1)
    102         searchToCellStart = 0;
    103     dvdnav_status_t dvdRet =
    104         dvdnav_time_search(this->dvdnav, seekTime, searchToCellStart);
     108   
     109    if (ffrewSkip != 1 && time != 0)
     110    {
     111        QMapConstIterator<uint, uint> it = seekSpeedMap.find(labs(time));
     112        seekSpeed = it.data();
     113        if (time < 0)
     114            seekSpeed = -seekSpeed;
     115        dvdRet = dvdnav_time_search_within_cell(this->dvdnav, seekSpeed);
     116    }
     117    else
     118    {
     119        seektime = (uint64_t)time;
     120        dvdRet = dvdnav_time_search(this->dvdnav, seektime, searchToCellStart);
     121    }
     122
    105123    if (dvdRet == DVDNAV_STATUS_ERR)
    106124    {
    107125        VERBOSE(VB_PLAYBACK, LOC_ERR +
     
    406424                currentTime = cellStart +
    407425                    (uint)(dvdnav_convert_time(&timeFromCellStart));
    408426                currentpos = GetReadPosition();
    409                
     427
    410428                if (seeking)
    411429                {
    412                     uint relativeTime = (uint)((seekTime - currentTime)/ 90000);
    413                     if (relativeTime == 0)
     430                   
     431                    int relativetime = (int)((seektime - currentTime)/ 90000);
     432                    if (relativetime <= 0)
    414433                    {
    415434                        seeking = false;
    416                         seekTime = 0;
     435                        seektime = 0;
    417436                    }
    418437                    else
    419                         dvdnav_time_search_within_cell(dvdnav, relativeTime);
     438                        dvdnav_time_search_within_cell(dvdnav, relativetime * 2);
    420439                }
    421                
     440
    422441                if (blockBuf != dvdBlockWriteBuf)
    423442                {
    424443                    dvdnav_free_cache_block(dvdnav, blockBuf);
     
    13101330#endif
    13111331}
    13121332
     1333/**\brief returns seconds left in the title
     1334 */
     1335uint DVDRingBufferPriv::TitleTimeLeft(void)
     1336{
     1337    return (GetTotalTimeOfTitle() -
     1338            GetCurrentTime());
     1339}
     1340
    13131341/** \brief converts palette values from YUV to RGB
    13141342 */
    13151343void DVDRingBufferPriv::guess_palette(uint32_t *rgba_palette,uint8_t *palette,
  • libmythtv/DVDRingBuffer.h

     
    9595    int NumMenuButtons(void) const;
    9696    void IgnoreStillOrWait(bool skip) { skipstillorwait = skip; }
    9797    uint GetCurrentTime(void) { return (currentTime / 90000); }
     98    uint TitleTimeLeft(void);
    9899    void  SetTrack(uint type, int trackNo);
    99100    int   GetTrack(uint type);
    100101    uint8_t GetNumAudioChannels(int id);
     
    162163    QString        dvdname;
    163164    QString        serialnumber;
    164165    bool           seeking;
    165     uint64_t       seekTime;
     166    uint64_t       seektime;
    166167    uint           currentTime;
     168    QMap<uint, uint> seekSpeedMap;
    167169
    168170    NuppelVideoPlayer *parent;
    169171
  • libmythtv/decoderbase.cpp

     
    549549            .arg(desiredFrame).arg(framesPlayed)
    550550            .arg((discardFrames) ? "do" : "don't"));
    551551
     552    if (ringBuffer->isDVD() &&
     553        ringBuffer->DVD()->TitleTimeLeft() < 5)
     554    {
     555        return false;
     556    }
    552557    // Rewind if we have already played the desiredFrame. The +1 is for
    553558    // MPEG4 NUV files, which need to decode an extra frame sometimes.
    554559    // This shouldn't effect how this works in general because this is
     
    723728    int diffTime = 0;
    724729    long long desiredTimePos;
    725730    int ffrewSkip = 1;
     731    int current_speed = 0;
    726732    if (GetNVP())
     733    {
    727734        ffrewSkip = GetNVP()->GetFFRewSkip();
     735        current_speed = (int)GetNVP()->GetNextPlaySpeed();
     736    }
     737
    728738    if (ffrewSkip == 1)
    729739    {
    730740        diffTime = (int)ceil((desiredFrame - framesPlayed) / fps);
     
    737747
    738748        if (desiredTimePos < 0)
    739749            desiredTimePos = 0;
     750        return (desiredTimePos * 90000LL);
    740751    }
    741     else
    742         desiredTimePos = (long long)ceil(desiredFrame / fps);
    743     return (desiredTimePos * 90000LL);
     752    return current_speed;
    744753}
    745754
    746755
  • libmythdvdnav/searching.c

     
    8383        } else {
    8484          vobu_start = next_vobu;
    8585        }
    86         address ++;
     86        address++;
    8787      }
    8888    }
    8989    else {
    9090      found = 0;
    9191      first_address = 0;
    9292      last_address  = admap->last_byte >> 2;
    93       while ((!found) && first_address <= last_address)
     93      while (first_address <= last_address)
    9494      {
    9595        address = (first_address + last_address) / 2;
    9696        next_vobu = admap->vobu_start_sectors[address];
     97        vobu_start = next_vobu;
    9798        if (seekto_block > next_vobu)
    9899          first_address = address + 1;
    99100        else if (seekto_block < next_vobu)
     
    103104        }
    104105      }
    105106      found = 1;
    106       vobu_start = next_vobu;
     107      if (next_vobu > seekto_block)
     108        vobu_start = admap->vobu_start_sectors[last_address - 1];
    107109    }
    108110    if(found) {
    109111      *vobu = vobu_start;
     
    640642  return DVDNAV_STATUS_OK;
    641643}
    642644
     645/** \brief Seeks the nearest VOBU to the relative_time within the cell
     646 * relative_time is in seconds * 2.
     647 * If you want 5 seconds ahead relative time = +10.
     648 * If relative_time is negative, then
     649 * look backwards within the cell.
     650 */
    643651dvdnav_status_t dvdnav_time_search_within_cell(dvdnav_t *this,
    644                     uint relative_time)
     652                    int relative_time)
    645653{
    646654  if(!this) {
    647655    printerr("Passed a NULL pointer.");
     
    649657  }
    650658
    651659  uint32_t cur_vobu, new_vobu, start, offset;
    652   int current_cell, i;
     660  uint32_t first_cell_nr, last_cell_nr, cell_nr;
     661  cell_playback_t *cell;
     662  int i, length, scan_admap;
    653663 
    654664  dsi_t * dsi;
    655665  dvd_state_t *state;
    656666  int stime[19] = { 240, 120, 60, 20, 15, 14, 13, 12, 11,
    657667                    10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
    658668  pthread_mutex_lock(&this->vm_lock);
     669  length = relative_time;
     670  state = &(this->vm->state);
     671  cell_nr = state->cellN -1;
     672  cell = &(state->pgc->cell_playback[cell_nr]);
    659673  cur_vobu = this->vobu.vobu_start;
    660   for (i = 0; i <= 19; i++) {
    661     if (stime[i]/2.0 <= relative_time) {
    662       dsi = dvdnav_get_current_nav_dsi(this);
    663       offset = dsi->vobu_sri.fwda[i];
    664       if (offset >> 31)
    665         new_vobu = cur_vobu + (dsi->vobu_sri.fwda[i] & 0xfffff);
    666       else
    667         new_vobu = cur_vobu;
    668       break;
     674  scan_admap = 0;
     675
     676  if (this->pgc_based) {
     677    first_cell_nr = 0;
     678    last_cell_nr = state->pgc->nr_of_cells - 1;
     679  } else {
     680    printerr("dvdnav_time_search_within_cell: works only if pgc_based is enabled");
     681    return DVDNAV_STATUS_ERR;
     682  }
     683
     684  if (length != 0)
     685  {
     686    dsi = dvdnav_get_current_nav_dsi(this);
     687    if (length > 0) {
     688      for (i = 0; i <= 19; i++) {
     689        if (stime[i]/2.0 <= length/2.0) {
     690          offset = dsi->vobu_sri.fwda[i];
     691          if (offset >> 31) {
     692            new_vobu = cur_vobu + (offset & 0xffff);
     693          } else {
     694            if (cell_nr == last_cell_nr) {
     695              offset = state->pgc->cell_playback[last_cell_nr].last_sector;
     696              scan_admap = 1;
     697            } else {
     698              cell_nr++;
     699              new_vobu =  state->pgc->cell_playback[cell_nr].first_sector;
     700            }
     701          }
     702          break;
     703        }
     704      }
     705    } else {
     706      for (i = 0; i <= 19; i++) {
     707        if (stime[18 - i]/2.0 >= abs(length)/2.0)
     708        {
     709          offset = dsi->vobu_sri.bwda[i];
     710          if (offset >> 31) {
     711            new_vobu = cur_vobu - (offset & 0xffff);
     712          } else {
     713            if (cell_nr == first_cell_nr) {
     714              new_vobu = 0;
     715            } else {
     716              cell_nr--;
     717              offset = state->pgc->cell_playback[cell_nr].last_sector;
     718              scan_admap = 1;
     719            }
     720          }
     721          break;
     722        }
     723      }
    669724    }
    670725  }
    671  
    672   state = &(this->vm->state);
    673   current_cell = state->cellN;
    674   start =  state->pgc->cell_playback[current_cell-1].first_sector;
    675   if (vm_jump_cell_block(this->vm, state->cellN, new_vobu - start)) {
     726
     727  if (scan_admap)
     728  {
     729    if (dvdnav_scan_admap(this, state->domain, offset, &new_vobu) == DVDNAV_STATUS_ERR)
     730      return DVDNAV_STATUS_ERR;
     731  }
     732  start =  state->pgc->cell_playback[cell_nr].first_sector;
     733  if (vm_jump_cell_block(this->vm, cell_nr+1, new_vobu - start)) {
    676734    this->vm->hop_channel += HOP_SEEK;
    677735  }
    678736  pthread_mutex_unlock(&this->vm_lock);
    679737  return DVDNAV_STATUS_OK;
    680738}
     739
  • libmythdvdnav/dvdnav.h

     
    369369dvdnav_status_t dvdnav_time_search(dvdnav_t *self,
    370370                                   uint64_t time, uint search_to_nearest_cell);
    371371
    372 /* Seeks the nearest VOBU to the relative_time within the cell
    373  * relative_time is in seconds
    374  */
    375 dvdnav_status_t dvdnav_time_search_within_cell(dvdnav_t *self,
    376                    uint relative_time);
     372int dvdnav_time_search_within_cell(dvdnav_t *self,
     373                   int relative_time);
    377374/*
    378375 * Stop playing current position and play the "GoUp"-program chain.
    379376 * (which generally leads to the title menu or a higer-level menu).
    380377 */
    381378dvdnav_status_t dvdnav_go_up(dvdnav_t *self);
    382 
    383379/*
    384380 * Stop playing the current position and start playback at the
    385381 * previous program (if it exists).