Ticket #2808: time_based_seeking.4.diff
File time_based_seeking.4.diff, 8.5 KB (added by , 17 years ago) |
---|
-
libs/libmythtv/DVDRingBuffer.cpp
45 45 seekpos(0), seekwhence(0), 46 46 dvdname(NULL), serialnumber(NULL), 47 47 seeking(false), seekTime(0), 48 currentTime(0), 48 49 parent(0) 49 50 { 50 51 memset(&dvdMenuButton, 0, sizeof(AVSubtitle)); … … 81 82 long long DVDRingBufferPriv::Seek(long long time) 82 83 { 83 84 seekTime = (uint64_t)time; 84 uint offset_divider= 1;85 uint searchToCellStart = 1; 85 86 int ffrewSkip = 1; 86 87 if (parent) 87 88 ffrewSkip = parent->GetFFRewSkip(); 88 dvdnav_status_t dvdRet = dvdnav_time_search(this->dvdnav, seekTime, offset_divider); 89 if (ffrewSkip != 1) 90 searchToCellStart = 0; 91 dvdnav_status_t dvdRet = 92 dvdnav_time_search(this->dvdnav, seekTime, searchToCellStart); 89 93 if (dvdRet == DVDNAV_STATUS_ERR) 90 94 { 91 95 VERBOSE(VB_PLAYBACK, LOC_ERR + … … 95 99 { 96 100 gotStop = false; 97 101 // TODO: precise seeking too inefficient 98 //if (time > 0 && ffrewSkip == 1)99 //seeking = true;102 if (time > 0 && ffrewSkip == 1) 103 seeking = true; 100 104 } 101 105 102 106 return currentpos; … … 212 216 return -1; 213 217 } 214 218 219 QMutexLocker lock(&seekLock); 215 220 while (needed) 216 221 { 217 222 blockBuf = dvdBlockWriteBuf; … … 391 396 } 392 397 } 393 398 399 dvd_time_t timeFromCellStart = dsi->dsi_gi.c_eltm; 400 currentTime = cellStart + 401 (uint)(dvdnav_convert_time(&timeFromCellStart)); 394 402 currentpos = GetReadPosition(); 395 403 396 404 if (seeking) 397 405 { 398 dvd_time_t timeFromCellStart = dsi->dsi_gi.c_eltm; 399 uint64_t currentpts = cellStart + 400 (uint)dvdnav_convert_time(&timeFromCellStart); 401 if (currentpts >= seekTime) 406 uint relativeTime = (uint)((seekTime - currentTime)/ 90000); 407 if (relativeTime == 0) 402 408 { 403 409 seeking = false; 404 410 seekTime = 0; 405 411 } 412 else 413 dvdnav_time_search_within_cell(dvdnav, relativeTime); 406 414 } 407 415 408 416 if (blockBuf != dvdBlockWriteBuf) … … 990 998 uint DVDRingBufferPriv::GetCurrentTime(void) 991 999 { 992 1000 QMutexLocker lock(&seekLock); 993 dsi_t *dvdnavDsi = dvdnav_get_current_nav_dsi(dvdnav); 994 dvd_time_t timeFromCellStart = dvdnavDsi->dsi_gi.c_eltm; 995 uint currentTime = GetCellStart() + 996 (uint)(dvdnav_convert_time(&timeFromCellStart) / 90000); 997 return currentTime; 1001 return (currentTime / 90000); 998 1002 } 999 1003 1000 1004 uint DVDRingBufferPriv::GetAudioLanguage(int id) -
libs/libmythtv/DVDRingBuffer.h
160 160 QString serialnumber; 161 161 bool seeking; 162 162 uint64_t seekTime; 163 uint currentTime; 163 164 164 165 NuppelVideoPlayer *parent; 165 166 -
libs/libmythdvdnav/searching.c
63 63 } 64 64 if(admap) { 65 65 uint32_t address = 0; 66 uint32_t vobu_start, next_vobu ;66 uint32_t vobu_start, next_vobu, first_address, last_address; 67 67 int32_t found = 0; 68 68 69 69 /* Search through ADMAP for best sector */ 70 70 vobu_start = SRI_END_OF_CELL; 71 /* FIXME: Implement a faster search algorithm */ 72 while((!found) && ((address<<2) < admap->last_byte)) { 73 next_vobu = admap->vobu_start_sectors[address]; 71 /* use binary search algorithm to improve efficiency */ 72 if (admap->last_byte > 20 && 73 admap->vobu_start_sectors[20] >= seekto_block) 74 { 75 while((!found) && ((address<<2) < admap->last_byte)) { 76 next_vobu = admap->vobu_start_sectors[address]; 74 77 75 /* fprintf(MSG_OUT, "libdvdnav: Found block %u\n", next_vobu); */76 77 if (next_vobu == seekto_block) {78 vobu_start = next_vobu; 79 found = 1;80 } else if (vobu_start < seekto_block && next_vobu > seekto_block){81 found = 1;82 } else {83 vobu_start = next_vobu;78 if (next_vobu == seekto_block) { 79 vobu_start = next_vobu; 80 found = 1; 81 } else if (vobu_start < seekto_block && next_vobu > seekto_block) { 82 found = 1; 83 } else { 84 vobu_start = next_vobu; 85 } 86 address ++; 84 87 } 85 address ++;86 88 } 89 else { 90 found = 0; 91 first_address = 0; 92 last_address = admap->last_byte >> 2; 93 while ((!found) && first_address <= last_address) 94 { 95 address = (first_address + last_address) / 2; 96 next_vobu = admap->vobu_start_sectors[address]; 97 if (seekto_block > next_vobu) 98 first_address = address + 1; 99 else if (seekto_block < next_vobu) 100 last_address = address - 1; 101 else { 102 vobu_start = next_vobu; 103 found = 1; 104 break; 105 } 106 } 107 } 87 108 if(found) { 88 109 *vobu = vobu_start; 89 110 return DVDNAV_STATUS_OK; … … 97 118 } 98 119 99 120 dvdnav_status_t dvdnav_time_search(dvdnav_t *this, 100 uint64_t time, uint offset_divider) {121 uint64_t time, uint search_to_nearest_cell) { 101 122 102 123 uint64_t target = time; 103 124 uint64_t length = 0; … … 110 131 111 132 cell_playback_t *cell; 112 133 dvd_state_t *state; 113 dsi_t *dsi;114 134 dvdnav_status_t result; 115 135 116 136 if(this->position_current.still != 0) { … … 146 166 cell_length = dvdnav_convert_time(&cell->playback_time); 147 167 length += cell_length; 148 168 if (target <= length) { 149 offset = (cell->last_sector - cell->first_sector) / offset_divider;169 offset = (cell->last_sector - cell->first_sector); 150 170 diff2 = ((double)target - (double)prev_length) / (double)cell_length; 151 171 offset = (diff2 * offset); 152 172 target = cell->first_sector; 153 target += offset;154 173 if (!search_to_nearest_cell) 174 target += offset; 155 175 found = 1; 156 176 break; 157 177 } … … 619 639 620 640 return DVDNAV_STATUS_OK; 621 641 } 642 643 dvdnav_status_t dvdnav_time_search_within_cell(dvdnav_t *this, 644 uint relative_time) 645 { 646 if(!this) { 647 printerr("Passed a NULL pointer."); 648 return DVDNAV_STATUS_ERR; 649 } 650 651 uint32_t cur_vobu, new_vobu, start; 652 int current_cell, i; 653 654 dsi_t * dsi; 655 dvd_state_t *state; 656 int stime[19] = { 240, 120, 60, 20, 15, 14, 13, 12, 11, 657 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; 658 pthread_mutex_lock(&this->vm_lock); 659 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 new_vobu = cur_vobu + (dsi->vobu_sri.fwda[i] & 0xfffff); 664 break; 665 } 666 } 667 668 state = &(this->vm->state); 669 current_cell = state->cellN; 670 start = state->pgc->cell_playback[current_cell-1].first_sector; 671 if (vm_jump_cell_block(this->vm, state->cellN, new_vobu - start)) { 672 this->vm->hop_channel += HOP_SEEK; 673 } 674 pthread_mutex_unlock(&this->vm_lock); 675 return DVDNAV_STATUS_OK; 676 } -
libs/libmythdvdnav/dvdnav.h
362 362 * Stop playing the current position and start playback of the title 363 363 * from the specified timecode. 364 364 * 365 * Currently unimplemented! 365 * if search_to_nearest_cell is set then search to the nearest Cell. 366 * and then use dvdnav_time_search_within_cell for further seeking 367 * Otherwise tries to guess the nearest VOBU by calculating an offset. 366 368 */ 367 369 dvdnav_status_t dvdnav_time_search(dvdnav_t *self, 368 uint64_t time, uint offset_divider);370 uint64_t time, uint search_to_nearest_cell); 369 371 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); 370 377 /* 371 378 * Stop playing current position and play the "GoUp"-program chain. 372 379 * (which generally leads to the title menu or a higer-level menu).