Mercurial > libdvdnav.hg
annotate searching.c @ 437:d8ec83537d07 src
Check for out-of-bounds values for pgcn
Fixes a crash in dvdnav_describe_title_chapters() with vlc, lsdvd, and
other video players caused by an invalid value for pgcn. This occurs
with the "Inside Man" DVD.
Based on patches by Bryce Harrington <bryce AT canonical DOT com>
and Vincent Mussard <frodon AT wanadoo DOT fr>
| author | rathann |
|---|---|
| date | Tue, 12 Nov 2013 00:55:10 +0000 |
| parents | a566d307173d |
| children |
| rev | line source |
|---|---|
| 131 | 1 /* |
| 0 | 2 * Copyright (C) 2000 Rich Wareham <richwareham@users.sourceforge.net> |
| 388 | 3 * |
| 0 | 4 * This file is part of libdvdnav, a DVD navigation library. |
| 388 | 5 * |
| 0 | 6 * libdvdnav is free software; you can redistribute it and/or modify |
| 7 * it under the terms of the GNU General Public License as published by | |
| 8 * the Free Software Foundation; either version 2 of the License, or | |
| 9 * (at your option) any later version. | |
| 388 | 10 * |
| 0 | 11 * libdvdnav is distributed in the hope that it will be useful, |
| 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 * GNU General Public License for more details. | |
| 388 | 15 * |
|
389
d3c273ced49c
Use consistent license headers everywhere: Fix wrong FSF address.
diego
parents:
388
diff
changeset
|
16 * You should have received a copy of the GNU General Public License along |
|
d3c273ced49c
Use consistent license headers everywhere: Fix wrong FSF address.
diego
parents:
388
diff
changeset
|
17 * with libdvdnav; if not, write to the Free Software Foundation, Inc., |
|
d3c273ced49c
Use consistent license headers everywhere: Fix wrong FSF address.
diego
parents:
388
diff
changeset
|
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| 0 | 19 */ |
| 20 | |
| 21 #ifdef HAVE_CONFIG_H | |
| 22 #include "config.h" | |
| 23 #endif | |
| 24 | |
| 114 | 25 #include <assert.h> |
| 278 | 26 #include <inttypes.h> |
|
294
2146ff691bcd
include limits.h; it was included in the previous dvdnav_internal.h and without it players segfault
nicodvb
parents:
290
diff
changeset
|
27 #include <limits.h> |
|
288
ce4230602517
moved away from dvdnav_internal.h inclusion of various system headers
nicodvb
parents:
285
diff
changeset
|
28 #include <stdio.h> |
|
ce4230602517
moved away from dvdnav_internal.h inclusion of various system headers
nicodvb
parents:
285
diff
changeset
|
29 #include <string.h> |
| 313 | 30 #include <stdlib.h> |
| 290 | 31 #include <sys/time.h> |
|
395
9c5aef10d165
Move dvd_types.h, dvdnav_events.h and dvdnav.h into a dvdnav directory.
reimar
parents:
392
diff
changeset
|
32 #include "dvdnav/dvdnav.h" |
| 386 | 33 #include <dvdread/nav_types.h> |
| 34 #include <dvdread/ifo_types.h> | |
|
285
52877d182e96
moved all header inclusions from .h to .c files; my word, I've never seen such a horrible entanglement as in this mess
nicodvb
parents:
278
diff
changeset
|
35 #include "remap.h" |
|
52877d182e96
moved all header inclusions from .h to .c files; my word, I've never seen such a horrible entanglement as in this mess
nicodvb
parents:
278
diff
changeset
|
36 #include "vm/decoder.h" |
|
52877d182e96
moved all header inclusions from .h to .c files; my word, I've never seen such a horrible entanglement as in this mess
nicodvb
parents:
278
diff
changeset
|
37 #include "vm/vm.h" |
| 0 | 38 #include "dvdnav_internal.h" |
| 39 | |
| 114 | 40 /* |
| 41 #define LOG_DEBUG | |
| 42 */ | |
| 43 | |
| 0 | 44 /* Searching API calls */ |
| 45 | |
| 24 | 46 /* Scan the ADMAP for a particular block number. */ |
| 47 /* Return placed in vobu. */ | |
| 48 /* Returns error status */ | |
| 114 | 49 /* FIXME: Maybe need to handle seeking outside current cell. */ |
| 417 | 50 static dvdnav_status_t dvdnav_scan_admap(dvdnav_t *this, int32_t domain, uint32_t seekto_block, int next, uint32_t *vobu) { |
| 24 | 51 vobu_admap_t *admap = NULL; |
| 114 | 52 |
| 53 #ifdef LOG_DEBUG | |
| 54 fprintf(MSG_OUT, "libdvdnav: Seeking to target %u ...\n", seekto_block); | |
| 55 #endif | |
| 24 | 56 *vobu = -1; |
| 57 | |
| 58 /* Search through the VOBU_ADMAP for the nearest VOBU | |
| 59 * to the target block */ | |
| 60 switch(domain) { | |
| 114 | 61 case FP_DOMAIN: |
| 62 case VMGM_DOMAIN: | |
| 63 admap = this->vm->vmgi->menu_vobu_admap; | |
| 64 break; | |
| 65 case VTSM_DOMAIN: | |
| 66 admap = this->vm->vtsi->menu_vobu_admap; | |
| 67 break; | |
| 68 case VTS_DOMAIN: | |
| 69 admap = this->vm->vtsi->vts_vobu_admap; | |
| 70 break; | |
| 71 default: | |
| 72 fprintf(MSG_OUT, "libdvdnav: Error: Unknown domain for seeking.\n"); | |
| 24 | 73 } |
| 74 if(admap) { | |
| 166 | 75 uint32_t address = 0; |
| 76 uint32_t vobu_start, next_vobu; | |
|
303
52cda7471a24
fixed off-by-one bug in scan_admap (copied reference code from ifo_print.c); reported by ggurov+abv-bg
nicodvb
parents:
302
diff
changeset
|
77 int admap_entries = (admap->last_byte + 1 - VOBU_ADMAP_SIZE)/VOBU_ADMAP_SIZE; |
| 24 | 78 |
| 79 /* Search through ADMAP for best sector */ | |
|
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
80 vobu_start = SRI_END_OF_CELL; |
| 24 | 81 /* FIXME: Implement a faster search algorithm */ |
|
304
0110b591bf9c
make dvdnav_sector_search() work correctly for blocks in the last vobu; patch by ggurov+abv-bg
nicodvb
parents:
303
diff
changeset
|
82 while(address < admap_entries) { |
| 24 | 83 next_vobu = admap->vobu_start_sectors[address]; |
| 84 | |
| 76 | 85 /* fprintf(MSG_OUT, "libdvdnav: Found block %u\n", next_vobu); */ |
| 24 | 86 |
| 305 | 87 if(vobu_start <= seekto_block && next_vobu > seekto_block) |
|
304
0110b591bf9c
make dvdnav_sector_search() work correctly for blocks in the last vobu; patch by ggurov+abv-bg
nicodvb
parents:
303
diff
changeset
|
88 break; |
| 305 | 89 vobu_start = next_vobu; |
| 90 address++; | |
| 24 | 91 } |
| 417 | 92 *vobu = next ? next_vobu : vobu_start; |
| 305 | 93 return DVDNAV_STATUS_OK; |
| 24 | 94 } |
| 76 | 95 fprintf(MSG_OUT, "libdvdnav: admap not located\n"); |
| 193 | 96 return DVDNAV_STATUS_ERR; |
| 24 | 97 } |
| 98 | |
| 265 | 99 /* FIXME: right now, this function does not use the time tables but interpolates |
| 100 only the cell times */ | |
| 101 dvdnav_status_t dvdnav_time_search(dvdnav_t *this, | |
| 102 uint64_t time) { | |
| 388 | 103 |
| 265 | 104 uint64_t target = time; |
| 105 uint64_t length = 0; | |
| 106 uint32_t first_cell_nr, last_cell_nr, cell_nr; | |
| 107 int32_t found; | |
| 108 cell_playback_t *cell; | |
| 109 dvd_state_t *state; | |
| 110 | |
| 111 if(this->position_current.still != 0) { | |
| 112 printerr("Cannot seek in a still frame."); | |
| 113 return DVDNAV_STATUS_ERR; | |
| 114 } | |
| 388 | 115 |
| 265 | 116 pthread_mutex_lock(&this->vm_lock); |
| 117 state = &(this->vm->state); | |
| 118 if(!state->pgc) { | |
| 119 printerr("No current PGC."); | |
| 120 pthread_mutex_unlock(&this->vm_lock); | |
| 121 return DVDNAV_STATUS_ERR; | |
| 122 } | |
| 123 | |
| 388 | 124 |
| 125 this->cur_cell_time = 0; | |
| 265 | 126 if (this->pgc_based) { |
| 127 first_cell_nr = 1; | |
| 128 last_cell_nr = state->pgc->nr_of_cells; | |
| 129 } else { | |
| 130 /* Find start cell of program. */ | |
| 131 first_cell_nr = state->pgc->program_map[state->pgN-1]; | |
| 132 /* Find end cell of program */ | |
| 133 if(state->pgN < state->pgc->nr_of_programs) | |
| 134 last_cell_nr = state->pgc->program_map[state->pgN] - 1; | |
| 135 else | |
| 136 last_cell_nr = state->pgc->nr_of_cells; | |
| 137 } | |
| 138 | |
| 139 found = 0; | |
| 140 for(cell_nr = first_cell_nr; (cell_nr <= last_cell_nr) && !found; cell_nr ++) { | |
| 141 cell = &(state->pgc->cell_playback[cell_nr-1]); | |
|
270
5d091ebc4c3b
in dvdnav_time_search() skip secondary angles when searching the cell to hump to
nicodvb
parents:
269
diff
changeset
|
142 if(cell->block_type == BLOCK_TYPE_ANGLE_BLOCK && cell->block_mode != BLOCK_MODE_FIRST_CELL) |
|
5d091ebc4c3b
in dvdnav_time_search() skip secondary angles when searching the cell to hump to
nicodvb
parents:
269
diff
changeset
|
143 continue; |
| 265 | 144 length = dvdnav_convert_time(&cell->playback_time); |
| 145 if (target >= length) { | |
| 146 target -= length; | |
| 147 } else { | |
| 148 /* FIXME: there must be a better way than interpolation */ | |
| 149 target = target * (cell->last_sector - cell->first_sector + 1) / length; | |
| 150 target += cell->first_sector; | |
| 388 | 151 |
| 265 | 152 found = 1; |
| 153 break; | |
| 154 } | |
| 155 } | |
| 156 | |
| 157 if(found) { | |
|
275
f8ba866996f9
in dvdnav_time_search() vobu and start are uint32_t
nicodvb
parents:
273
diff
changeset
|
158 uint32_t vobu; |
| 265 | 159 #ifdef LOG_DEBUG |
| 160 fprintf(MSG_OUT, "libdvdnav: Seeking to cell %i from choice of %i to %i\n", | |
| 161 cell_nr, first_cell_nr, last_cell_nr); | |
| 162 #endif | |
| 417 | 163 if (dvdnav_scan_admap(this, state->domain, target, 0, &vobu) == DVDNAV_STATUS_OK) { |
|
275
f8ba866996f9
in dvdnav_time_search() vobu and start are uint32_t
nicodvb
parents:
273
diff
changeset
|
164 uint32_t start = state->pgc->cell_playback[cell_nr-1].first_sector; |
| 388 | 165 |
| 265 | 166 if (vm_jump_cell_block(this->vm, cell_nr, vobu - start)) { |
| 167 #ifdef LOG_DEBUG | |
| 168 fprintf(MSG_OUT, "libdvdnav: After cellN=%u blockN=%u target=%x vobu=%x start=%x\n" , | |
| 169 state->cellN, state->blockN, target, vobu, start); | |
| 170 #endif | |
| 171 this->vm->hop_channel += HOP_SEEK; | |
| 172 pthread_mutex_unlock(&this->vm_lock); | |
| 173 return DVDNAV_STATUS_OK; | |
| 174 } | |
| 175 } | |
| 176 } | |
| 388 | 177 |
| 265 | 178 fprintf(MSG_OUT, "libdvdnav: Error when seeking\n"); |
| 179 printerr("Error when seeking."); | |
| 180 pthread_mutex_unlock(&this->vm_lock); | |
| 181 return DVDNAV_STATUS_ERR; | |
| 182 } | |
| 183 | |
|
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
184 dvdnav_status_t dvdnav_sector_search(dvdnav_t *this, |
| 195 | 185 uint64_t offset, int32_t origin) { |
| 0 | 186 uint32_t target = 0; |
| 417 | 187 uint32_t current_pos; |
| 188 uint32_t cur_sector; | |
| 189 uint32_t cur_cell_nr; | |
| 0 | 190 uint32_t length = 0; |
| 114 | 191 uint32_t first_cell_nr, last_cell_nr, cell_nr; |
| 195 | 192 int32_t found; |
| 417 | 193 int forward = 0; |
| 114 | 194 cell_playback_t *cell; |
| 0 | 195 dvd_state_t *state; |
| 196 dvdnav_status_t result; | |
| 197 | |
| 114 | 198 if(this->position_current.still != 0) { |
| 199 printerr("Cannot seek in a still frame."); | |
| 193 | 200 return DVDNAV_STATUS_ERR; |
| 114 | 201 } |
| 388 | 202 |
|
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
203 result = dvdnav_get_position(this, &target, &length); |
| 0 | 204 if(!result) { |
| 193 | 205 return DVDNAV_STATUS_ERR; |
| 0 | 206 } |
| 388 | 207 |
| 114 | 208 pthread_mutex_lock(&this->vm_lock); |
| 209 state = &(this->vm->state); | |
| 210 if(!state->pgc) { | |
| 211 printerr("No current PGC."); | |
| 212 pthread_mutex_unlock(&this->vm_lock); | |
| 193 | 213 return DVDNAV_STATUS_ERR; |
| 114 | 214 } |
|
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
215 #ifdef LOG_DEBUG |
| 388 | 216 fprintf(MSG_OUT, "libdvdnav: seeking to offset=%lu pos=%u length=%u\n", offset, target, length); |
|
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
217 fprintf(MSG_OUT, "libdvdnav: Before cellN=%u blockN=%u\n", state->cellN, state->blockN); |
|
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
218 #endif |
| 114 | 219 |
| 417 | 220 current_pos = target; |
| 221 cur_sector = this->vobu.vobu_start + this->vobu.blockN; | |
| 222 cur_cell_nr = state->cellN; | |
| 223 | |
| 0 | 224 switch(origin) { |
| 225 case SEEK_SET: | |
|
302
ef017423e37c
since sectors range in [0..len-1] the target offset must be validated not to exceed length-1; reported by ggurov@abv.bg
nicodvb
parents:
301
diff
changeset
|
226 if(offset >= length) { |
| 114 | 227 printerr("Request to seek behind end."); |
|
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
228 pthread_mutex_unlock(&this->vm_lock); |
| 193 | 229 return DVDNAV_STATUS_ERR; |
| 0 | 230 } |
| 231 target = offset; | |
| 232 break; | |
| 233 case SEEK_CUR: | |
|
302
ef017423e37c
since sectors range in [0..len-1] the target offset must be validated not to exceed length-1; reported by ggurov@abv.bg
nicodvb
parents:
301
diff
changeset
|
234 if(target + offset >= length) { |
| 114 | 235 printerr("Request to seek behind end."); |
|
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
236 pthread_mutex_unlock(&this->vm_lock); |
| 193 | 237 return DVDNAV_STATUS_ERR; |
| 0 | 238 } |
| 239 target += offset; | |
| 240 break; | |
| 241 case SEEK_END: | |
|
301
4e24652c5ddf
in dvdnav_sector_search() replaced check (length-offset<0) with safer (length<offset) ; patch by ggurob abv bg
nicodvb
parents:
297
diff
changeset
|
242 if(length < offset) { |
| 114 | 243 printerr("Request to seek before start."); |
|
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
244 pthread_mutex_unlock(&this->vm_lock); |
| 193 | 245 return DVDNAV_STATUS_ERR; |
| 0 | 246 } |
| 247 target = length - offset; | |
|
102
3e6970dbe8d6
- allow seeking to offset 0 (pressing '0' in xine won't work otherwise)
mroi
parents:
90
diff
changeset
|
248 break; |
| 0 | 249 default: |
| 250 /* Error occured */ | |
| 114 | 251 printerr("Illegal seek mode."); |
|
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
252 pthread_mutex_unlock(&this->vm_lock); |
| 193 | 253 return DVDNAV_STATUS_ERR; |
| 0 | 254 } |
| 417 | 255 forward = target > current_pos; |
| 388 | 256 |
|
269
77e472cef5f8
implemented dvdnav_get_current_time() with obvious meaning
nicodvb
parents:
265
diff
changeset
|
257 this->cur_cell_time = 0; |
| 132 | 258 if (this->pgc_based) { |
| 259 first_cell_nr = 1; | |
| 260 last_cell_nr = state->pgc->nr_of_cells; | |
| 0 | 261 } else { |
| 132 | 262 /* Find start cell of program. */ |
| 263 first_cell_nr = state->pgc->program_map[state->pgN-1]; | |
| 264 /* Find end cell of program */ | |
| 265 if(state->pgN < state->pgc->nr_of_programs) | |
| 266 last_cell_nr = state->pgc->program_map[state->pgN] - 1; | |
| 267 else | |
| 268 last_cell_nr = state->pgc->nr_of_cells; | |
| 0 | 269 } |
| 132 | 270 |
| 114 | 271 found = 0; |
| 0 | 272 for(cell_nr = first_cell_nr; (cell_nr <= last_cell_nr) && !found; cell_nr ++) { |
| 273 cell = &(state->pgc->cell_playback[cell_nr-1]); | |
|
297
eb96940d93e0
in dvdnav_sector_search() when playing multiangle titles skip cells not corresponding to BLOCK_MODE_FIRST_CELL
nicodvb
parents:
294
diff
changeset
|
274 if(cell->block_type == BLOCK_TYPE_ANGLE_BLOCK && cell->block_mode != BLOCK_MODE_FIRST_CELL) |
|
eb96940d93e0
in dvdnav_sector_search() when playing multiangle titles skip cells not corresponding to BLOCK_MODE_FIRST_CELL
nicodvb
parents:
294
diff
changeset
|
275 continue; |
|
130
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
276 length = cell->last_sector - cell->first_sector + 1; |
|
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
277 if (target >= length) { |
|
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
278 target -= length; |
|
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
279 } else { |
| 131 | 280 /* convert the target sector from Cell-relative to absolute physical sector */ |
|
130
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
281 target += cell->first_sector; |
| 417 | 282 if (forward && (cell_nr == cur_cell_nr)) { |
| 283 uint32_t vobu; | |
| 284 /* if we are seeking forward from the current position, make sure | |
| 285 * we move to a new position that is after our current position. | |
| 286 * simply truncating to the vobu will go backwards */ | |
| 287 if (dvdnav_scan_admap(this, state->domain, target, 0, &vobu) != DVDNAV_STATUS_OK) | |
| 288 break; | |
| 289 if (vobu <= cur_sector) { | |
| 290 if (dvdnav_scan_admap(this, state->domain, target, 1, &vobu) != DVDNAV_STATUS_OK) | |
| 291 break; | |
| 292 if (vobu > cell->last_sector) { | |
| 293 if (cell_nr == last_cell_nr) | |
| 294 break; | |
| 295 cell_nr++; | |
| 296 cell = &(state->pgc->cell_playback[cell_nr-1]); | |
| 297 target = cell->first_sector; | |
| 298 } else { | |
| 299 target = vobu; | |
| 300 } | |
| 301 } | |
| 302 } | |
| 114 | 303 found = 1; |
|
130
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
304 break; |
| 0 | 305 } |
| 306 } | |
| 307 | |
| 114 | 308 if(found) { |
|
376
430d842f35bd
in dvdnav_sector_search() vobu is uint32_t it; patch by Erik Hovland org
nicodvb
parents:
332
diff
changeset
|
309 uint32_t vobu; |
| 114 | 310 #ifdef LOG_DEBUG |
| 76 | 311 fprintf(MSG_OUT, "libdvdnav: Seeking to cell %i from choice of %i to %i\n", |
|
130
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
312 cell_nr, first_cell_nr, last_cell_nr); |
| 114 | 313 #endif |
| 417 | 314 if (dvdnav_scan_admap(this, state->domain, target, 0, &vobu) == DVDNAV_STATUS_OK) { |
|
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
315 int32_t start = state->pgc->cell_playback[cell_nr-1].first_sector; |
| 388 | 316 |
|
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
317 if (vm_jump_cell_block(this->vm, cell_nr, vobu - start)) { |
| 114 | 318 #ifdef LOG_DEBUG |
|
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
319 fprintf(MSG_OUT, "libdvdnav: After cellN=%u blockN=%u target=%x vobu=%x start=%x\n" , |
|
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
320 state->cellN, state->blockN, target, vobu, start); |
| 114 | 321 #endif |
|
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
322 this->vm->hop_channel += HOP_SEEK; |
|
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
323 pthread_mutex_unlock(&this->vm_lock); |
| 193 | 324 return DVDNAV_STATUS_OK; |
|
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
325 } |
|
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
326 } |
| 0 | 327 } |
| 388 | 328 |
|
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
329 fprintf(MSG_OUT, "libdvdnav: Error when seeking\n"); |
| 388 | 330 fprintf(MSG_OUT, "libdvdnav: FIXME: Implement seeking to location %u\n", target); |
| 114 | 331 printerr("Error when seeking."); |
|
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
332 pthread_mutex_unlock(&this->vm_lock); |
| 193 | 333 return DVDNAV_STATUS_ERR; |
| 0 | 334 } |
| 335 | |
| 195 | 336 dvdnav_status_t dvdnav_part_search(dvdnav_t *this, int32_t part) { |
| 337 int32_t title, old_part; | |
| 388 | 338 |
| 193 | 339 if (dvdnav_current_title_info(this, &title, &old_part) == DVDNAV_STATUS_OK) |
| 114 | 340 return dvdnav_part_play(this, title, part); |
| 193 | 341 return DVDNAV_STATUS_ERR; |
| 0 | 342 } |
| 343 | |
|
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
344 dvdnav_status_t dvdnav_prev_pg_search(dvdnav_t *this) { |
| 114 | 345 pthread_mutex_lock(&this->vm_lock); |
| 346 if(!this->vm->state.pgc) { | |
| 347 printerr("No current PGC."); | |
| 348 pthread_mutex_unlock(&this->vm_lock); | |
| 193 | 349 return DVDNAV_STATUS_ERR; |
| 114 | 350 } |
|
68
3b45c78f061e
Some NULL-pointer check from aschultz@cs.uni-magdeburg.de
richwareham
parents:
63
diff
changeset
|
351 |
| 114 | 352 #ifdef LOG_DEBUG |
| 113 | 353 fprintf(MSG_OUT, "libdvdnav: previous chapter\n"); |
| 114 | 354 #endif |
| 355 if (!vm_jump_prev_pg(this->vm)) { | |
| 356 fprintf(MSG_OUT, "libdvdnav: previous chapter failed.\n"); | |
| 357 printerr("Skip to previous chapter failed."); | |
|
102
3e6970dbe8d6
- allow seeking to offset 0 (pressing '0' in xine won't work otherwise)
mroi
parents:
90
diff
changeset
|
358 pthread_mutex_unlock(&this->vm_lock); |
| 193 | 359 return DVDNAV_STATUS_ERR; |
| 0 | 360 } |
|
269
77e472cef5f8
implemented dvdnav_get_current_time() with obvious meaning
nicodvb
parents:
265
diff
changeset
|
361 this->cur_cell_time = 0; |
|
102
3e6970dbe8d6
- allow seeking to offset 0 (pressing '0' in xine won't work otherwise)
mroi
parents:
90
diff
changeset
|
362 this->position_current.still = 0; |
|
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
363 this->vm->hop_channel++; |
| 114 | 364 #ifdef LOG_DEBUG |
| 76 | 365 fprintf(MSG_OUT, "libdvdnav: previous chapter done\n"); |
| 114 | 366 #endif |
|
102
3e6970dbe8d6
- allow seeking to offset 0 (pressing '0' in xine won't work otherwise)
mroi
parents:
90
diff
changeset
|
367 pthread_mutex_unlock(&this->vm_lock); |
| 0 | 368 |
| 193 | 369 return DVDNAV_STATUS_OK; |
| 0 | 370 } |
| 371 | |
|
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
372 dvdnav_status_t dvdnav_top_pg_search(dvdnav_t *this) { |
| 114 | 373 pthread_mutex_lock(&this->vm_lock); |
| 374 if(!this->vm->state.pgc) { | |
| 375 printerr("No current PGC."); | |
| 376 pthread_mutex_unlock(&this->vm_lock); | |
| 193 | 377 return DVDNAV_STATUS_ERR; |
| 114 | 378 } |
|
68
3b45c78f061e
Some NULL-pointer check from aschultz@cs.uni-magdeburg.de
richwareham
parents:
63
diff
changeset
|
379 |
| 114 | 380 #ifdef LOG_DEBUG |
| 381 fprintf(MSG_OUT, "libdvdnav: top chapter\n"); | |
| 382 #endif | |
| 383 if (!vm_jump_top_pg(this->vm)) { | |
| 384 fprintf(MSG_OUT, "libdvdnav: top chapter failed.\n"); | |
| 385 printerr("Skip to top chapter failed."); | |
| 113 | 386 pthread_mutex_unlock(&this->vm_lock); |
| 193 | 387 return DVDNAV_STATUS_ERR; |
| 0 | 388 } |
|
269
77e472cef5f8
implemented dvdnav_get_current_time() with obvious meaning
nicodvb
parents:
265
diff
changeset
|
389 this->cur_cell_time = 0; |
|
102
3e6970dbe8d6
- allow seeking to offset 0 (pressing '0' in xine won't work otherwise)
mroi
parents:
90
diff
changeset
|
390 this->position_current.still = 0; |
|
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
391 this->vm->hop_channel++; |
| 114 | 392 #ifdef LOG_DEBUG |
| 393 fprintf(MSG_OUT, "libdvdnav: top chapter done\n"); | |
| 394 #endif | |
| 395 pthread_mutex_unlock(&this->vm_lock); | |
| 396 | |
| 193 | 397 return DVDNAV_STATUS_OK; |
| 114 | 398 } |
| 399 | |
| 400 dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *this) { | |
|
122
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
401 vm_t *try_vm; |
| 114 | 402 |
| 403 pthread_mutex_lock(&this->vm_lock); | |
| 404 if(!this->vm->state.pgc) { | |
| 405 printerr("No current PGC."); | |
| 406 pthread_mutex_unlock(&this->vm_lock); | |
| 193 | 407 return DVDNAV_STATUS_ERR; |
| 114 | 408 } |
| 409 | |
| 410 #ifdef LOG_DEBUG | |
| 411 fprintf(MSG_OUT, "libdvdnav: next chapter\n"); | |
| 412 #endif | |
|
122
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
413 /* make a copy of current VM and try to navigate the copy to the next PG */ |
|
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
414 try_vm = vm_new_copy(this->vm); |
|
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
415 if (!vm_jump_next_pg(try_vm) || try_vm->stopped) { |
|
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
416 vm_free_copy(try_vm); |
|
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
417 /* next_pg failed, try to jump at least to the next cell */ |
|
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
418 try_vm = vm_new_copy(this->vm); |
|
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
419 vm_get_next_cell(try_vm); |
|
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
420 if (try_vm->stopped) { |
|
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
421 vm_free_copy(try_vm); |
|
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
422 fprintf(MSG_OUT, "libdvdnav: next chapter failed.\n"); |
|
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
423 printerr("Skip to next chapter failed."); |
|
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
424 pthread_mutex_unlock(&this->vm_lock); |
| 193 | 425 return DVDNAV_STATUS_ERR; |
|
122
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
426 } |
| 114 | 427 } |
|
269
77e472cef5f8
implemented dvdnav_get_current_time() with obvious meaning
nicodvb
parents:
265
diff
changeset
|
428 this->cur_cell_time = 0; |
|
122
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
429 /* merge changes on success */ |
|
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
430 vm_merge(this->vm, try_vm); |
|
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
431 vm_free_copy(try_vm); |
| 114 | 432 this->position_current.still = 0; |
| 433 this->vm->hop_channel++; | |
| 434 #ifdef LOG_DEBUG | |
| 76 | 435 fprintf(MSG_OUT, "libdvdnav: next chapter done\n"); |
| 114 | 436 #endif |
|
102
3e6970dbe8d6
- allow seeking to offset 0 (pressing '0' in xine won't work otherwise)
mroi
parents:
90
diff
changeset
|
437 pthread_mutex_unlock(&this->vm_lock); |
| 0 | 438 |
| 193 | 439 return DVDNAV_STATUS_OK; |
| 0 | 440 } |
| 441 | |
|
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
442 dvdnav_status_t dvdnav_menu_call(dvdnav_t *this, DVDMenuID_t menu) { |
| 125 | 443 vm_t *try_vm; |
| 388 | 444 |
| 114 | 445 pthread_mutex_lock(&this->vm_lock); |
| 446 if(!this->vm->state.pgc) { | |
| 447 printerr("No current PGC."); | |
| 448 pthread_mutex_unlock(&this->vm_lock); | |
| 193 | 449 return DVDNAV_STATUS_ERR; |
| 114 | 450 } |
| 388 | 451 |
|
269
77e472cef5f8
implemented dvdnav_get_current_time() with obvious meaning
nicodvb
parents:
265
diff
changeset
|
452 this->cur_cell_time = 0; |
| 125 | 453 /* make a copy of current VM and try to navigate the copy to the menu */ |
| 454 try_vm = vm_new_copy(this->vm); | |
|
162
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
455 if ( (menu == DVD_MENU_Escape) && (this->vm->state.domain != VTS_DOMAIN)) { |
|
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
456 /* Try resume */ |
| 167 | 457 if (vm_jump_resume(try_vm) && !try_vm->stopped) { |
|
162
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
458 /* merge changes on success */ |
|
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
459 vm_merge(this->vm, try_vm); |
|
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
460 vm_free_copy(try_vm); |
|
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
461 this->position_current.still = 0; |
|
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
462 this->vm->hop_channel++; |
| 388 | 463 pthread_mutex_unlock(&this->vm_lock); |
| 193 | 464 return DVDNAV_STATUS_OK; |
|
162
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
465 } |
|
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
466 } |
| 166 | 467 if (menu == DVD_MENU_Escape) menu = DVD_MENU_Root; |
| 388 | 468 |
| 125 | 469 if (vm_jump_menu(try_vm, menu) && !try_vm->stopped) { |
| 470 /* merge changes on success */ | |
| 471 vm_merge(this->vm, try_vm); | |
| 472 vm_free_copy(try_vm); | |
| 129 | 473 this->position_current.still = 0; |
| 114 | 474 this->vm->hop_channel++; |
| 388 | 475 pthread_mutex_unlock(&this->vm_lock); |
| 193 | 476 return DVDNAV_STATUS_OK; |
| 114 | 477 } else { |
| 125 | 478 vm_free_copy(try_vm); |
| 479 printerr("No such menu or menu not reachable."); | |
| 388 | 480 pthread_mutex_unlock(&this->vm_lock); |
| 193 | 481 return DVDNAV_STATUS_ERR; |
| 114 | 482 } |
| 0 | 483 } |
| 484 | |
| 195 | 485 dvdnav_status_t dvdnav_get_position(dvdnav_t *this, uint32_t *pos, |
| 486 uint32_t *len) { | |
| 0 | 487 uint32_t cur_sector; |
| 195 | 488 int32_t cell_nr, first_cell_nr, last_cell_nr; |
|
130
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
489 cell_playback_t *cell; |
| 0 | 490 dvd_state_t *state; |
| 114 | 491 |
| 492 if(!this->started) { | |
| 493 printerr("Virtual DVD machine not started."); | |
| 193 | 494 return DVDNAV_STATUS_ERR; |
| 114 | 495 } |
| 496 | |
| 497 pthread_mutex_lock(&this->vm_lock); | |
|
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
498 state = &(this->vm->state); |
|
224
f19fce15577b
fix assertion failure when someone asks for the position between an Exit
mroi
parents:
195
diff
changeset
|
499 if(!state->pgc || this->vm->stopped) { |
| 114 | 500 printerr("No current PGC."); |
| 501 pthread_mutex_unlock(&this->vm_lock); | |
| 193 | 502 return DVDNAV_STATUS_ERR; |
| 0 | 503 } |
|
181
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
504 if (this->position_current.hop_channel != this->vm->hop_channel || |
|
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
505 this->position_current.domain != state->domain || |
|
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
506 this->position_current.vts != state->vtsN || |
|
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
507 this->position_current.cell_restart != state->cell_restart) { |
|
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
508 printerr("New position not yet determined."); |
|
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
509 pthread_mutex_unlock(&this->vm_lock); |
| 193 | 510 return DVDNAV_STATUS_ERR; |
|
181
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
511 } |
| 114 | 512 |
| 0 | 513 /* Get current sector */ |
|
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
514 cur_sector = this->vobu.vobu_start + this->vobu.blockN; |
| 0 | 515 |
| 132 | 516 if (this->pgc_based) { |
| 517 first_cell_nr = 1; | |
| 518 last_cell_nr = state->pgc->nr_of_cells; | |
| 0 | 519 } else { |
| 132 | 520 /* Find start cell of program. */ |
| 521 first_cell_nr = state->pgc->program_map[state->pgN-1]; | |
| 522 /* Find end cell of program */ | |
| 523 if(state->pgN < state->pgc->nr_of_programs) | |
| 524 last_cell_nr = state->pgc->program_map[state->pgN] - 1; | |
| 525 else | |
| 526 last_cell_nr = state->pgc->nr_of_cells; | |
| 0 | 527 } |
| 132 | 528 |
|
130
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
529 *pos = -1; |
|
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
530 *len = 0; |
|
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
531 for (cell_nr = first_cell_nr; cell_nr <= last_cell_nr; cell_nr++) { |
|
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
532 cell = &(state->pgc->cell_playback[cell_nr-1]); |
|
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
533 if (cell_nr == state->cellN) { |
|
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
534 /* the current sector is in this cell, |
|
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
535 * pos is length of PG up to here + sector's offset in this cell */ |
|
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
536 *pos = *len + cur_sector - cell->first_sector; |
|
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
537 } |
|
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
538 *len += cell->last_sector - cell->first_sector + 1; |
|
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
539 } |
| 388 | 540 |
| 166 | 541 assert((signed)*pos != -1); |
| 0 | 542 |
| 114 | 543 pthread_mutex_unlock(&this->vm_lock); |
| 0 | 544 |
| 193 | 545 return DVDNAV_STATUS_OK; |
| 0 | 546 } |
| 547 | |
|
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
548 dvdnav_status_t dvdnav_get_position_in_title(dvdnav_t *this, |
| 195 | 549 uint32_t *pos, |
| 550 uint32_t *len) { | |
|
8
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
551 uint32_t cur_sector; |
|
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
552 uint32_t first_cell_nr; |
|
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
553 uint32_t last_cell_nr; |
|
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
554 cell_playback_t *first_cell; |
|
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
555 cell_playback_t *last_cell; |
|
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
556 dvd_state_t *state; |
| 114 | 557 |
| 558 state = &(this->vm->state); | |
| 559 if(!state->pgc) { | |
| 560 printerr("No current PGC."); | |
| 193 | 561 return DVDNAV_STATUS_ERR; |
| 114 | 562 } |
| 563 | |
|
8
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
564 /* Get current sector */ |
|
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
565 cur_sector = this->vobu.vobu_start + this->vobu.blockN; |
|
8
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
566 |
|
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
567 /* Now find first and last cells in title. */ |
|
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
568 first_cell_nr = state->pgc->program_map[0]; |
|
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
569 first_cell = &(state->pgc->cell_playback[first_cell_nr-1]); |
|
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
570 last_cell_nr = state->pgc->nr_of_cells; |
|
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
571 last_cell = &(state->pgc->cell_playback[last_cell_nr-1]); |
| 388 | 572 |
|
8
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
573 *pos = cur_sector - first_cell->first_sector; |
|
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
574 *len = last_cell->last_sector - first_cell->first_sector; |
| 388 | 575 |
| 193 | 576 return DVDNAV_STATUS_OK; |
|
8
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
577 } |
| 313 | 578 |
|
315
9abc06e356ff
now dvdnav_describe_title_chapters() also returns the duration of the title
nicodvb
parents:
314
diff
changeset
|
579 uint32_t dvdnav_describe_title_chapters(dvdnav_t *this, int32_t title, uint64_t **times, uint64_t *duration) { |
| 313 | 580 int32_t retval=0; |
| 581 uint16_t parts, i; | |
| 582 title_info_t *ptitle = NULL; | |
| 583 ptt_info_t *ptt = NULL; | |
|
398
ec2408d48b85
in dvdnav_describe_chapters() ifo could be leaked in case of erros; fixed by Erik Hovland
nicodvb
parents:
395
diff
changeset
|
584 ifo_handle_t *ifo = NULL; |
| 313 | 585 pgc_t *pgc; |
| 586 cell_playback_t *cell; | |
| 587 uint64_t length, *tmp=NULL; | |
| 588 | |
|
314
ba9c3555e92f
in dvdnav_describe_title_chapters() init *times to NULL, so if something fails we don't leave the ptr uninited
nicodvb
parents:
313
diff
changeset
|
589 *times = NULL; |
|
315
9abc06e356ff
now dvdnav_describe_title_chapters() also returns the duration of the title
nicodvb
parents:
314
diff
changeset
|
590 *duration = 0; |
| 313 | 591 pthread_mutex_lock(&this->vm_lock); |
| 592 if(!this->vm->vmgi) { | |
| 593 printerr("Bad VM state or missing VTSI."); | |
| 594 goto fail; | |
| 595 } | |
| 596 if(!this->started) { | |
| 597 /* don't report an error but be nice */ | |
| 598 vm_start(this->vm); | |
| 599 this->started = 1; | |
| 600 } | |
| 601 ifo = vm_get_title_ifo(this->vm, title); | |
| 602 if(!ifo || !ifo->vts_pgcit) { | |
| 603 printerr("Couldn't open IFO for chosen title, exit."); | |
|
398
ec2408d48b85
in dvdnav_describe_chapters() ifo could be leaked in case of erros; fixed by Erik Hovland
nicodvb
parents:
395
diff
changeset
|
604 retval = 0; |
| 313 | 605 goto fail; |
| 606 } | |
| 388 | 607 |
| 313 | 608 ptitle = &this->vm->vmgi->tt_srpt->title[title-1]; |
| 609 parts = ptitle->nr_of_ptts; | |
| 610 ptt = ifo->vts_ptt_srpt->title[ptitle->vts_ttn-1].ptt; | |
| 388 | 611 |
| 313 | 612 tmp = calloc(1, sizeof(uint64_t)*parts); |
| 613 if(!tmp) | |
| 614 goto fail; | |
| 388 | 615 |
| 313 | 616 length = 0; |
| 617 for(i=0; i<parts; i++) { | |
| 618 uint32_t cellnr, endcellnr; | |
| 437 | 619 if (ptt[i].pgcn == 0 || ptt[i].pgcn > ifo->vts_pgcit->nr_of_pgci_srp) { |
| 620 printerr("PGCN out of bounds."); | |
| 621 continue; | |
| 622 } | |
| 426 | 623 if (ifo->vts_pgcit->pgci_srp[ptt[i].pgcn-1].pgc_start_byte >= ifo->vts_pgcit->last_byte) { |
| 624 printerr("PGC start out of bounds"); | |
| 625 continue; | |
| 626 } | |
| 313 | 627 pgc = ifo->vts_pgcit->pgci_srp[ptt[i].pgcn-1].pgc; |
|
425
323e54a7f200
Prevent segmentation faults in vdnav_describe_title_chapters()
rathann
parents:
424
diff
changeset
|
628 if (pgc == NULL) { |
|
323e54a7f200
Prevent segmentation faults in vdnav_describe_title_chapters()
rathann
parents:
424
diff
changeset
|
629 printerr("PGC missing."); |
|
323e54a7f200
Prevent segmentation faults in vdnav_describe_title_chapters()
rathann
parents:
424
diff
changeset
|
630 continue; |
|
323e54a7f200
Prevent segmentation faults in vdnav_describe_title_chapters()
rathann
parents:
424
diff
changeset
|
631 } |
| 430 | 632 if (pgc->program_map == NULL) { |
| 633 printerr("Program map missing."); | |
| 634 continue; | |
| 635 } | |
| 436 | 636 if(ptt[i].pgn == 0 || ptt[i].pgn > pgc->nr_of_programs) { |
| 313 | 637 printerr("WRONG part number."); |
| 638 goto fail; | |
| 639 } | |
| 388 | 640 |
|
427
c53e528905ec
Let dvdnav_describe_title_chapters() skip PGCs with a cell number of zero.
rathann
parents:
426
diff
changeset
|
641 if (pgc->nr_of_cells == 0) { |
|
c53e528905ec
Let dvdnav_describe_title_chapters() skip PGCs with a cell number of zero.
rathann
parents:
426
diff
changeset
|
642 printerr("Number of cells cannot be 0"); |
|
c53e528905ec
Let dvdnav_describe_title_chapters() skip PGCs with a cell number of zero.
rathann
parents:
426
diff
changeset
|
643 continue; |
|
c53e528905ec
Let dvdnav_describe_title_chapters() skip PGCs with a cell number of zero.
rathann
parents:
426
diff
changeset
|
644 } |
|
424
4219a513c804
Fix crash when trying to play a DVD from different region than currently set
rathann
parents:
417
diff
changeset
|
645 if ((cellnr = pgc->program_map[ptt[i].pgn-1]) == 0) { |
|
4219a513c804
Fix crash when trying to play a DVD from different region than currently set
rathann
parents:
417
diff
changeset
|
646 printerr("Cell new row cannot be 0"); |
|
4219a513c804
Fix crash when trying to play a DVD from different region than currently set
rathann
parents:
417
diff
changeset
|
647 continue; |
|
4219a513c804
Fix crash when trying to play a DVD from different region than currently set
rathann
parents:
417
diff
changeset
|
648 } |
|
431
fef53ca48541
Let dvdnav_describe_title_chapters() skip PGCs with missing cells.
rathann
parents:
430
diff
changeset
|
649 if (pgc->cell_playback == NULL) { |
|
fef53ca48541
Let dvdnav_describe_title_chapters() skip PGCs with missing cells.
rathann
parents:
430
diff
changeset
|
650 printerr("Cell missing"); |
|
fef53ca48541
Let dvdnav_describe_title_chapters() skip PGCs with missing cells.
rathann
parents:
430
diff
changeset
|
651 continue; |
|
fef53ca48541
Let dvdnav_describe_title_chapters() skip PGCs with missing cells.
rathann
parents:
430
diff
changeset
|
652 } |
|
424
4219a513c804
Fix crash when trying to play a DVD from different region than currently set
rathann
parents:
417
diff
changeset
|
653 |
| 313 | 654 if(ptt[i].pgn < pgc->nr_of_programs) |
| 655 endcellnr = pgc->program_map[ptt[i].pgn]; | |
| 656 else | |
| 657 endcellnr = 0; | |
| 388 | 658 |
| 313 | 659 do { |
| 660 cell = &pgc->cell_playback[cellnr-1]; | |
| 661 if(!(cell->block_type == BLOCK_TYPE_ANGLE_BLOCK && | |
| 662 cell->block_mode != BLOCK_MODE_FIRST_CELL | |
| 663 )) | |
| 664 { | |
| 665 tmp[i] = length + dvdnav_convert_time(&cell->playback_time); | |
| 666 length = tmp[i]; | |
| 667 } | |
| 668 cellnr++; | |
| 669 } while(cellnr < endcellnr); | |
| 670 } | |
|
315
9abc06e356ff
now dvdnav_describe_title_chapters() also returns the duration of the title
nicodvb
parents:
314
diff
changeset
|
671 *duration = length; |
| 313 | 672 vm_ifo_close(ifo); |
|
398
ec2408d48b85
in dvdnav_describe_chapters() ifo could be leaked in case of erros; fixed by Erik Hovland
nicodvb
parents:
395
diff
changeset
|
673 ifo = NULL; |
| 313 | 674 retval = parts; |
| 675 *times = tmp; | |
| 676 | |
| 677 fail: | |
| 678 pthread_mutex_unlock(&this->vm_lock); | |
|
398
ec2408d48b85
in dvdnav_describe_chapters() ifo could be leaked in case of erros; fixed by Erik Hovland
nicodvb
parents:
395
diff
changeset
|
679 if(!retval && ifo) |
|
ec2408d48b85
in dvdnav_describe_chapters() ifo could be leaked in case of erros; fixed by Erik Hovland
nicodvb
parents:
395
diff
changeset
|
680 vm_ifo_close(ifo); |
| 313 | 681 if(!retval && tmp) |
| 682 free(tmp); | |
| 683 return retval; | |
| 684 } |
