Ticket #2808: time_based_seeking.2.diff
File time_based_seeking.2.diff, 13.0 KB (added by , 17 years ago) |
---|
-
libs/libmythtv/NuppelVideoPlayer.cpp
1258 1258 long long real_skip = (toBegin) ? -curFrame : ffrew_skip; 1259 1259 GetDecoder()->DoRewind(curFrame + real_skip, false); 1260 1260 stopFFREW = framesPlayed <= keyframedist; 1261 if (ringBuffer->isDVD()) 1262 stopFFREW = (ringBuffer->DVD()->GetCurrentTime() < 2); 1261 1263 } 1262 1264 1263 1265 if (stopFFREW) … … 4006 4008 ret = 0; 4007 4009 else if (behind - ff <= maxtime * 2) 4008 4010 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 } 4009 4020 } 4010 4021 } 4011 4022 -
libs/libmythtv/DVDRingBuffer.cpp
1 1 #include <unistd.h> 2 #include <math.h> 2 3 3 4 #include "DVDRingBuffer.h" 4 5 #include "mythcontext.h" … … 26 27 dvdBlockRPos(0), dvdBlockWPos(0), 27 28 pgLength(0), pgcLength(0), 28 29 cellStart(0), pgStart(0), 30 currentpos(0), 29 31 lastNav(NULL), part(0), 30 32 title(0), titleParts(0), 31 33 gotStop(false), … … 40 42 menupktpts(0), curAudioTrack(0), 41 43 curSubtitleTrack(0), autoselectaudio(true), 42 44 autoselectsubtitle(true), 43 jumptotitle(true), repeatseek(false),45 jumptotitle(true), 44 46 seekpos(0), seekwhence(0), 45 47 dvdname(NULL), serialnumber(NULL), 48 seeking(false), seekTime(0), 46 49 parent(0) 47 50 { 48 51 memset(&dvdMenuButton, 0, sizeof(AVSubtitle)); … … 70 73 (NumMenuButtons() > 0)); 71 74 } 72 75 73 long long DVDRingBufferPriv::NormalSeek(long long pos, int whence)76 long long DVDRingBufferPriv::NormalSeek(long long time) 74 77 { 75 78 QMutexLocker lock(&seekLock); 76 return Seek( pos, whence);79 return Seek(time); 77 80 } 78 81 79 long long DVDRingBufferPriv::Seek(long long pos, int whence)82 long long DVDRingBufferPriv::Seek(long long time) 80 83 { 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) 83 87 { 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)); 89 90 } 90 gotStop = false; 91 return GetReadPosition(); 91 else 92 { 93 gotStop = false; 94 if (time > 0) 95 seeking = true; 96 } 97 98 return currentpos; 92 99 } 93 100 94 101 void DVDRingBufferPriv::GetDescForPos(QString &desc) const … … 173 180 { 174 181 uint32_t pos = 0; 175 182 uint32_t length = 1; 176 if (dvdnav) 183 if (dvdnav) 177 184 { 178 185 if (dvdnav_get_position(dvdnav, &pos, &length) == DVDNAV_STATUS_ERR) 179 186 { 180 187 // try one more time 181 usleep(10000);182 188 dvdnav_get_position(dvdnav, &pos, &length); 183 189 } 184 190 } … … 196 202 char *dest = (char*) data; 197 203 int offset = 0; 198 204 205 QMutexLocker lock(&seekLock); 199 206 if (gotStop) 200 207 { 201 208 VERBOSE(VB_IMPORTANT, LOC + "safe_read: called after DVDNAV_STOP"); … … 221 228 switch (dvdEvent) 222 229 { 223 230 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); 226 235 227 tot += DVD_BLOCK_SIZE; 228 236 tot += DVD_BLOCK_SIZE; 237 } 238 229 239 if (blockBuf != dvdBlockWriteBuf) 230 240 { 231 241 dvdnav_free_cache_block(dvdnav, blockBuf); … … 259 269 dvdnav_get_number_of_parts(dvdnav, title, &titleParts); 260 270 dvdnav_get_position(dvdnav, &pos, &length); 261 271 titleLength = length *DVD_BLOCK_SIZE; 262 cellstartPos = GetReadPosition(); 272 if (!seeking) 273 cellstartPos = GetReadPosition(); 263 274 264 275 VERBOSE(VB_PLAYBACK, 265 276 QString("DVDNAV_CELL_CHANGE: " … … 294 305 autoselectsubtitle = true; 295 306 } 296 307 297 if (repeatseek)298 {299 QMutexLocker lock(&seekLock);300 Seek(seekpos, seekwhence);301 repeatseek = false;302 }303 304 308 if (blockBuf != dvdBlockWriteBuf) 305 309 { 306 310 dvdnav_free_cache_block(dvdnav, blockBuf); … … 372 376 case DVDNAV_NAV_PACKET: 373 377 { 374 378 lastNav = (dvdnav_t *)blockBuf; 379 dsi_t *dsi = dvdnav_get_current_nav_dsi(dvdnav); 375 380 if (vobid == 0 && cellid == 0) 376 381 { 377 dsi_t *dsi = dvdnav_get_current_nav_dsi(dvdnav);378 382 vobid = dsi->dsi_gi.vobu_vob_idn; 379 383 cellid = dsi->dsi_gi.vobu_c_idn; 380 384 if ((lastvobid == vobid) && (lastcellid == cellid) … … 383 387 cellRepeated = true; 384 388 } 385 389 } 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 386 405 if (blockBuf != dvdBlockWriteBuf) 387 406 { 388 407 dvdnav_free_cache_block(dvdnav, blockBuf); … … 522 541 else 523 542 { 524 543 QMutexLocker lock(&seekLock); 525 Seek(0 ,SEEK_SET);544 Seek(0); 526 545 } 527 546 gotStop = false; 528 547 } … … 967 986 968 987 uint DVDRingBufferPriv::GetCurrentTime(void) 969 988 { 989 QMutexLocker lock(&seekLock); 970 990 dsi_t *dvdnavDsi = dvdnav_get_current_nav_dsi(dvdnav); 971 991 dvd_time_t timeFromCellStart = dvdnavDsi->dsi_gi.c_eltm; 972 992 uint currentTime = GetCellStart() + … … 1027 1047 if (type == kTrackTypeSubtitle) 1028 1048 { 1029 1049 curSubtitleTrack = trackNo; 1030 autoselectsubtitle = false; 1050 if (trackNo < 0) 1051 autoselectsubtitle = true; 1052 else 1053 autoselectsubtitle = false; 1031 1054 } 1032 1055 else if (type == kTrackTypeAudio) 1033 1056 { … … 1104 1127 { 1105 1128 QMutexLocker lock(&seekLock); 1106 1129 gotoCellStart = true; 1107 Seek(cell startPos, SEEK_SET);1130 Seek(cellStart); 1108 1131 } 1109 1132 1110 1133 /** -
libs/libmythtv/RingBuffer.cpp
1180 1180 #ifdef USING_FRONTEND 1181 1181 else if (dvdPriv) 1182 1182 { 1183 dvdPriv->NormalSeek(pos , whence);1183 dvdPriv->NormalSeek(pos); 1184 1184 } 1185 1185 #endif // USING_FRONTEND 1186 1186 else -
libs/libmythtv/DVDRingBuffer.h
79 79 bool nextTrack(void); 80 80 void prevTrack(void); 81 81 int safe_read(void *data, unsigned sz); 82 long long NormalSeek(long long pos, int whence);82 long long NormalSeek(long long time); 83 83 void SkipStillFrame(void); 84 84 void WaitSkip(void); 85 85 void GoToMenu(const QString str); … … 113 113 long long pgcLength; 114 114 long long cellStart; 115 115 long long pgStart; 116 long long currentpos; 116 117 dvdnav_t *lastNav; // This really belongs in the player. 117 118 int32_t part; 118 119 int32_t title; … … 153 154 bool autoselectaudio; 154 155 bool autoselectsubtitle; 155 156 bool jumptotitle; 156 bool repeatseek;157 157 long long seekpos; 158 158 int seekwhence; 159 159 QString dvdname; 160 160 QString serialnumber; 161 161 bool seeking; 162 uint64_t seekTime; 162 163 163 164 NuppelVideoPlayer *parent; 164 165 165 166 QMutex menuBtnLock; 166 167 QMutex seekLock; 167 168 168 long long Seek(long long pos, int whence);169 long long Seek(long long time); 169 170 bool DrawMenuButton(uint8_t *spu_pkt, int buf_size); 170 171 bool DVDButtonUpdate(bool b_mode); 171 172 void ClearMenuSPUParameters(void); -
libs/libmythtv/decoderbase.cpp
1 1 #include <unistd.h> 2 #include <math.h> 2 3 3 4 #include <algorithm> 4 5 using namespace std; … … 450 451 normalframes = max(normalframes, 0); 451 452 SeekReset(lastKey, normalframes, true, discardFrames); 452 453 453 if ( discardFrames)454 if (ringBuffer->isDVD() || discardFrames) 454 455 { 455 456 // We need to tell the NVP and VideoOutput what frame we're on. 456 457 GetNVP()->SetFramesPlayed(framesPlayed+1); … … 720 721 if (!ringBuffer->isDVD()) 721 722 return 0; 722 723 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); 726 738 } 727 739 728 740 long long DecoderBase::DVDCurrentFrameNumber(void) -
libs/libmythdvdnav/searching.c
101 101 102 102 uint64_t target = time; 103 103 uint64_t length = 0; 104 uint64_t cell_length = 0; 105 uint64_t prev_length = 0; 104 106 uint32_t first_cell_nr, last_cell_nr, cell_nr; 105 107 int32_t found; 108 uint64_t offset = 0; 109 float diff2 = 1.0; 110 106 111 cell_playback_t *cell; 107 112 dvd_state_t *state; 113 dsi_t *dsi; 108 114 dvdnav_status_t result; 109 115 110 116 if(this->position_current.still != 0) { … … 137 143 found = 0; 138 144 for(cell_nr = first_cell_nr; (cell_nr <= last_cell_nr) && !found; cell_nr ++) { 139 145 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; 147 166 148 167 found = 1; 149 168 break; 150 169 } 170 prev_length = length; 151 171 } 152 172 173 153 174 if(found) { 154 175 int32_t vobu; 155 176 #ifdef LOG_DEBUG … … 257 278 found = 0; 258 279 for(cell_nr = first_cell_nr; (cell_nr <= last_cell_nr) && !found; cell_nr ++) { 259 280 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; 262 285 found = 1; 263 286 break; 264 287 }